<commit_before>extern crate unicode_names;

use std::env;
use std::fmt;
use std::char;

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let quote : String = self.c.escape_default().collect();
        try!(write!(f, ": prints as {}", quote));
        match unicode_names::name(self.c) {
            Some(n) => {
                write!(f, "\nUnicode name: {} = {}\n",
                       self.c, n)
            },
            None => write!(f, "\n")
        }
    }
}

impl std::convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    Unicode(char)
}

impl std::convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            _ => Codepoint::Unicode(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII  {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:x}, {:}, 0x{:x}, 0{:o}, bits {:b}",
                       num, num, num, num, num)
            }
            &Codepoint::Unicode(c) => {
                let num = c as u32;
                write!(f, "UCS 4  {:x}, {:}, 0x{:x}, 0{:o}, bits {:b}",
                       num, num, num, num, num)
            }
        }
    }
}

/// Takes a stringly description of a character (the character itself,
/// or a unicode code point name) and returns either None (if the
/// character description is not understood), or Some(Describable)
/// that holds the character.
fn from_arg(spec: &str) -> Vec<Describable> {
    let mut res : Vec<Describable> = Vec::new();

    if spec.chars().count() == 1 {
        spec.chars().next().map(|c| res.push(Describable{c: c}));
    } else {
        unicode_names::character(spec).map(|c| res.push(Describable{c: c}));
    }
    for base in vec![16, 10, 8, 2] {
        let _ = u32::from_str_radix(spec, base.clone()).ok().
            map(|num| char::from_u32(num).map(|c| res.push(Describable{c: c})));
    }
    res
}

fn main() {
    let args =
        env::args().skip(1)
        .flat_map(|argument| from_arg(argument.as_ref()));
    for c in args {
        println!("{}", c);
    }
}

#[test]
fn from_arg_translates_chars() {
    assert_eq!('c', from_arg("c")[0].c);
    assert_eq!(']', from_arg("]")[0].c);
}

#[test]
fn from_arg_translates_descriptions() {
    assert_eq!('c', from_arg("latin small letter c")[0].c);
    assert_eq!(']', from_arg("right square bracket")[0].c);
}

#[test]
fn from_arg_translates_numbers() {
    let received = from_arg("60");
    let mut iter = received.iter();
    assert_eq!('`', iter.next().unwrap().c);
    assert_eq!('<', iter.next().unwrap().c);
    assert_eq!('0', iter.next().unwrap().c);
}
<commit_msg>Have a reasonable order for ambiguous codes<commit_after>extern crate unicode_names;

use std::env;
use std::fmt;
use std::char;

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let quote : String = self.c.escape_default().collect();
        try!(write!(f, ": prints as {}", quote));
        match unicode_names::name(self.c) {
            Some(n) => {
                write!(f, "\nUnicode name: {} = {}\n",
                       self.c, n)
            },
            None => write!(f, "\n")
        }
    }
}

impl std::convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    Unicode(char)
}

impl std::convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            _ => Codepoint::Unicode(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII  {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:x}, {:}, 0x{:x}, 0{:o}, bits {:b}",
                       num, num, num, num, num)
            }
            &Codepoint::Unicode(c) => {
                let num = c as u32;
                write!(f, "UCS 4  {:x}, {:}, 0x{:x}, 0{:o}, bits {:b}",
                       num, num, num, num, num)
            }
        }
    }
}

/// Takes a stringly description of a character (the character itself,
/// or a unicode code point name) and returns either None (if the
/// character description is not understood), or Some(Describable)
/// that holds the character.
fn from_arg(spec: &str) -> Vec<Describable> {
    let mut chars: Vec<char> = Vec::new();

    if spec.chars().count() == 1 {
        spec.chars().next().map(|c| chars.push(c));
    } else {
        unicode_names::character(spec).map(|c| chars.push(c));
    }
    for base in vec![16, 10, 8, 2] {
        let _ = u32::from_str_radix(spec, base.clone()).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }
    chars.sort_by(|a, b| b.cmp(a));
    chars.dedup();
    chars.iter().map(|c| c.clone().into()).collect()
}

fn main() {
    let args =
        env::args().skip(1)
        .flat_map(|argument| from_arg(argument.as_ref()));
    for c in args {
        println!("{}", c);
    }
}

#[test]
fn from_arg_translates_chars() {
    assert_eq!('n', from_arg("n")[0].c);
    assert_eq!(']', from_arg("]")[0].c);
}

#[test]
fn from_arg_translates_descriptions() {
    assert_eq!('n', from_arg("latin small letter n")[0].c);
    assert_eq!(']', from_arg("right square bracket")[0].c);
}

#[test]
fn from_arg_translates_numbers() {
    let received = from_arg("60");
    let mut iter = received.iter();
    assert_eq!('`', iter.next().unwrap().c);
    assert_eq!('<', iter.next().unwrap().c);
    assert_eq!('0', iter.next().unwrap().c);

    assert_eq!(2, from_arg("0").len());
    assert_eq!(0x30, from_arg("0").iter().next().unwrap().c as u32);
}
<|endoftext|>


<commit_before>#![recursion_limit = "128"]

extern crate ape;
extern crate app_dirs;
extern crate core;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;
#[macro_use]
extern crate error_chain;
extern crate getopts;
extern crate hyper;
extern crate id3;
extern crate image;
extern crate iron;
extern crate lewton;
extern crate metaflac;
extern crate mount;
extern crate params;
extern crate rand;
extern crate reqwest;
extern crate regex;
extern crate ring;
extern crate router;
extern crate secure_session;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate staticfile;
extern crate toml;
extern crate typemap;
extern crate url;

#[cfg(windows)]
extern crate uuid;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;
#[cfg(windows)]
extern crate shell32;
#[cfg(windows)]
extern crate user32;

#[cfg(unix)]
extern crate unix_daemonize;

#[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode};

use core::ops::Deref;
use errors::*;
use getopts::Options;
use iron::prelude::*;
use mount::Mount;
use staticfile::Static;
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;

mod api;
mod config;
mod db;
mod ddns;
mod errors;
mod index;
mod metadata;
mod playlist;
mod ui;
mod user;
mod utils;
mod thumbnails;
mod vfs;

fn main() {
	if let Err(ref e) = run() {
		println!("Error: {}", e);

		for e in e.iter().skip(1) {
			println!("caused by: {}", e);
		}
		if let Some(backtrace) = e.backtrace() {
			println!("backtrace: {:?}", backtrace);
		}
		::std::process::exit(1);
	}
}

#[cfg(unix)]
fn daemonize() -> Result<()> {
	let mut log_file = utils::get_data_root()?;
	log_file.push("polaris.log");
	match daemonize_redirect(Some(&log_file), Some(&log_file), ChdirMode::NoChdir) {
		Ok(_) => Ok(()),
		Err(_) => bail!(ErrorKind::DaemonError),
	}
}

fn run() -> Result<()> {

	// Parse CLI options
	let args: Vec<String> = std::env::args().collect();
	let mut options = Options::new();
	options.optopt("c", "config", "set the configuration file", "FILE");
	options.optopt("p", "port", "set polaris to run on a custom port", "PORT");
	options.optopt("d", "database", "set the path to index database", "FILE");
	options.optopt("w", "web", "set the path to web client files", "DIRECTORY");

	#[cfg(unix)]
	options.optflag("f",
	                "foreground",
	                "run polaris in the foreground instead of daemonizing");

	options.optflag("h", "help", "print this help menu");

	let matches = options.parse(&args[1..])?;

	if matches.opt_present("h") {
		let program = args[0].clone();
		let brief = format!("Usage: {} [options]", program);
		print!("{}", options.usage(&brief));
		return Ok(());
	}

	//attribute inside the if clause, because they are not yet allowed on `if` expressions
	if !matches.opt_present("f") {
		#[cfg(unix)]
		daemonize()?;
	}

	// Init DB
	println!("Starting up database");
	let db_path = matches.opt_str("d");
	let mut default_db_path = utils::get_data_root()?;
	default_db_path.push("db.sqlite");
	let db_path = db_path
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_db_path);
	let db = Arc::new(db::DB::new(&db_path)?);

	// Parse config
	let config_file_name = matches.opt_str("c");
	let config_file_path = config_file_name.map(|p| Path::new(p.as_str()).to_path_buf());
	if let Some(path) = config_file_path {
		let config = config::parse_toml_file(&path)?;
		config::overwrite(db.deref(), &config)?;
	}

	// Init index
	let (index_sender, index_receiver) = channel();
	let index_sender = Arc::new(Mutex::new(index_sender));
	let db_ref = db.clone();
	std::thread::spawn(move || {
		                   let db = db_ref.deref();
		                   index::update_loop(db, index_receiver);
		                  });

	// Trigger auto-indexing
	let db_ref = db.clone();
	let sender_ref = index_sender.clone();
	std::thread::spawn(move || { index::self_trigger(db_ref.deref(), sender_ref); });

	// Mount API
	println!("Mounting API");
	let mut mount = Mount::new();
	let handler = api::get_handler(db.clone(), index_sender)?;
	mount.mount("/api/", handler);

	// Mount static files
	println!("Mounting static files");
	let web_dir_name = matches.opt_str("w");
	let mut default_web_dir = utils::get_data_root()?;
	default_web_dir.push("web");
	let web_dir_path = web_dir_name
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_web_dir);

	mount.mount("/", Static::new(web_dir_path));

	println!("Starting up server");
	let port: u16 = matches
		.opt_str("p")
		.unwrap_or("5050".to_owned())
		.parse()
		.or(Err("invalid port number"))?;
	let mut server = match Iron::new(mount).http(("0.0.0.0", port)) {
		Ok(s) => s,
		Err(e) => bail!("Error starting up server: {}", e),
	};

	// Start DDNS updates
	let db_ref = db.clone();
	std::thread::spawn(move || { ddns::run(db_ref.deref()); });

	// Run UI
	ui::run();

	println!("Shutting down server");
	if let Err(e) = server.close() {
		bail!("Error shutting down server: {}", e);
	}

	Ok(())
}
<commit_msg>Fixed runtime error on windows (-f option not defined)<commit_after>#![recursion_limit = "128"]

extern crate ape;
extern crate app_dirs;
extern crate core;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;
#[macro_use]
extern crate error_chain;
extern crate getopts;
extern crate hyper;
extern crate id3;
extern crate image;
extern crate iron;
extern crate lewton;
extern crate metaflac;
extern crate mount;
extern crate params;
extern crate rand;
extern crate reqwest;
extern crate regex;
extern crate ring;
extern crate router;
extern crate secure_session;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate staticfile;
extern crate toml;
extern crate typemap;
extern crate url;

#[cfg(windows)]
extern crate uuid;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;
#[cfg(windows)]
extern crate shell32;
#[cfg(windows)]
extern crate user32;

#[cfg(unix)]
extern crate unix_daemonize;

#[cfg(unix)]
use unix_daemonize::{daemonize_redirect, ChdirMode};

use core::ops::Deref;
use errors::*;
#[cfg(unix)]
use getopts::Matches;
use getopts::Options;
use iron::prelude::*;
use mount::Mount;
use staticfile::Static;
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::channel;

mod api;
mod config;
mod db;
mod ddns;
mod errors;
mod index;
mod metadata;
mod playlist;
mod ui;
mod user;
mod utils;
mod thumbnails;
mod vfs;

fn main() {
	if let Err(ref e) = run() {
		println!("Error: {}", e);

		for e in e.iter().skip(1) {
			println!("caused by: {}", e);
		}
		if let Some(backtrace) = e.backtrace() {
			println!("backtrace: {:?}", backtrace);
		}
		::std::process::exit(1);
	}
}

 #[cfg(unix)]
fn daemonize(options : &getopts::Matches) -> Result<()> {
	if options.opt_present("f") {
		return Ok(());
	}
	let mut log_file = utils::get_data_root()?;
	log_file.push("polaris.log");
	match daemonize_redirect(Some(&log_file), Some(&log_file), ChdirMode::NoChdir) {
		Ok(_) => Ok(()),
		Err(_) => bail!(ErrorKind::DaemonError),
	}
}

fn run() -> Result<()> {

	// Parse CLI options
	let args: Vec<String> = std::env::args().collect();
	let mut options = Options::new();
	options.optopt("c", "config", "set the configuration file", "FILE");
	options.optopt("p", "port", "set polaris to run on a custom port", "PORT");
	options.optopt("d", "database", "set the path to index database", "FILE");
	options.optopt("w", "web", "set the path to web client files", "DIRECTORY");

	#[cfg(unix)]
	options.optflag("f",
	                "foreground",
	                "run polaris in the foreground instead of daemonizing");

	options.optflag("h", "help", "print this help menu");

	let matches = options.parse(&args[1..])?;

	if matches.opt_present("h") {
		let program = args[0].clone();
		let brief = format!("Usage: {} [options]", program);
		print!("{}", options.usage(&brief));
		return Ok(());
	}

	#[cfg(unix)]
	daemonize(&matches)?;

	// Init DB
	println!("Starting up database");
	let db_path = matches.opt_str("d");
	let mut default_db_path = utils::get_data_root()?;
	default_db_path.push("db.sqlite");
	let db_path = db_path
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_db_path);
	let db = Arc::new(db::DB::new(&db_path)?);

	// Parse config
	let config_file_name = matches.opt_str("c");
	let config_file_path = config_file_name.map(|p| Path::new(p.as_str()).to_path_buf());
	if let Some(path) = config_file_path {
		let config = config::parse_toml_file(&path)?;
		config::overwrite(db.deref(), &config)?;
	}

	// Init index
	let (index_sender, index_receiver) = channel();
	let index_sender = Arc::new(Mutex::new(index_sender));
	let db_ref = db.clone();
	std::thread::spawn(move || {
		                   let db = db_ref.deref();
		                   index::update_loop(db, index_receiver);
		                  });

	// Trigger auto-indexing
	let db_ref = db.clone();
	let sender_ref = index_sender.clone();
	std::thread::spawn(move || { index::self_trigger(db_ref.deref(), sender_ref); });

	// Mount API
	println!("Mounting API");
	let mut mount = Mount::new();
	let handler = api::get_handler(db.clone(), index_sender)?;
	mount.mount("/api/", handler);

	// Mount static files
	println!("Mounting static files");
	let web_dir_name = matches.opt_str("w");
	let mut default_web_dir = utils::get_data_root()?;
	default_web_dir.push("web");
	let web_dir_path = web_dir_name
		.map(|n| Path::new(n.as_str()).to_path_buf())
		.unwrap_or(default_web_dir);

	mount.mount("/", Static::new(web_dir_path));

	println!("Starting up server");
	let port: u16 = matches
		.opt_str("p")
		.unwrap_or("5050".to_owned())
		.parse()
		.or(Err("invalid port number"))?;
	let mut server = match Iron::new(mount).http(("0.0.0.0", port)) {
		Ok(s) => s,
		Err(e) => bail!("Error starting up server: {}", e),
	};

	// Start DDNS updates
	let db_ref = db.clone();
	std::thread::spawn(move || { ddns::run(db_ref.deref()); });

	// Run UI
	ui::run();

	println!("Shutting down server");
	if let Err(e) = server.close() {
		bail!("Error shutting down server: {}", e);
	}

	Ok(())
}
<|endoftext|>


<commit_before>//extern crate rand;
extern crate clap;
extern crate image;

//use std::io;
//use std::cmp::Ordering;
//use std::fs::File;
use std::path::Path;
//use rand::Rng;
use clap::{Arg, App};
use image::{DynamicImage, GenericImage, RgbaImage};

/*fn foo() {

    let secret_number = rand::thread_rng().gen_range(1, 101);

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("failed to read line");

    let guess: i32 = guess.trim().parse()
        .expect("please type a number");

    match guess.cmp(&secret_number) {
        Ordering::Equal => println!("same"),
        Ordering::Greater => println!("too big"),
        Ordering::Less => println!("too small"),
    }
}*/

fn main() {
    let matches = App::new("asami")
        //.version("1.0")
        .author("Sebastian Schulz <mail@sesc.me>")
        .about("pixel sorter")
        .arg(Arg::with_name("input")
            .short("i")
            .long("input")
            .value_name("PATH")
            .help("path to input file")
            .takes_value(true)
            .required(true))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .value_name("PATH")
            .help("path to output file")
            .takes_value(true)
            .required(true))
        /*.arg(Arg::with_name("v")
            .short("v")
            .multiple(true)
            .help("Sets the level of verbosity"))*/
        .get_matches();

    let input = matches.value_of("input").unwrap();
    let output = matches.value_of("output").unwrap();

    handle_request(input, output);

    // Vary the output based on how many times the user used the "verbose" flag
    // (i.e. 'myprog -v -v -v' or 'myprog -vvv' vs 'myprog -v'
    /*match matches.occurrences_of("v") {
        0 => println!("No verbose info"),
        1 => println!("Some verbose info"),
        2 => println!("Tons of verbose info"),
        3 | _ => println!("Don't be crazy"),
    }*/
}

fn handle_request(input: &str, output: &str) {
    println!("input: {}, output: {}", input, output);

    let ref in_img = image::open(&Path::new(input)).unwrap();

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", in_img.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", in_img.color());

    let ref mut out_img = RgbaImage::new(in_img.width(), in_img.height());

    sort_them_pixels(in_img, out_img);

    // Write the contents of this image to the Writer in PNG format.
    let _ = out_img.save(output).unwrap();
}

fn sort_them_pixels(input: &DynamicImage, output: &mut RgbaImage){
    let mut x = 0;
    let mut y = 0;

    let mut tmp = Vec::new();

    for (_, _, pixel) in input.pixels() {
        tmp.push(pixel);
        if tmp.len() > 10 {
            tmp.sort_by(|a, b| (a[1]).cmp(&b[1]));
            //tmp = Vec::new();
            while !tmp.is_empty() {
                output.put_pixel(x, y, tmp.pop().unwrap());
                y = y + (x + 1) / input.width();
                x = (x + 1) % input.width();
            }
        }
    }
}
<commit_msg>removed old comments<commit_after>//extern crate rand;
extern crate clap;
extern crate image;

use std::path::Path;
//use rand::Rng;
use clap::{Arg, App};
use image::{DynamicImage, GenericImage, RgbaImage};

fn main() {
    let matches = App::new("asami")
        //.version("1.0")
        .author("Sebastian Schulz <mail@sesc.me>")
        .about("pixel sorter")
        .arg(Arg::with_name("input")
            .short("i")
            .long("input")
            .value_name("PATH")
            .help("path to input file")
            .takes_value(true)
            .required(true))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .value_name("PATH")
            .help("path to output file")
            .takes_value(true)
            .required(true))
        /*.arg(Arg::with_name("v")
            .short("v")
            .multiple(true)
            .help("Sets the level of verbosity"))*/
        .get_matches();

    let input = matches.value_of("input").unwrap();
    let output = matches.value_of("output").unwrap();

    handle_request(input, output);

    // Vary the output based on how many times the user used the "verbose" flag
    // (i.e. 'myprog -v -v -v' or 'myprog -vvv' vs 'myprog -v'
    /*match matches.occurrences_of("v") {
        0 => println!("No verbose info"),
        1 => println!("Some verbose info"),
        2 => println!("Tons of verbose info"),
        3 | _ => println!("Don't be crazy"),
    }*/
}

fn handle_request(input: &str, output: &str) {
    println!("input: {}, output: {}", input, output);

    let ref in_img = image::open(&Path::new(input)).unwrap();

    println!("dimensions {:?}", in_img.dimensions());
    println!("{:?}", in_img.color());

    let ref mut out_img = RgbaImage::new(in_img.width(), in_img.height());

    sort_them_pixels(in_img, out_img);

    let _ = out_img.save(output).unwrap();
}

fn sort_them_pixels(input: &DynamicImage, output: &mut RgbaImage){
    let mut x = 0;
    let mut y = 0;

    let mut tmp = Vec::new();

    for (_, _, pixel) in input.pixels() {
        tmp.push(pixel);
        if tmp.len() > 10 {
            tmp.sort_by(|a, b| (a[3]).cmp(&b[1]));
            while !tmp.is_empty() {
                output.put_pixel(x, y, tmp.pop().unwrap());
                y = y + (x + 1) / input.width();
                x = (x + 1) % input.width();
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
extern crate uuid;
use uuid::Uuid;
extern crate getopts;
use getopts::Options;
use std::io;

macro_rules! exit_with_exception {
    ($error:ident, $extra:tt) => {
        let _ = write!(&mut std::io::stderr(), "{}\n", $extra);
        let _ = write!(&mut std::io::stderr(), "{}\n", $error);
        std::process::exit(-1);
    };
}

fn print_usage(program: &str, opts: Options, include_info: bool, include_copyright: bool) {
    let path = PathBuf::from(program);
    let command = path.file_name().unwrap().to_string_lossy();

    let copyright =
        "rewrite 0.2 by NeoSmart Technologies. Written by Mahmoud Al-Qudsi <mqudsi@neosmart.net>";
    let brief = format!("Usage: {} FILE [options]", command);
    let info = "Safely rewrite contents of FILE with stdin, even where FILE is being read by \
                upstream command";

    if include_copyright {
        println!("{}", copyright);
    }
    if include_info {
        println!("{}", info);
    }
    print!("{}", opts.usage(&brief));
}

fn redirect_to_file(outfile: &str) {
    // Create the temporary file in the same directory as outfile this lets us guarantee a rename
    // (instead of a move) on completion
    let mut tempfile = PathBuf::from(outfile);
    tempfile.pop(); // Now refers to parent, which might be nothing
    tempfile.push(Uuid::new_v4().hyphenated().to_string());
    // println!("{}", tempfile.display());

    {
        let mut buffer = [0; 512];
        let mut stdin = io::stdin();
        let mut f = File::create(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create temporary output file!");
        });

        loop {
            let read_bytes = stdin.read(&mut buffer).unwrap_or_else(|e| {
                exit_with_exception!(e, "Error reading from stdin!");
            });
            if read_bytes == 0 {
                break;
            }

            let write_bytes = f.write(&buffer[0..read_bytes]).unwrap_or_else(|e| {
                exit_with_exception!(e, "Failed to write to temporary output file!");
            });

            debug_assert!(write_bytes == read_bytes);
        }
    }

    std::fs::rename(&tempfile, &outfile).unwrap_or_else(|_x| {
        // fs::rename() does not support cross-device linking.
        // Copy and delete instead.
        std::fs::copy(&tempfile, &outfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create output file!");
        });
        std::fs::remove_file(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to delete temporary output file!");
        });
    });
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "prints this help info");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            println!("{}", e);
            print_usage(&program, opts, false, false);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts, true, true);
        return;
    }

    let infile = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts, true, false);
        return;
    };

    redirect_to_file(&infile);
}
<commit_msg>Use write_all() instead of asserting<commit_after>use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
extern crate uuid;
use uuid::Uuid;
extern crate getopts;
use getopts::Options;
use std::io;

macro_rules! exit_with_exception {
    ($error:ident, $extra:tt) => {
        let _ = write!(&mut std::io::stderr(), "{}\n", $extra);
        let _ = write!(&mut std::io::stderr(), "{}\n", $error);
        std::process::exit(-1);
    };
}

fn print_usage(program: &str, opts: Options, include_info: bool, include_copyright: bool) {
    let path = PathBuf::from(program);
    let command = path.file_name().unwrap().to_string_lossy();

    let copyright =
        "rewrite 0.2 by NeoSmart Technologies. Written by Mahmoud Al-Qudsi <mqudsi@neosmart.net>";
    let brief = format!("Usage: {} FILE [options]", command);
    let info = "Safely rewrite contents of FILE with stdin, even where FILE is being read by \
                upstream command";

    if include_copyright {
        println!("{}", copyright);
    }
    if include_info {
        println!("{}", info);
    }
    print!("{}", opts.usage(&brief));
}

fn redirect_to_file(outfile: &str) {
    // Create the temporary file in the same directory as outfile this lets us guarantee a rename
    // (instead of a move) on completion
    let mut tempfile = PathBuf::from(outfile);
    tempfile.pop(); // Now refers to parent, which might be nothing
    tempfile.push(Uuid::new_v4().hyphenated().to_string());
    // println!("{}", tempfile.display());

    {
        let mut buffer = [0; 512];
        let mut stdin = io::stdin();
        let mut f = File::create(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create temporary output file!");
        });

        loop {
            let read_bytes = stdin.read(&mut buffer).unwrap_or_else(|e| {
                exit_with_exception!(e, "Error reading from stdin!");
            });
            if read_bytes == 0 {
                break;
            }

            f.write_all(&buffer[0..read_bytes]).unwrap_or_else(|e| {
                exit_with_exception!(e, "Failed to write to temporary output file!");
            });
        }
    }

    std::fs::rename(&tempfile, &outfile).unwrap_or_else(|_x| {
        // fs::rename() does not support cross-device linking.
        // Copy and delete instead.
        std::fs::copy(&tempfile, &outfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to create output file!");
        });
        std::fs::remove_file(&tempfile).unwrap_or_else(|e| {
            exit_with_exception!(e, "Failed to delete temporary output file!");
        });
    });
}

fn main() {
    let args: Vec<_> = env::args().collect();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "prints this help info");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(e) => {
            println!("{}", e);
            print_usage(&program, opts, false, false);
            return;
        }
    };

    if matches.opt_present("h") {
        print_usage(&program, opts, true, true);
        return;
    }

    let infile = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts, true, false);
        return;
    };

    redirect_to_file(&infile);
}
<|endoftext|>


<commit_before>use clap::Clap;
use std::cmp::Ordering;
use std::fs::File;

fn normalize_col(col: &str) -> String {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)$").unwrap();
    }
    let mut col = RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace("(", "")
        .replace(")", "")
        .replace(" ", "_")
        .replace(".", "_")
        .replace("-", "_")
        .replace("/", "_")
        .replace("?", "")
        .replace(",", "_")
        .replace("&", "_")
        .replace(":", "")
        .replace("#", "");
    if !col.chars().next().map(char::is_alphabetic).unwrap_or(true) {
        col = format!("c_{}", col)
    }
    col
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &[String]) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&dyn rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: &str,
    delimiter: u8,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let mut num_rows = 0;
    let f = File::open(path)?;
    let file_size = f.metadata().unwrap().len();
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .delimiter(delimiter)
        .from_reader(f);

    let normalized_cols =
        reader
            .headers()?
            .iter()
            .map(normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                v
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    let pb = indicatif::ProgressBar::new(file_size);
    pb.set_style(
        indicatif::ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
            .progress_chars("#>-"),
    );
    let mut records = reader.byte_records();
    let tx = db.transaction().unwrap();
    {
        let mut stmt = tx.prepare(&insert_query).expect("tx.prepare() failed");
        while let Some(row) = records.next() {
            let mut row = row?;
            match row.len().cmp(&normalized_cols.len()) {
                Ordering::Less => {
                    for _ in 0..normalized_cols.len() - row.len() {
                        row.push_field(b"");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(rusqlite::params_from_iter(
                row.iter().map(String::from_utf8_lossy),
            ))
            .unwrap();

            num_rows += 1;
            if num_rows % 10000 == 0 {
                pb.set_position(records.reader().position().byte())
            }
        }
    }
    tx.commit().unwrap();
    pb.finish();

    println!(
        "Loaded {} rows into {}({}) from {:?}",
        num_rows,
        table_name,
        normalized_cols.join(", "),
        path,
    );
    Ok(normalized_cols)
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef<'_>,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) | rusqlite::types::ValueRef::Text(v) => {
                String::from_utf8(v.to_vec()).unwrap()
            }
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _prepare_query<'a>(
    conn: &'a mut rusqlite::Connection,
    query: &str,
) -> Result<rusqlite::Statement<'a>, String> {
    conn.prepare(query).map_err(|e| e.to_string())
}

fn _handle_query(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    let mut stmt = _prepare_query(conn, line)?;

    let mut table = comfy_table::Table::new();
    table.load_preset("││──╞═╪╡┆    ┬┴┌┐└┘");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    let mut title_row = comfy_table::Row::new();
    for col in stmt.column_names() {
        title_row.add_cell(comfy_table::Cell::new(col));
    }
    table.set_header(title_row);

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = comfy_table::Row::new();
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(comfy_table::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    println!("{}", table);
    Ok(())
}

fn _handle_export(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"^\.export\(([\w_\-\./]+)\) (.*)").unwrap();
    }
    let caps = RE
        .captures(line)
        .ok_or_else(|| "Must match `.export(file-name) SQL`".to_owned())?;
    let destination_path = &caps[1];
    let query = &caps[2];

    let mut stmt = _prepare_query(conn, query)?;

    let mut writer = csv::Writer::from_path(destination_path).map_err(|e| format!("{:?}", e))?;
    writer.write_record(stmt.column_names()).unwrap();

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        writer
            .write_record((0..r.column_count()).map(|i| {
                let cell: FromAnySqlType = r.get(i).unwrap();
                cell.value
            }))
            .unwrap();
    }

    Ok(())
}

fn _process_query(conn: &mut rusqlite::Connection, line: &str) {
    let result = if line.starts_with(".export") {
        _handle_export(conn, line)
    } else if line.starts_with(".schema") {
        _handle_query(
            conn,
            "SELECT sql AS schema FROM sqlite_master WHERE name like 't%'",
        )
    } else {
        _handle_query(conn, line)
    };
    if let Err(e) = result {
        println!("{}", e);
    }
}

fn install_udfs(c: &mut rusqlite::Connection) -> Result<(), Box<dyn std::error::Error>> {
    c.create_scalar_function(
        "regexp_extract",
        3,
        rusqlite::functions::FunctionFlags::SQLITE_UTF8
            | rusqlite::functions::FunctionFlags::SQLITE_DETERMINISTIC,
        |ctx| {
            let re = ctx.get_or_create_aux(
                0,
                |vr| -> Result<_, Box<dyn std::error::Error + Send + Sync + 'static>> {
                    Ok(regex::Regex::new(vr.as_str()?)?)
                },
            )?;
            let value = ctx.get::<Box<str>>(1)?;
            let replacement = ctx.get::<Box<str>>(2)?;

            let caps = match re.captures(&value) {
                Some(caps) => caps,
                None => return Ok("".to_string()),
            };
            let mut dest = String::new();
            caps.expand(&replacement, &mut dest);
            Ok(dest)
        },
    )?;

    Ok(())
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 5] = [b' ', b'(', b')', b',', b'.'];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        SimpleWordCompleter { words }
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    type Hint = String;

    fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
        None
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::validate::Validator for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        _ctx: &rustyline::Context<'_>,
    ) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        Ok((start, matches))
    }
}

#[derive(Clap)]
struct Opts {
    #[clap(long, about = "Use ',' as the delimiter for the CSV")]
    comma: bool,
    #[clap(long, about = "Use '|' as the delimiter for the CSV")]
    pipe: bool,
    #[clap(long, about = "Use '\\t' as the delimiter for the CSV")]
    tab: bool,
    #[clap(long, about = "Use ';' as the delimiter for the CSV")]
    semicolon: bool,

    #[clap()]
    paths: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();

    let delim = match (opts.comma, opts.pipe, opts.tab, opts.semicolon) {
        (true, false, false, false) | (false, false, false, false) => b',',
        (false, true, false, false) => b'|',
        (false, false, true, false) => b'\t',
        (false, false, false, true) => b';',
        _ => {
            eprintln!("Can't pass more than one of --comma, --pipe, and --tab");
            std::process::exit(1);
        }
    };

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = [
        // keywords
        "distinct",
        "select",
        "from",
        "group",
        "by",
        "order",
        "where",
        "count",
        "limit",
        "offset",
        // functions
        "length",
        "coalesce",
        "regexp_extract",
        // csv-sql commands
        "export",
        "schema",
    ]
    .iter()
    .map(|&s| s.to_string())
    .collect::<Vec<String>>();

    if opts.paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", &opts.paths[0], delim)?;
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in opts.paths.iter().enumerate() {
            let mut col_names =
                _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path, delim)?;
            base_words.append(&mut col_names);
        }
    }

    install_udfs(&mut conn)?;

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    let history_path = dirs::home_dir().unwrap().join(".csv-sql-history");
    let _ = rl.load_history(&history_path);
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                _process_query(&mut conn, &line);
                rl.add_history_entry(line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
    rl.save_history(&history_path).unwrap();

    Ok(())
}

#[cfg(test)]
mod test {
    use super::normalize_col;

    #[test]
    fn test_normalize_col() {
        for (value, expected) in &[
            ("", ""),
            ("abc", "abc"),
            ("(S)AO", "sao"),
            ("abc (123)", "abc"),
            ("2/6/2000", "c_2_6_2000"),
            ("COMBO#", "combo"),
        ] {
            assert_eq!(&&normalize_col(value), expected);
        }
    }
}
<commit_msg>Implement a regexp function for use with the regexp syntax (#625)<commit_after>use clap::Clap;
use std::cmp::Ordering;
use std::fs::File;

fn normalize_col(col: &str) -> String {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)$").unwrap();
    }
    let mut col = RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace("(", "")
        .replace(")", "")
        .replace(" ", "_")
        .replace(".", "_")
        .replace("-", "_")
        .replace("/", "_")
        .replace("?", "")
        .replace(",", "_")
        .replace("&", "_")
        .replace(":", "")
        .replace("#", "");
    if !col.chars().next().map(char::is_alphabetic).unwrap_or(true) {
        col = format!("c_{}", col)
    }
    col
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &[String]) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&dyn rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: &str,
    delimiter: u8,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let mut num_rows = 0;
    let f = File::open(path)?;
    let file_size = f.metadata().unwrap().len();
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .delimiter(delimiter)
        .from_reader(f);

    let normalized_cols =
        reader
            .headers()?
            .iter()
            .map(normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                v
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    let pb = indicatif::ProgressBar::new(file_size);
    pb.set_style(
        indicatif::ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
            .progress_chars("#>-"),
    );
    let mut records = reader.byte_records();
    let tx = db.transaction().unwrap();
    {
        let mut stmt = tx.prepare(&insert_query).expect("tx.prepare() failed");
        while let Some(row) = records.next() {
            let mut row = row?;
            match row.len().cmp(&normalized_cols.len()) {
                Ordering::Less => {
                    for _ in 0..normalized_cols.len() - row.len() {
                        row.push_field(b"");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(rusqlite::params_from_iter(
                row.iter().map(String::from_utf8_lossy),
            ))
            .unwrap();

            num_rows += 1;
            if num_rows % 10000 == 0 {
                pb.set_position(records.reader().position().byte())
            }
        }
    }
    tx.commit().unwrap();
    pb.finish();

    println!(
        "Loaded {} rows into {}({}) from {:?}",
        num_rows,
        table_name,
        normalized_cols.join(", "),
        path,
    );
    Ok(normalized_cols)
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef<'_>,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) | rusqlite::types::ValueRef::Text(v) => {
                String::from_utf8(v.to_vec()).unwrap()
            }
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _prepare_query<'a>(
    conn: &'a mut rusqlite::Connection,
    query: &str,
) -> Result<rusqlite::Statement<'a>, String> {
    conn.prepare(query).map_err(|e| e.to_string())
}

fn _handle_query(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    let mut stmt = _prepare_query(conn, line)?;

    let mut table = comfy_table::Table::new();
    table.load_preset("││──╞═╪╡┆    ┬┴┌┐└┘");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    let mut title_row = comfy_table::Row::new();
    for col in stmt.column_names() {
        title_row.add_cell(comfy_table::Cell::new(col));
    }
    table.set_header(title_row);

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = comfy_table::Row::new();
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(comfy_table::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    println!("{}", table);
    Ok(())
}

fn _handle_export(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"^\.export\(([\w_\-\./]+)\) (.*)").unwrap();
    }
    let caps = RE
        .captures(line)
        .ok_or_else(|| "Must match `.export(file-name) SQL`".to_owned())?;
    let destination_path = &caps[1];
    let query = &caps[2];

    let mut stmt = _prepare_query(conn, query)?;

    let mut writer = csv::Writer::from_path(destination_path).map_err(|e| format!("{:?}", e))?;
    writer.write_record(stmt.column_names()).unwrap();

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        writer
            .write_record((0..r.column_count()).map(|i| {
                let cell: FromAnySqlType = r.get(i).unwrap();
                cell.value
            }))
            .unwrap();
    }

    Ok(())
}

fn _process_query(conn: &mut rusqlite::Connection, line: &str) {
    let result = if line.starts_with(".export") {
        _handle_export(conn, line)
    } else if line.starts_with(".schema") {
        _handle_query(
            conn,
            "SELECT sql AS schema FROM sqlite_master WHERE name like 't%'",
        )
    } else {
        _handle_query(conn, line)
    };
    if let Err(e) = result {
        println!("{}", e);
    }
}

fn install_udfs(c: &mut rusqlite::Connection) -> Result<(), Box<dyn std::error::Error>> {
    c.create_scalar_function(
        "regexp_extract",
        3,
        rusqlite::functions::FunctionFlags::SQLITE_UTF8
            | rusqlite::functions::FunctionFlags::SQLITE_DETERMINISTIC,
        |ctx| {
            let re = ctx.get_or_create_aux(
                0,
                |vr| -> Result<_, Box<dyn std::error::Error + Send + Sync + 'static>> {
                    Ok(regex::Regex::new(vr.as_str()?)?)
                },
            )?;
            let value = ctx.get::<Box<str>>(1)?;
            let replacement = ctx.get::<Box<str>>(2)?;

            let caps = match re.captures(&value) {
                Some(caps) => caps,
                None => return Ok("".to_string()),
            };
            let mut dest = String::new();
            caps.expand(&replacement, &mut dest);
            Ok(dest)
        },
    )?;
    c.create_scalar_function(
        "regexp",
        2,
        rusqlite::functions::FunctionFlags::SQLITE_UTF8
            | rusqlite::functions::FunctionFlags::SQLITE_DETERMINISTIC,
        |ctx| {
            let re = ctx.get_or_create_aux(
                0,
                |vr| -> Result<_, Box<dyn std::error::Error + Send + Sync + 'static>> {
                    Ok(regex::Regex::new(vr.as_str()?)?)
                },
            )?;
            let value = ctx.get::<Box<str>>(1)?;
            Ok(re.is_match(&value))
        },
    )?;

    Ok(())
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 5] = [b' ', b'(', b')', b',', b'.'];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        SimpleWordCompleter { words }
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    type Hint = String;

    fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
        None
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::validate::Validator for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        _ctx: &rustyline::Context<'_>,
    ) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        Ok((start, matches))
    }
}

#[derive(Clap)]
struct Opts {
    #[clap(long, about = "Use ',' as the delimiter for the CSV")]
    comma: bool,
    #[clap(long, about = "Use '|' as the delimiter for the CSV")]
    pipe: bool,
    #[clap(long, about = "Use '\\t' as the delimiter for the CSV")]
    tab: bool,
    #[clap(long, about = "Use ';' as the delimiter for the CSV")]
    semicolon: bool,

    #[clap()]
    paths: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();

    let delim = match (opts.comma, opts.pipe, opts.tab, opts.semicolon) {
        (true, false, false, false) | (false, false, false, false) => b',',
        (false, true, false, false) => b'|',
        (false, false, true, false) => b'\t',
        (false, false, false, true) => b';',
        _ => {
            eprintln!("Can't pass more than one of --comma, --pipe, and --tab");
            std::process::exit(1);
        }
    };

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = [
        // keywords
        "distinct",
        "select",
        "from",
        "group",
        "by",
        "order",
        "where",
        "count",
        "limit",
        "offset",
        // functions
        "length",
        "coalesce",
        "regexp_extract",
        // csv-sql commands
        "export",
        "schema",
    ]
    .iter()
    .map(|&s| s.to_string())
    .collect::<Vec<String>>();

    if opts.paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", &opts.paths[0], delim)?;
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in opts.paths.iter().enumerate() {
            let mut col_names =
                _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path, delim)?;
            base_words.append(&mut col_names);
        }
    }

    install_udfs(&mut conn)?;

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    let history_path = dirs::home_dir().unwrap().join(".csv-sql-history");
    let _ = rl.load_history(&history_path);
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                _process_query(&mut conn, &line);
                rl.add_history_entry(line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
    rl.save_history(&history_path).unwrap();

    Ok(())
}

#[cfg(test)]
mod test {
    use super::normalize_col;

    #[test]
    fn test_normalize_col() {
        for (value, expected) in &[
            ("", ""),
            ("abc", "abc"),
            ("(S)AO", "sao"),
            ("abc (123)", "abc"),
            ("2/6/2000", "c_2_6_2000"),
            ("COMBO#", "combo"),
        ] {
            assert_eq!(&&normalize_col(value), expected);
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::io;
use std::path::Path;

extern crate clap;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate syn;
extern crate toml;

use clap::{Arg, ArgMatches, App};

mod logging;
mod bindgen;

use bindgen::{Cargo, Config, Language, Library, LibraryBuilder};

fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
    // We allow specifying a language to override the config default. This is
    // used by compile-tests.
    if let Some(lang) = matches.value_of("lang") {
        config.language = match lang {
            "C++"=> Language::Cxx,
            "c++"=> Language::Cxx,
            "C"=> Language::C,
            "c"=> Language::C,
            _ => {
                error!("unknown language specified");
                return;
            }
        };
    }

    if matches.is_present("d") {
        config.parse.parse_deps = true;
    }
}

fn load_library<'a>(input: &str, matches: &ArgMatches<'a>) -> Result<Library, String> {
    let input = Path::new(input);

    // If a file is specified then we load it as a single source
    if !input.is_dir() {
        // Load any config specified or search in the input directory
        let mut config = match matches.value_of("config") {
            Some(c) => Config::from_file(c).unwrap(),
            None => Config::from_root_or_default(input),
        };

        apply_config_overrides(&mut config, &matches);

        return LibraryBuilder::new().with_config(config)
                                    .with_std_types()
                                    .with_src(input)
                                    .build();
    }

    // We have to load a whole crate, so we use cargo to gather metadata
    let lib = Cargo::load(input,
                          matches.value_of("crate"),
                          true)?;

    // Load any config specified or search in the binding crate directory
    let mut config = match matches.value_of("config") {
        Some(c) => Config::from_file(c).unwrap(),
        None => {
            let binding_crate_dir = lib.find_crate_dir(&lib.binding_crate_ref());

            if let Some(binding_crate_dir) = binding_crate_dir {
                Config::from_root_or_default(&binding_crate_dir)
            } else {
                // This shouldn't happen
                Config::from_root_or_default(input)
            }
        }
    };

    apply_config_overrides(&mut config, &matches);

    LibraryBuilder::new().with_config(config)
                         .with_std_types()
                         .with_crate(lib)
                         .build()
}

fn main() {
    let matches = App::new("cbindgen")
                    .version(bindgen::VERSION)
                    .about("Generate C bindings for a Rust library")
                    .arg(Arg::with_name("v")
                         .short("v")
                         .multiple(true)
                         .help("Enable verbose logging"))
                    .arg(Arg::with_name("config")
                         .short("c")
                         .long("config")
                         .value_name("PATH")
                         .help("Specify path to a `cbindgen.toml` config to use"))
                    .arg(Arg::with_name("lang")
                         .short("l")
                         .long("lang")
                         .value_name("LANGUAGE")
                         .help("Specify the language to output bindings in")
                         .possible_values(&["c++", "C++", "c", "C"]))
                    .arg(Arg::with_name("d")
                         .short("d")
                         .long("parse-dependencies")
                         .help("Whether to parse dependencies when generating bindings"))
                    .arg(Arg::with_name("INPUT")
                         .help("A crate directory or source file to generate bindings for")
                         .required(true)
                         .index(1))
                    .arg(Arg::with_name("crate")
                         .long("crate")
                         .value_name("CRATE_NAME")
                         .help("If generating bindings for a crate, the specific crate to generate bindings for")
                         .required(false))
                    .arg(Arg::with_name("out")
                         .short("o")
                         .long("output")
                         .value_name("PATH")
                         .help("The file to output the bindings to")
                         .required(false))
                    .get_matches();

    // Initialize logging
    match matches.occurrences_of("v") {
        0 => logging::WarnLogger::init().unwrap(),
        1 => logging::InfoLogger::init().unwrap(),
        _ => logging::TraceLogger::init().unwrap(),
    }

    // Find the input directory
    let input = matches.value_of("INPUT").unwrap();

    let library = match load_library(input, &matches) {
        Ok(library) => library,
        Err(msg) => {
            error!("{}", msg);
            error!("couldn't generate bindings for {}", input);
            return;
        }
    };

    // Generate a bindings file
    let built = match library.generate() {
        Ok(x) => x,
        Err(msg) => {
            error!("{}", msg);
            error!("couldn't generate bindings for {}", input);
            return;
        },
    };

    // Write the bindings file
    match matches.value_of("out") {
        Some(file) => {
            built.write_to_file(file);
        }
        _ => {
            built.write(io::stdout());
        }
    }
}
<commit_msg>Use the current directory if no input is specified<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::env;
use std::io;
use std::path::{Path, PathBuf};

extern crate clap;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate syn;
extern crate toml;

use clap::{Arg, ArgMatches, App};

mod logging;
mod bindgen;

use bindgen::{Cargo, Config, Language, Library, LibraryBuilder};

fn apply_config_overrides<'a>(config: &mut Config, matches: &ArgMatches<'a>) {
    // We allow specifying a language to override the config default. This is
    // used by compile-tests.
    if let Some(lang) = matches.value_of("lang") {
        config.language = match lang {
            "C++"=> Language::Cxx,
            "c++"=> Language::Cxx,
            "C"=> Language::C,
            "c"=> Language::C,
            _ => {
                error!("unknown language specified");
                return;
            }
        };
    }

    if matches.is_present("d") {
        config.parse.parse_deps = true;
    }
}

fn load_library<'a>(input: &Path, matches: &ArgMatches<'a>) -> Result<Library, String> {
    // If a file is specified then we load it as a single source
    if !input.is_dir() {
        // Load any config specified or search in the input directory
        let mut config = match matches.value_of("config") {
            Some(c) => Config::from_file(c).unwrap(),
            None => Config::from_root_or_default(input),
        };

        apply_config_overrides(&mut config, &matches);

        return LibraryBuilder::new().with_config(config)
                                    .with_std_types()
                                    .with_src(input)
                                    .build();
    }

    // We have to load a whole crate, so we use cargo to gather metadata
    let lib = Cargo::load(input,
                          matches.value_of("crate"),
                          true)?;

    // Load any config specified or search in the binding crate directory
    let mut config = match matches.value_of("config") {
        Some(c) => Config::from_file(c).unwrap(),
        None => {
            let binding_crate_dir = lib.find_crate_dir(&lib.binding_crate_ref());

            if let Some(binding_crate_dir) = binding_crate_dir {
                Config::from_root_or_default(&binding_crate_dir)
            } else {
                // This shouldn't happen
                Config::from_root_or_default(input)
            }
        }
    };

    apply_config_overrides(&mut config, &matches);

    LibraryBuilder::new().with_config(config)
                         .with_std_types()
                         .with_crate(lib)
                         .build()
}

fn main() {
    let matches = App::new("cbindgen")
                    .version(bindgen::VERSION)
                    .about("Generate C bindings for a Rust library")
                    .arg(Arg::with_name("v")
                         .short("v")
                         .multiple(true)
                         .help("Enable verbose logging"))
                    .arg(Arg::with_name("config")
                         .short("c")
                         .long("config")
                         .value_name("PATH")
                         .help("Specify path to a `cbindgen.toml` config to use"))
                    .arg(Arg::with_name("lang")
                         .short("l")
                         .long("lang")
                         .value_name("LANGUAGE")
                         .help("Specify the language to output bindings in")
                         .possible_values(&["c++", "C++", "c", "C"]))
                    .arg(Arg::with_name("d")
                         .short("d")
                         .long("parse-dependencies")
                         .help("Whether to parse dependencies when generating bindings"))
                    .arg(Arg::with_name("INPUT")
                         .help("A crate directory or source file to generate bindings for")
                         .required(false)
                         .index(1))
                    .arg(Arg::with_name("crate")
                         .long("crate")
                         .value_name("CRATE_NAME")
                         .help("If generating bindings for a crate, the specific crate to generate bindings for")
                         .required(false))
                    .arg(Arg::with_name("out")
                         .short("o")
                         .long("output")
                         .value_name("PATH")
                         .help("The file to output the bindings to")
                         .required(false))
                    .get_matches();

    // Initialize logging
    match matches.occurrences_of("v") {
        0 => logging::WarnLogger::init().unwrap(),
        1 => logging::InfoLogger::init().unwrap(),
        _ => logging::TraceLogger::init().unwrap(),
    }

    // Find the input directory
    let input = match matches.value_of("INPUT") {
        Some(input) => PathBuf::from(input),
        None => env::current_dir().unwrap(),
    };

    let library = match load_library(&input, &matches) {
        Ok(library) => library,
        Err(msg) => {
            error!("{}", msg);
            error!("couldn't generate bindings for {}", input.display());
            return;
        }
    };

    // Generate a bindings file
    let built = match library.generate() {
        Ok(x) => x,
        Err(msg) => {
            error!("{}", msg);
            error!("couldn't generate bindings for {}", input.display());
            return;
        },
    };

    // Write the bindings file
    match matches.value_of("out") {
        Some(file) => {
            built.write_to_file(file);
        }
        _ => {
            built.write(io::stdout());
        }
    }
}
<|endoftext|>


<commit_before>#![no_main]

extern crate rustybrot_lib;
use rustybrot_lib::*;

#[no_mangle]
pub fn get_buddhabrot(array:*mut u16, size_x: usize, size_y: usize, x_min:f32, x_max:f32, y_min:f32, y_max:f32, min_iteration:u32, max_iteration: u32, num_sample: u32) -> u16 {
	let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y)
    };

    for i in image.iter_mut() {
    	*i = 0;
    }

    let mut fitted_x_min: f32 = x_min;
    let mut fitted_x_max: f32 = x_max;
    let mut fitted_y_min: f32 = y_min;
    let mut fitted_y_max: f32 = y_max;

    //let screen_ratio = size_x as f32 / size_y as f32;
    //fit_to_ratio(screen_ratio*(y_max-y_min)/(x_max-x_min), &mut fitted_x_min, &mut fitted_x_max, &mut fitted_y_min, &mut fitted_y_max).expect("failed to fit to screen ratio");

    let max = gen_buddhabrot(size_x, size_y, fitted_x_min, fitted_x_max, fitted_y_min, fitted_y_max, min_iteration, max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
    return max;
}

#[no_mangle]
pub fn get_buddhabrot_metropolis(array:*mut u16, size_x: usize, size_y: usize, x_min:f64, x_max:f64, y_min:f64, y_max:f64, min_iteration:u32, max_iteration: u32, num_sample: u32) -> u16 {
    let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y)
    };

    for i in image.iter_mut() {
        *i = 0;
    }

    let mut fitted_x_min: f64 = x_min;
    let mut fitted_x_max: f64 = x_max;
    let mut fitted_y_min: f64 = y_min;
    let mut fitted_y_max: f64 = y_max;

    //let screen_ratio = size_x as f64 / size_y as f64;
    //fit_to_ratio(screen_ratio*(y_max-y_min)/(x_max-x_min), &mut fitted_x_min, &mut fitted_x_max, &mut fitted_y_min, &mut fitted_y_max).expect("failed to fit to screen ratio");

    let max = gen_buddhabrot_metropolis(size_x, size_y, fitted_x_min, fitted_x_max, fitted_y_min, fitted_y_max, min_iteration, max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
    return max;
}

#[no_mangle]
pub fn get_buddhabrot_color(array:*mut u16, size_x: usize, size_y: usize, x_min:f32, x_max:f32, y_min:f32, y_max:f32, red_min_iteration: u32, red_max_iteration: u32, green_min_iteration: u32, green_max_iteration: u32, blue_min_iteration: u32, blue_max_iteration: u32, num_sample: u32) {
    let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y*3)
    };

    for i in image.iter_mut() {
        *i = 0;
    }

    //let screen_ratio = size_x as f64 / size_y as f64;
    //fit_to_ratio(screen_ratio*(y_max-y_min)/(x_max-x_min), &mut fitted_x_min, &mut fitted_x_max, &mut fitted_y_min, &mut fitted_y_max).expect("failed to fit to screen ratio");

    gen_buddhabrot_color(size_x, size_y, x_min, x_max, y_min, y_max, red_min_iteration, red_max_iteration, green_min_iteration, green_max_iteration, blue_min_iteration, blue_max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
}

#[no_mangle]
pub fn get_buddhabrot_metropolis_color(array:*mut u16, size_x: usize, size_y: usize, x_min:f64, x_max:f64, y_min:f64, y_max:f64, red_min_iteration: u32, red_max_iteration: u32, green_min_iteration: u32, green_max_iteration: u32, blue_min_iteration: u32, blue_max_iteration: u32, num_sample: u32) {
    let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y*3)
    };

    for i in image.iter_mut() {
        *i = 0;
    }

    //let screen_ratio = size_x as f64 / size_y as f64;
    //fit_to_ratio(screen_ratio*(y_max-y_min)/(x_max-x_min), &mut fitted_x_min, &mut fitted_x_max, &mut fitted_y_min, &mut fitted_y_max).expect("failed to fit to screen ratio");

    gen_buddhabrot_metropolis_color(size_x, size_y, x_min, x_max, y_min, y_max, red_min_iteration, red_max_iteration, green_min_iteration, green_max_iteration, blue_min_iteration, blue_max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
}

<commit_msg>Cleanup old code<commit_after>#![no_main]

extern crate rustybrot_lib;
use rustybrot_lib::*;

#[no_mangle]
pub fn get_buddhabrot(array:*mut u16, size_x: usize, size_y: usize, x_min:f32, x_max:f32, y_min:f32, y_max:f32, min_iteration:u32, max_iteration: u32, num_sample: u32) -> u16 {
	let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y)
    };

    for i in image.iter_mut() {
    	*i = 0;
    }

    let max = gen_buddhabrot(size_x, size_y, x_min, x_max, y_min, y_max, min_iteration, max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
    return max;
}

#[no_mangle]
pub fn get_buddhabrot_metropolis(array:*mut u16, size_x: usize, size_y: usize, x_min:f64, x_max:f64, y_min:f64, y_max:f64, min_iteration:u32, max_iteration: u32, num_sample: u32) -> u16 {
    let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y)
    };

    for i in image.iter_mut() {
        *i = 0;
    }

    let max = gen_buddhabrot_metropolis(size_x, size_y, x_min, x_max, y_min, y_max, min_iteration, max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
    return max;
}

#[no_mangle]
pub fn get_buddhabrot_color(array:*mut u16, size_x: usize, size_y: usize, x_min:f32, x_max:f32, y_min:f32, y_max:f32, red_min_iteration: u32, red_max_iteration: u32, green_min_iteration: u32, green_max_iteration: u32, blue_min_iteration: u32, blue_max_iteration: u32, num_sample: u32) {
    let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y*3)
    };

    for i in image.iter_mut() {
        *i = 0;
    }

    gen_buddhabrot_color(size_x, size_y, x_min, x_max, y_min, y_max, red_min_iteration, red_max_iteration, green_min_iteration, green_max_iteration, blue_min_iteration, blue_max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
}

#[no_mangle]
pub fn get_buddhabrot_metropolis_color(array:*mut u16, size_x: usize, size_y: usize, x_min:f64, x_max:f64, y_min:f64, y_max:f64, red_min_iteration: u32, red_max_iteration: u32, green_min_iteration: u32, green_max_iteration: u32, blue_min_iteration: u32, blue_max_iteration: u32, num_sample: u32) {
    let mut image = unsafe {
        std::slice::from_raw_parts_mut(array, size_x*size_y*3)
    };

    for i in image.iter_mut() {
        *i = 0;
    }

    gen_buddhabrot_metropolis_color(size_x, size_y, x_min, x_max, y_min, y_max, red_min_iteration, red_max_iteration, green_min_iteration, green_max_iteration, blue_min_iteration, blue_max_iteration, num_sample, &mut image).expect("failed to gen buddhabrot");
}

<|endoftext|>


<commit_before>use std::error::Error;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut argument_spaces = "2".to_string();
    if args.len() == 2 {
        argument_spaces = args[1].clone().to_string();
    }

    let mut argument_path = (".").to_string();
    if args.len() == 3 {
        argument_spaces = args[1].clone().to_string();
        argument_path = args[2].clone().to_string();
    }

    let file_name = "/.editorconfig";
    let full_path = argument_path + &file_name;

    let save_path = Path::new(&full_path);
    let save_path_display = save_path.display();

    let part_1 = String::from("# editorconfig.org\n\
\n\
root = true\n\
\n\
[*]\n\
end_of_line = lf\n\
charset = utf-8\n\
trim_trailing_whitespace = true\n\
insert_final_newline = true\n\
indent_style = space\n\
indent_size = ");

let part_2 = String::from("\n\
\n\
[*.md]\n\
trim_trailing_whitespace = false\n");

    let contents = part_1 + &argument_spaces + &part_2;

    let mut output_file = match File::create(&save_path) {
        Err(error) => panic!("Could not create {}: {}", save_path_display, error.description()),
        Ok(file) => file,
    };

    output_file.write_all(contents.as_bytes()).unwrap();
}
<commit_msg>Format and reduce allocations<commit_after>use std::error::Error;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::prelude::*;

fn main() {
    let args: Vec<String> = env::args().collect();

    let argument_spaces = args.get(1).map(|x| x.as_str()).unwrap_or("2");

    let argument_path = args.get(2).map(|x| x.as_str()).unwrap_or(".");

    let file_name = "/.editorconfig";
    let full_path = argument_path.to_owned() + file_name;

    let save_path = Path::new(&full_path);
    let save_path_display = save_path.display();

    let part_1 = "# editorconfig.org\n\
        \n\
        root = true\n\
        \n\
        [*]\n\
        end_of_line = lf\n\
        charset = utf-8\n\
        trim_trailing_whitespace = true\n\
        insert_final_newline = true\n\
        indent_style = space\n\
        indent_size = ";

    let part_2 = "\n\
        \n\
        [*.md]\n\
        trim_trailing_whitespace = false\n";

    let contents = part_1.to_owned() + argument_spaces + part_2;

    let mut output_file = match File::create(&save_path) {
        Err(error) => {
            panic!(
                "Could not create {}: {}",
                save_path_display,
                error.description()
            )
        }
        Ok(file) => file,
    };

    output_file.write_all(contents.as_bytes()).unwrap();
}
<|endoftext|>


<commit_before>// Worklog is for recording your hours.
//

extern crate chrono;
extern crate csv;
extern crate getopts;
extern crate rustc_serialize;

mod error;
mod timeclock;
mod util;

use error::WorklogError;
use getopts::Options;
use std::env;
use std::error::Error;
use std::fs::File;
use std::fs::OpenOptions;
use std::path::PathBuf;
use timeclock::direction::Direction;

#[cfg(target_family = "unix")]
static CSV_FILE_NAME: &'static str = ".worklog.csv";
#[cfg(target_family = "windows")]
static CSV_FILE_NAME: &'static str = "worklog.csv";

fn print_full_summary(file: &File) -> Result<u8, WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let entries = timeclock::pair_time_entries(csv_entries);
    let records = timeclock::collect_date_records(entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        total_hours += rec.hours();
        println!("{}", rec);
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(0)
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

/// Get the path for the csv data file
fn get_csv_path() -> Result<PathBuf, WorklogError> {
    let mut data_path = match env::home_dir() {
        Some(path) => path,
        None => {
            return Err(env::VarError::NotPresent).map_err(WorklogError::Env)
        }
    };

    data_path.push(CSV_FILE_NAME);
    return Ok(data_path);
}

fn main0() -> Result<i8, WorklogError> {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optflagopt("i", "in", "in time", "TIME");
    opts.optflagopt("o", "out", "out time", "TIME");
    opts.optopt("m", "memo", "the memo", "MEMO");
    opts.optflag("h", "help", "print this help menu");

    let matches = try!(opts.parse(&args[1..]));

    let csv_path = try!(get_csv_path());

    let csv_file = try!(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(csv_path));

    if matches.opt_present("h") {
        print_usage(&program, opts);

    } else if matches.opts_present(&["i".to_owned(), "o".to_owned()]) {
        // The ridiculous array above isn't my fault.

        // Reject --in and --out if present at the same time
        if matches.opt_present("i") && matches.opt_present("o") {
            println!("--in or --out, not both");
            return Ok(1);
        }

        let dir = match matches.opt_present("i") {
            true => Direction::In,
            false => Direction::Out,
        };

        let time =
            matches.opt_str("i").or(matches.opt_default("o", "now")).unwrap();
        let time = try!(util::parse_multi_time_fmt(&time));

        let memo = matches.opt_str("m").or(Some("".to_owned())).unwrap();
        timeclock::mark_time(dir, time, memo, csv_file);

        let dir_str = format!("{}", dir).to_lowercase();
        println!("Clocked {} at {}", dir_str, time.format("%F %I:%M %P"));

    } else {
        try!(print_full_summary(&csv_file));
    }

    Ok(0)
}

fn main() {
    match main0() {
        Ok(_) => {}
        Err(err) => println!("Whoops! {}", err.description()),
    };
}
<commit_msg>added print_short_summary() as default<commit_after>// Worklog is for recording your hours.
//

extern crate chrono;
extern crate csv;
extern crate getopts;
extern crate rustc_serialize;

mod error;
mod timeclock;
mod util;

use chrono::*;
use error::WorklogError;
use getopts::Options;
use std::env;
use std::error::Error;
use std::fs::File;
use std::fs::OpenOptions;
use std::path::PathBuf;
use timeclock::direction::Direction;

#[cfg(target_family = "unix")]
static CSV_FILE_NAME: &'static str = ".worklog.csv";
#[cfg(target_family = "windows")]
static CSV_FILE_NAME: &'static str = "worklog.csv";

// TODO This belongs in a config file somewhere
const WEEKSTART: i64 = Weekday::Sat as i64;

fn print_full_summary(file: &File) -> Result<u8, WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let entries = timeclock::pair_time_entries(csv_entries);
    let records = timeclock::collect_date_records(entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        total_hours += rec.hours();
        println!("{}", rec);
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(0)
}

fn print_short_summary(file: &File,
                       since: Date<FixedOffset>)
                       -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let entries = timeclock::pair_time_entries(csv_entries);
    let records = timeclock::collect_date_records(entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        if rec.date > since {
            total_hours += rec.hours();
            println!("{}", rec);
        }
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

/// Get the path for the csv data file
fn get_csv_path() -> Result<PathBuf, WorklogError> {
    let mut data_path = match env::home_dir() {
        Some(path) => path,
        None => {
            return Err(env::VarError::NotPresent).map_err(WorklogError::Env)
        }
    };

    data_path.push(CSV_FILE_NAME);
    return Ok(data_path);
}

fn main0() -> Result<i8, WorklogError> {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optflagopt("i", "in", "in time", "TIME");
    opts.optflagopt("o", "out", "out time", "TIME");
    opts.optopt("m", "memo", "the memo", "MEMO");
    opts.optflag("s", "summary", "show the full summary");
    opts.optflag("h", "help", "print this help menu");

    let matches = try!(opts.parse(&args[1..]));

    let csv_path = try!(get_csv_path());

    let csv_file = try!(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(csv_path));

    if matches.opt_present("h") {
        print_usage(&program, opts);

    } else if matches.opts_present(&["i".to_owned(), "o".to_owned()]) {
        // The ridiculous array above isn't my fault.

        // Reject --in and --out if present at the same time
        if matches.opt_present("i") && matches.opt_present("o") {
            println!("--in or --out, not both");
            return Ok(1);
        }

        let dir = match matches.opt_present("i") {
            true => Direction::In,
            false => Direction::Out,
        };

        let time =
            matches.opt_str("i").or(matches.opt_default("o", "now")).unwrap();
        let time = try!(util::parse_multi_time_fmt(&time));

        let memo = matches.opt_str("m").or(Some("".to_owned())).unwrap();
        timeclock::mark_time(dir, time, memo, csv_file);

        let dir_str = format!("{}", dir).to_lowercase();
        println!("Clocked {} at {}", dir_str, time.format("%F %I:%M %P"));

    } else if matches.opt_present("s") {
        try!(print_full_summary(&csv_file));

    } else {
        let days_back = (-WEEKSTART + 7) % 7;
        let start_date = util::now().date() - Duration::days(days_back);
        try!(print_short_summary(&csv_file, start_date));
    }

    Ok(0)
}

fn main() {
    match main0() {
        Ok(_) => {}
        Err(err) => println!("Whoops! {}", err.description()),
    };
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate nom;

#[macro_use]
extern crate enum_primitive;

extern crate num;

#[macro_use]
extern crate glium;

mod cpu;
mod display;
mod game_boy_advance;
mod gamepad;
mod instruction;
mod interconnect;
mod opcode;
mod parser;
mod utils;

mod errors {
    error_chain!{}
}
use errors::*;
quick_main!(run);

use glium::glutin::Event;
use glium::{DisplayBuild, Surface};
use interconnect::InterconnectWrite;

fn run() -> Result<()> {
    let mut gba = game_boy_advance::GameBoyAdvance::new();

    // Program courtesy of https://www.reinterpretcast.com/writing-a-game-boy-advance-game
    // Write into the I/O registers, setting video display parameters.
    let ioram_base = 0x04000000;
    // Use video mode 3 (in BG2, a 16bpp bitmap in VRAM)
    gba.interconnect.write(ioram_base, 0x03);
    // Enable BG2 (BG0 = 1, BG1 = 2, BG2 = 4, ...)
    gba.interconnect.write(ioram_base, 0x03);

    let vram_base = 0x06000000;
    gba.interconnect.write(vram_base + 80 * 240 + 115, 0b0_00000_00000_11111);
    gba.interconnect.write(vram_base + 80 * 240 + 120, 0b0_00000_11111_00000);
    gba.interconnect.write(vram_base + 80 * 240 + 125, 0b0_11111_00000_00000);

    loop {
        for ev in gba.interconnect.display.display.poll_events() {
            match ev {
                Event::KeyboardInput(key_state, _, Some(virtual_key_code)) => {
                    gba.interconnect.gamepad.update(key_state, virtual_key_code)
                }
                Event::Closed => return Ok(()),
                _ => (),
            }

            println!("Keyboard state: {:?}", gba.interconnect.gamepad);
        }
    }
}
<commit_msg>Correct memory address for vram program setup<commit_after>#[macro_use]
extern crate error_chain;

#[macro_use]
extern crate nom;

#[macro_use]
extern crate enum_primitive;

extern crate num;

#[macro_use]
extern crate glium;

mod cpu;
mod display;
mod game_boy_advance;
mod gamepad;
mod instruction;
mod interconnect;
mod opcode;
mod parser;
mod utils;

mod errors {
    error_chain!{}
}
use errors::*;
quick_main!(run);

use glium::glutin::Event;
use glium::{DisplayBuild, Surface};
use interconnect::InterconnectWrite;

fn run() -> Result<()> {
    let mut gba = game_boy_advance::GameBoyAdvance::new();

    // Program courtesy of https://www.reinterpretcast.com/writing-a-game-boy-advance-game
    // Write into the I/O registers, setting video display parameters.
    let ioram_base = 0x04000000;
    // Use video mode 3 (in BG2, a 16bpp bitmap in VRAM)
    gba.interconnect.write(ioram_base, 0x03);
    // Enable BG2 (BG0 = 1, BG1 = 2, BG2 = 4, ...)
    gba.interconnect.write(ioram_base + 1, 0x03);

    let vram_base = 0x06000000;
    gba.interconnect.write(vram_base + 80 * 240 + 115, 0b0_00000_00000_11111);
    gba.interconnect.write(vram_base + 80 * 240 + 120, 0b0_00000_11111_00000);
    gba.interconnect.write(vram_base + 80 * 240 + 125, 0b0_11111_00000_00000);

    loop {
        for ev in gba.interconnect.display.display.poll_events() {
            match ev {
                Event::KeyboardInput(key_state, _, Some(virtual_key_code)) => {
                    gba.interconnect.gamepad.update(key_state, virtual_key_code)
                }
                Event::Closed => return Ok(()),
                _ => (),
            }

            println!("Keyboard state: {:?}", gba.interconnect.gamepad);
        }
    }
}
<|endoftext|>


<commit_before>
extern crate love2d;
use love2d::{Window, Event};
use love2d::{ElementState, VirtualKeyCode};

use std::collections::HashMap;

fn main() {
    let mut app = Window::new("Hello World", 640, 480);
    let mut keymap: HashMap<VirtualKeyCode, bool> = HashMap::new();

    'main: loop {
        {
            let mut frame = app.next_frame();
            frame.clear();

            // let delta = frame.delta();

            frame.set_color_html("312");
            frame.draw_rect((-0.5, -0.5), (0.5, 0.5));

            frame.set_color_html("#033112");
            frame.draw_rect((0.0, 0.0), (-1.0, -1.0));

            frame.set_color(1.0, 0.0, 0.0, 1.0);
            frame.draw_line(0.0, 0.0, 1.0, 1.0);

            frame.set_color(0.0, 0.0, 1.0, 0.3);
            frame.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

            frame.set_color(0.0, 1.0, 0.0, 0.3);
            frame.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

            frame.set_color(1.0, 0.0, 0.0, 0.3);
            frame.draw_circle(0.25, -0.25, 0.75, 0.25, 10);

            frame.finish();
        }

        for ev in app.poll_events() {
            match ev {
                Event::Closed => break 'main,
                Event::KeyboardInput(ElementState::Pressed, Some(key)) => {
                    match key {
                        VirtualKeyCode::Space => println!("Space!"),
                        VirtualKeyCode::Escape => break 'main,
                        _ => (),
                    };
                    keymap.insert(key, true);
                }
                Event::KeyboardInput(ElementState::Released, Some(key)) => {
                    keymap.insert(key, false);
                }
                _ => (),
            }
        }
    }
}
<commit_msg>Added use * to simplify event match block<commit_after>
extern crate love2d;
use love2d::{Window, Event};
use love2d::{ElementState, VirtualKeyCode};

use std::collections::HashMap;

fn main() {
    let mut app = Window::new("Hello World", 640, 480);
    let mut keymap: HashMap<VirtualKeyCode, bool> = HashMap::new();

    'main: loop {
        {
            let mut frame = app.next_frame();
            frame.clear();

            // let delta = frame.delta();

            frame.set_color_html("312");
            frame.draw_rect((-0.5, -0.5), (0.5, 0.5));

            frame.set_color_html("#033112");
            frame.draw_rect((0.0, 0.0), (-1.0, -1.0));

            frame.set_color(1.0, 0.0, 0.0, 1.0);
            frame.draw_line(0.0, 0.0, 1.0, 1.0);

            frame.set_color(0.0, 0.0, 1.0, 0.3);
            frame.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

            frame.set_color(0.0, 1.0, 0.0, 0.3);
            frame.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

            frame.set_color(1.0, 0.0, 0.0, 0.3);
            frame.draw_circle(0.25, -0.25, 0.75, 0.25, 10);

            frame.finish();
        }

        for ev in app.poll_events() {
            use Event::*;
            use VirtualKeyCode::*;
            match ev {
                Closed => break 'main,
                KeyboardInput(ElementState::Pressed, Some(key)) => {
                    match key {
                        Space => println!("Space!"),
                        Escape => break 'main,
                        _ => (),
                    };
                    keymap.insert(key, true);
                }
                KeyboardInput(ElementState::Released, Some(key)) => {
                    keymap.insert(key, false);
                }
                _ => (),
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Muxed. A tmux project manager with no runtime dependencies.
extern crate clap;
extern crate libc;
extern crate yaml_rust;
#[cfg(test)] extern crate rand;

mod tmux;
mod command;
mod project;

use project::parser;
use project::processor;
use clap::{Arg, App};
use command::Command;

#[macro_export]
macro_rules! try_or_err (
    ($expr: expr) => ({
        match $expr {
            Ok(val) => val,
            Err(e) => {
              println!("Muxed ran in to a problem:");
              println!("{}", e);
              return
            }
        }
    })
);

/// The main execution method.
/// Currently accepts a single option. The option represents a configuration
/// file in the same naming format. Given a project file name `projectName.yml`
/// in the `~/.muxed/` directory.
///
/// # Examples
///
/// ~/.muxed/projectName.yml
///
/// ```
/// root: ~/projects/muxed/
/// windows:
///     - cargo: "cargo build"
///     - vim: "vim ."
///     - git: ""
/// ```
///
/// You can run the command:
///
/// ```
/// $ ./muxed projectName
/// ```
pub fn main() {
    let matches = App::new("Muxed")
                          .version(env!("CARGO_PKG_VERSION"))
                          .author("Brian Pearce")
                          .about("Another TMUX project manager")
                          .arg(Arg::with_name("PROJECT_NAME")
                               .help("The name of your poject to open")
                               .required(true)
                               .index(1))
                          .arg(Arg::with_name("daemonize")
                               .short("d")
                               .multiple(false)
                               .help("If you want to create a muxed session without connecting to it"))
                          .arg(Arg::with_name("PROJECT_DIR")
                               .short("-p")
                               .multiple(false)
                               .value_name("PROJECT_DIR")
                               .takes_value(true)
                               .help("The directory your project config files live in. Defaults to ~/.muxed/"))
                          //.subcommand(SubCommand::with_name("new")
                          //            .about("Create a new project file"))
                          //.subcommand(SubCommand::with_name("edit")
                          //            .about("Edit a project file"))
                          .get_matches();

    let project_name = matches.value_of("PROJECT_NAME").unwrap().to_string();
    let daemonize = matches.is_present("daemonize");
    let muxed_dir = matches.value_of("PROJECT_DIR");

    let commands: Vec<Command>;
    // This refactoring could make a good conference talk example
    match project::session_exists(&project_name) {
        Some(c) => {
            commands = vec!(c);
        },
        None => {
            let yaml = try_or_err!(project::read(&project_name, &muxed_dir));
            commands = try_or_err!(parser::main(&yaml, &project_name, daemonize));
        }
    };

    processor::main(&commands)
}
<commit_msg>issue-5 First pass at external sub command.<commit_after>//! Muxed. A tmux project manager with no runtime dependencies.
extern crate clap;
extern crate libc;
extern crate yaml_rust;
#[cfg(test)] extern crate rand;

mod tmux;
mod command;
mod project;

use project::parser;
use project::processor;
use clap::{Arg, App, SubCommand, AppSettings};
use command::Command;
use std::process;

#[macro_export]
macro_rules! try_or_err (
    ($expr: expr) => ({
        match $expr {
            Ok(val) => val,
            Err(e) => {
              println!("Muxed ran in to a problem:");
              println!("{}", e);
              return
            }
        }
    })
);

/// The main execution method.
/// Currently accepts a single option. The option represents a configuration
/// file in the same naming format. Given a project file name `projectName.yml`
/// in the `~/.muxed/` directory.
///
/// # Examples
///
/// ~/.muxed/projectName.yml
///
/// ```
/// root: ~/projects/muxed/
/// windows:
///     - cargo: "cargo build"
///     - vim: "vim ."
///     - git: ""
/// ```
///
/// You can run the command:
///
/// ```
/// $ ./muxed projectName
/// ```
pub fn main() {
    let matches = App::new("Muxed")
                          .version(env!("CARGO_PKG_VERSION"))
                          .author("Brian Pearce")
                          .about("Another TMUX project manager")
                          .setting(AppSettings::SubcommandsNegateReqs)
                          .arg(Arg::with_name("PROJECT_NAME")
                               .help("The name of your poject to open")
                               .index(1)
                               .required(true)
                               .takes_value(true))
                          .arg(Arg::with_name("daemonize")
                               .short("d")
                               .multiple(false)
                               .help("If you want to create a muxed session without connecting to it"))
                          .arg(Arg::with_name("PROJECT_DIR")
                               .short("-p")
                               .multiple(false)
                               .value_name("PROJECT_DIR")
                               .takes_value(true)
                               .help("The directory your project config files live in. Defaults to ~/.muxed/"))
                          .subcommand(SubCommand::with_name("new")
                                      .about("Create a new project file")
                                      .arg(Arg::with_name("NEW_PROJECT_NAME")
                                          .help("The new project/file name")
                                          .required(true))
                                      .arg(Arg::with_name("PROJECT_DIR")
                                          .short("-p")
                                          .multiple(false)
                                          .takes_value(true)
                                          .help("The directory your project config files live in. Defaults to ~/.muxed/")))
                          .get_matches();

    if let Some(matches) = matches.subcommand_matches("new") {
        if matches.is_present("NEW_PROJECT_NAME") {
            let project_name = matches.value_of("NEW_PROJECT_NAME").unwrap().to_string();

            let mut output = process::Command::new("muxednew").arg(project_name);

            if matches.is_present("PROJECT_DIR") {
                output.arg("-p")
                      .arg(matches.value_of("PROJECT_DIR").unwrap());
            }

            output = try_or_err!(output.output().map_err(|_| "Muxednew might not be installed." ));

            if !output.status.success() {
                println!("{}", String::from_utf8_lossy(&output.stdout));
            };
        };

        return
    };

    let project_name = matches.value_of("PROJECT_NAME").unwrap().to_string();
    let daemonize = matches.is_present("daemonize");
    let muxed_dir = matches.value_of("PROJECT_DIR");

    let commands: Vec<Command>;
    // This refactoring could make a good conference talk example
    match project::session_exists(&project_name) {
        Some(c) => {
            commands = vec!(c);
        },
        None => {
            let yaml = try_or_err!(project::read(&project_name, &muxed_dir));
            commands = try_or_err!(parser::main(&yaml, &project_name, daemonize));
        }
    };

    processor::main(&commands)
}
<|endoftext|>