<commit_before>#![allow(unknown_lints)]
extern crate errno;
extern crate exec;
extern crate glob;
extern crate libc;
extern crate linefeed;
extern crate nix;
extern crate os_type;
extern crate regex;
extern crate sqlite;
extern crate time;
extern crate yaml_rust;
#[macro_use]
extern crate nom;

use std::env;
use std::rc::Rc;
use linefeed::Command;
use linefeed::{Reader, ReadResult};

#[macro_use]
mod tools;
mod binds;
mod builtins;
mod completers;
mod execute;
mod libs;
mod parsers;
mod history;
mod rcfile;
mod shell;

use tools::clog;

fn main() {
    let mut sh = shell::Shell::new();
    rcfile::load_rcfile(&mut sh);

    // this section handles `cicada -c 'echo hi && echo yoo'`,
    // e.g. it could be triggered from Vim (`:!ls` etc).
    if env::args().len() > 1 {
        let line = tools::env_args_to_command_line();
        log!("run with -c args: {}", &line);
        execute::run_procs(&mut sh, &line, false);
        return;
    }

    let isatty: bool = unsafe { libc::isatty(0) == 1 };
    if !isatty {
        // cases like open a new MacVim window,
        // (i.e. CMD+N) on an existing one
        execute::handle_non_tty(&mut sh);
        return;
    }

    let mut rl;
    match Reader::new("cicada") {
        Ok(x) => rl = x,
        Err(e) => {
            // non-tty will raise errors here
            println!("Reader Error: {:?}", e);
            return;
        }
    }
    history::init(&mut rl);
    rl.set_completer(Rc::new(completers::CicadaCompleter));

    rl.define_function("up-key-function", Rc::new(binds::UpKeyFunction));
    rl.bind_sequence(binds::SEQ_UP_KEY, Command::from_str("up-key-function"));
    rl.define_function("down-key-function", Rc::new(binds::DownKeyFunction));
    rl.bind_sequence(binds::SEQ_DOWN_KEY, Command::from_str("down-key-function"));

    let mut status = 0;
    loop {
        let prompt = libs::prompt::get_prompt(status);
        rl.set_prompt(&prompt);
        match rl.read_line() {
            Ok(ReadResult::Input(line)) => {
                let cmd;
                if line.trim() == "exit" {
                    break;
                } else if line.trim() == "" {
                    continue;
                } else {
                    cmd = line.clone();
                }

                let tsb_spec = time::get_time();
                let tsb = (tsb_spec.sec as f64) + tsb_spec.nsec as f64 / 1000000000.0;
                status = execute::run_procs(&mut sh, &cmd, true);
                let tse_spec = time::get_time();
                let tse = (tse_spec.sec as f64) + tse_spec.nsec as f64 / 1000000000.0;
                sh.previous_status = status;
                history::add(&mut sh, &mut rl, &line, status, tsb, tse);
            }
            Ok(ReadResult::Eof) => {
                println!("");
                continue;
            }
            Ok(ReadResult::Signal(s)) => {
                println!("readline signal: {:?}", s);
            }
            Err(e) => {
                println!("readline error: {:?}", e);
            }
        }
    }
}
<commit_msg>exit on Ctrl+D, like bash<commit_after>#![allow(unknown_lints)]
extern crate errno;
extern crate exec;
extern crate glob;
extern crate libc;
extern crate linefeed;
extern crate nix;
extern crate os_type;
extern crate regex;
extern crate sqlite;
extern crate time;
extern crate yaml_rust;
#[macro_use]
extern crate nom;

use std::env;
use std::rc::Rc;
use linefeed::Command;
use linefeed::{Reader, ReadResult};

#[macro_use]
mod tools;
mod binds;
mod builtins;
mod completers;
mod execute;
mod libs;
mod parsers;
mod history;
mod rcfile;
mod shell;

use tools::clog;

fn main() {
    let mut sh = shell::Shell::new();
    rcfile::load_rcfile(&mut sh);

    // this section handles `cicada -c 'echo hi && echo yoo'`,
    // e.g. it could be triggered from Vim (`:!ls` etc).
    if env::args().len() > 1 {
        let line = tools::env_args_to_command_line();
        log!("run with -c args: {}", &line);
        execute::run_procs(&mut sh, &line, false);
        return;
    }

    let isatty: bool = unsafe { libc::isatty(0) == 1 };
    if !isatty {
        // cases like open a new MacVim window,
        // (i.e. CMD+N) on an existing one
        execute::handle_non_tty(&mut sh);
        return;
    }

    let mut rl;
    match Reader::new("cicada") {
        Ok(x) => rl = x,
        Err(e) => {
            // non-tty will raise errors here
            println!("Reader Error: {:?}", e);
            return;
        }
    }
    history::init(&mut rl);
    rl.set_completer(Rc::new(completers::CicadaCompleter));

    rl.define_function("up-key-function", Rc::new(binds::UpKeyFunction));
    rl.bind_sequence(binds::SEQ_UP_KEY, Command::from_str("up-key-function"));
    rl.define_function("down-key-function", Rc::new(binds::DownKeyFunction));
    rl.bind_sequence(binds::SEQ_DOWN_KEY, Command::from_str("down-key-function"));

    let mut status = 0;
    loop {
        let prompt = libs::prompt::get_prompt(status);
        rl.set_prompt(&prompt);
        match rl.read_line() {
            Ok(ReadResult::Input(line)) => {
                let cmd;
                if line.trim() == "exit" {
                    break;
                } else if line.trim() == "" {
                    continue;
                } else {
                    cmd = line.clone();
                }

                let tsb_spec = time::get_time();
                let tsb = (tsb_spec.sec as f64) + tsb_spec.nsec as f64 / 1000000000.0;
                status = execute::run_procs(&mut sh, &cmd, true);
                let tse_spec = time::get_time();
                let tse = (tse_spec.sec as f64) + tse_spec.nsec as f64 / 1000000000.0;
                sh.previous_status = status;
                history::add(&mut sh, &mut rl, &line, status, tsb, tse);
            }
            Ok(ReadResult::Eof) => {
                println!("exit");
                break;
            }
            Ok(ReadResult::Signal(s)) => {
                println!("readline signal: {:?}", s);
            }
            Err(e) => {
                println!("readline error: {:?}", e);
            }
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

mod lib;

use clap::{App, Arg};
use lib::Petnames;
use std::str::FromStr;

fn main() {
    let matches = App::new("rust-petname")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generate human readable random names.")
        .after_help(concat!(
            "Based on Dustin Kirkland's petname project ",
            "<https://github.com/dustinkirkland/petname>."
        ))
        .arg(
            Arg::with_name("words")
                .short("w")
                .long("words")
                .value_name("WORDS")
                .default_value("2")
                .help("Number of words in name")
                .takes_value(true)
                .validator(can_be_parsed::<u8>),
        )
        .arg(
            Arg::with_name("separator")
                .short("s")
                .long("separator")
                .value_name("SEP")
                .default_value("-")
                .help("Separator between words")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("complexity")
                .short("c")
                .long("complexity")
                .value_name("COMPLEXITY")
                .possible_values(&["0", "1", "2"])
                .hide_possible_values(true)
                .default_value("0")
                .help("Use small words (0), medium words (1), or large words (2)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("count")
                .long("count")
                .value_name("COUNT")
                .default_value("1")
                .help("Generate multiple names. Set to 0 to produce infinite names!")
                .takes_value(true)
                .validator(can_be_parsed::<u64>),
        )
        .get_matches();

    // Unwrapping is safe because these options have defaults.
    let opt_separator = matches.value_of("separator").unwrap();
    let opt_words = matches.value_of("words").unwrap();
    let opt_complexity = matches.value_of("complexity").unwrap();
    let opt_count = matches.value_of("count").unwrap();

    // Parse words and count into numbers. Validated so unwrapping is okay.
    let opt_words: u8 = opt_words.parse().unwrap();
    let opt_count: u64 = opt_count.parse().unwrap();

    // Select the appropriate word list.
    let petnames = match opt_complexity {
        "0" => Petnames::small(),
        "1" => Petnames::medium(),
        "2" => Petnames::large(),
        _ => Petnames::small(),
    };

    // We're going to need a source of randomness.
    let mut rng = rand::thread_rng();

    // Stream if count is 0.
    if opt_count == 0 {
        loop {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    } else {
        for _ in 1..=opt_count {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    }
}

fn can_be_parsed<INTO>(value: String) -> Result<(), String>
where
    INTO: FromStr,
    <INTO as FromStr>::Err: std::fmt::Display,
{
    match value.parse::<INTO>() {
        Err(e) => Err(format!("{}", e)),
        Ok(_) => Ok(()),
    }
}
<commit_msg>Shorten the metavar for complexity option to make --help narrower.<commit_after>#[macro_use]
extern crate clap;

mod lib;

use clap::{App, Arg};
use lib::Petnames;
use std::str::FromStr;

fn main() {
    let matches = App::new("rust-petname")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generate human readable random names.")
        .after_help(concat!(
            "Based on Dustin Kirkland's petname project ",
            "<https://github.com/dustinkirkland/petname>."
        ))
        .arg(
            Arg::with_name("words")
                .short("w")
                .long("words")
                .value_name("WORDS")
                .default_value("2")
                .help("Number of words in name")
                .takes_value(true)
                .validator(can_be_parsed::<u8>),
        )
        .arg(
            Arg::with_name("separator")
                .short("s")
                .long("separator")
                .value_name("SEP")
                .default_value("-")
                .help("Separator between words")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("complexity")
                .short("c")
                .long("complexity")
                .value_name("COM")
                .possible_values(&["0", "1", "2"])
                .hide_possible_values(true)
                .default_value("0")
                .help("Use small words (0), medium words (1), or large words (2)")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("count")
                .long("count")
                .value_name("COUNT")
                .default_value("1")
                .help("Generate multiple names. Set to 0 to produce infinite names!")
                .takes_value(true)
                .validator(can_be_parsed::<u64>),
        )
        .get_matches();

    // Unwrapping is safe because these options have defaults.
    let opt_separator = matches.value_of("separator").unwrap();
    let opt_words = matches.value_of("words").unwrap();
    let opt_complexity = matches.value_of("complexity").unwrap();
    let opt_count = matches.value_of("count").unwrap();

    // Parse words and count into numbers. Validated so unwrapping is okay.
    let opt_words: u8 = opt_words.parse().unwrap();
    let opt_count: u64 = opt_count.parse().unwrap();

    // Select the appropriate word list.
    let petnames = match opt_complexity {
        "0" => Petnames::small(),
        "1" => Petnames::medium(),
        "2" => Petnames::large(),
        _ => Petnames::small(),
    };

    // We're going to need a source of randomness.
    let mut rng = rand::thread_rng();

    // Stream if count is 0.
    if opt_count == 0 {
        loop {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    } else {
        for _ in 1..=opt_count {
            let petname = petnames.generate(&mut rng, opt_words, opt_separator);
            println!("{}", petname);
        }
    }
}

fn can_be_parsed<INTO>(value: String) -> Result<(), String>
where
    INTO: FromStr,
    <INTO as FromStr>::Err: std::fmt::Display,
{
    match value.parse::<INTO>() {
        Err(e) => Err(format!("{}", e)),
        Ok(_) => Ok(()),
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy_pedantic))]
#![cfg_attr(feature="clippy", allow(missing_docs_in_private_items))]

#![deny(missing_debug_implementations, missing_copy_implementations,
    trivial_casts, trivial_numeric_casts, unsafe_code,
    unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate clap;
extern crate reqwest;
extern crate crypto;
extern crate url;
extern crate uuid;
extern crate rustc_serialize as serialize;
extern crate bytes;
extern crate pbr;
#[macro_use]
extern crate lazy_static;

mod auth_helper;
mod file_helper;
mod request_helper;
mod ui_helper;

use clap::App;
use reqwest::Url;
use reqwest::header::{AcceptRanges, ContentLength, RangeUnit};
use std::{process, thread};
use std::ops::Deref;
use std::path::Path;
use std::sync::Mutex;
use std::time::Duration;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

lazy_static! {
    static ref CURRENTLY_RUNNING_THREADS: Mutex<usize> = Mutex::new(0);
    static ref HAS_FAILED: Mutex<bool> = Mutex::new(false);
}

fn main() {
    let yaml = load_yaml!("cli.yml");
    let m = App::from_yaml(yaml)
        .version(VERSION)
        .get_matches();

    #[cfg_attr(feature="clippy", allow(option_unwrap_used))]
    let raw_uri = m.value_of("uri").unwrap(); // Unwrap is safe - required by clap
    let url = match Url::parse(raw_uri) {
        Ok(uri) => uri,
        Err(e) => panic!("Couldn't parse URI: {}", e),
    };

    let file_name = request_helper::get_last_url_segment(url.clone());

    if Path::new(&file_name).exists() {
        println!("{} already exists, please remove it and try again.",
                 file_name);
        process::exit(1);
    }

    let thread_count = m.value_of("thread_count")
        .map(|tc| tc.parse::<usize>().expect("Failed to parse thread count."))
        .unwrap_or(10);
    let part_count = m.value_of("part_count")
        .map(|tc| tc.parse::<usize>().expect("Failed to parse part count."))
        .unwrap_or(thread_count);
    let part_count_u64 = part_count as u64;

    if part_count < thread_count {
        panic!("Part count too low, must be at least the thread count.");
    }

    if thread_count > 20 {
        panic!("Thread count too high, please select between 2 and 20 threads.");
    } else if thread_count < 2 {
        panic!("Thread count too low, please select between 2 and 20 threads.");
    }

    let res = request_helper::head_request(url.clone());
    let headers = res.headers();
    if !headers.get::<AcceptRanges>().map_or(false, |range_header| {
        range_header.deref().contains(&RangeUnit::Bytes)
    }) {
        panic!("Requested resource does not allow Range requests!")
    }

    let content_length = headers.get::<ContentLength>()
        .map_or(0, |length_header| *length_header.deref());

    if content_length < 1024 {
        panic!("Content too small");
    }

    let part_length = (content_length / part_count_u64) / file_helper::CHUNK_SIZE_U64 *
                      file_helper::CHUNK_SIZE_U64;

    let mut sections: Vec<(u64, u64)> = vec![];
    let mut lengths: Vec<u64> = vec![];
    for section in 0..(part_count_u64 - 1) {
        sections.push((section * part_length, (section + 1) * part_length - 1));
        lengths.push(part_length);
    }
    sections.push(((part_count_u64 - 1) * part_length, content_length));
    lengths.push(content_length - (part_count_u64 - 1) * part_length);

    ui_helper::start_pbr(file_name.clone(), lengths);

    let footer_space = file_helper::create_file(file_name.clone(), content_length);
    let mut children = vec![];
    for child_id in 0..part_count {
        let section = sections[child_id];
        let url_clone = url.clone();
        let file_name_clone = file_name.clone();
        loop {
            {
                let mut currently_running = CURRENTLY_RUNNING_THREADS.lock()
                    .expect("Failed to aquire CURRENTLY_RUNNING_THREADS lock, lock poisoned!");
                if *currently_running < thread_count {
                    *currently_running += 1;
                    break;
                }
            }
            thread::sleep(Duration::new(1, 0));
        }
        let child = thread::spawn(move || {
            ui_helper::setting_up_bar(child_id);
            let start =
                file_helper::get_first_empty_chunk(file_name_clone.clone(), footer_space, section);
            if start <= section.1 {
                let prefilled = start - section.0;
                let section = (start, section.1);
                let range_req = request_helper::get_range_request(url_clone.clone(), section);
                ui_helper::start_bar(child_id);
                let written = file_helper::save_response(file_name_clone.clone(),
                                                         range_req,
                                                         footer_space,
                                                         child_id,
                                                         prefilled)
                    .unwrap();
                if written > 0 {
                    ui_helper::success_bar(child_id);
                } else {
                    ui_helper::fail_bar(child_id);
                    let mut failed = HAS_FAILED.lock()
                        .expect("Failed to aquire HAS_FAILED lock, lock poisoned!");
                    *failed = true;
                }
            } else {
                ui_helper::success_bar(child_id);
            }

            let mut currently_running = CURRENTLY_RUNNING_THREADS.lock()
                .expect("Failed to aquire CURRENTLY_RUNNING_THREADS lock, lock poisoned!");
            *currently_running -= 1;
        });
        children.push(child);
    }
    for child in children {
        let _ = child.join();
    }

    if *HAS_FAILED.lock().expect("Failed to aquire HAS_FAILED lock, lock poisoned!") {
        println!("Some parts failed to download, please rerun.");
        process::exit(1);
    } else {
        file_helper::remove_footer_and_save(file_name, content_length);
    }
}
<commit_msg>Don't attempt to download byte at content length, it doesn't exist (0 indexed)<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy_pedantic))]
#![cfg_attr(feature="clippy", allow(missing_docs_in_private_items))]

#![deny(missing_debug_implementations, missing_copy_implementations,
    trivial_casts, trivial_numeric_casts, unsafe_code,
    unused_import_braces, unused_qualifications)]

#[macro_use]
extern crate clap;
extern crate reqwest;
extern crate crypto;
extern crate url;
extern crate uuid;
extern crate rustc_serialize as serialize;
extern crate bytes;
extern crate pbr;
#[macro_use]
extern crate lazy_static;

mod auth_helper;
mod file_helper;
mod request_helper;
mod ui_helper;

use clap::App;
use reqwest::Url;
use reqwest::header::{AcceptRanges, ContentLength, RangeUnit};
use std::{process, thread};
use std::ops::Deref;
use std::path::Path;
use std::sync::Mutex;
use std::time::Duration;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

lazy_static! {
    static ref CURRENTLY_RUNNING_THREADS: Mutex<usize> = Mutex::new(0);
    static ref HAS_FAILED: Mutex<bool> = Mutex::new(false);
}

fn main() {
    let yaml = load_yaml!("cli.yml");
    let m = App::from_yaml(yaml)
        .version(VERSION)
        .get_matches();

    #[cfg_attr(feature="clippy", allow(option_unwrap_used))]
    let raw_uri = m.value_of("uri").unwrap(); // Unwrap is safe - required by clap
    let url = match Url::parse(raw_uri) {
        Ok(uri) => uri,
        Err(e) => panic!("Couldn't parse URI: {}", e),
    };

    let file_name = request_helper::get_last_url_segment(url.clone());

    if Path::new(&file_name).exists() {
        println!("{} already exists, please remove it and try again.",
                 file_name);
        process::exit(1);
    }

    let thread_count = m.value_of("thread_count")
        .map(|tc| tc.parse::<usize>().expect("Failed to parse thread count."))
        .unwrap_or(10);
    let part_count = m.value_of("part_count")
        .map(|tc| tc.parse::<usize>().expect("Failed to parse part count."))
        .unwrap_or(thread_count);
    let part_count_u64 = part_count as u64;

    if part_count < thread_count {
        panic!("Part count too low, must be at least the thread count.");
    }

    if thread_count > 20 {
        panic!("Thread count too high, please select between 2 and 20 threads.");
    } else if thread_count < 2 {
        panic!("Thread count too low, please select between 2 and 20 threads.");
    }

    let res = request_helper::head_request(url.clone());
    let headers = res.headers();
    if !headers.get::<AcceptRanges>().map_or(false, |range_header| {
        range_header.deref().contains(&RangeUnit::Bytes)
    }) {
        panic!("Requested resource does not allow Range requests!")
    }

    let content_length = headers.get::<ContentLength>()
        .map_or(0, |length_header| *length_header.deref());

    if content_length < 1024 {
        panic!("Content too small");
    }

    let part_length = (content_length / part_count_u64) / file_helper::CHUNK_SIZE_U64 *
                      file_helper::CHUNK_SIZE_U64;

    let mut sections: Vec<(u64, u64)> = vec![];
    let mut lengths: Vec<u64> = vec![];
    for section in 0..(part_count_u64 - 1) {
        sections.push((section * part_length, (section + 1) * part_length - 1));
        lengths.push(part_length);
    }
    sections.push(((part_count_u64 - 1) * part_length, content_length - 1));
    lengths.push(content_length - (part_count_u64 - 1) * part_length);

    ui_helper::start_pbr(file_name.clone(), lengths);

    let footer_space = file_helper::create_file(file_name.clone(), content_length);
    let mut children = vec![];
    for child_id in 0..part_count {
        let section = sections[child_id];
        let url_clone = url.clone();
        let file_name_clone = file_name.clone();
        loop {
            {
                let mut currently_running = CURRENTLY_RUNNING_THREADS.lock()
                    .expect("Failed to aquire CURRENTLY_RUNNING_THREADS lock, lock poisoned!");
                if *currently_running < thread_count {
                    *currently_running += 1;
                    break;
                }
            }
            thread::sleep(Duration::new(1, 0));
        }
        let child = thread::spawn(move || {
            ui_helper::setting_up_bar(child_id);
            let start =
                file_helper::get_first_empty_chunk(file_name_clone.clone(), footer_space, section);
            if start <= section.1 {
                let prefilled = start - section.0;
                let section = (start, section.1);
                let range_req = request_helper::get_range_request(url_clone.clone(), section);
                ui_helper::start_bar(child_id);
                let written = file_helper::save_response(file_name_clone.clone(),
                                                         range_req,
                                                         footer_space,
                                                         child_id,
                                                         prefilled)
                    .unwrap();
                if written > 0 {
                    ui_helper::success_bar(child_id);
                } else {
                    ui_helper::fail_bar(child_id);
                    let mut failed = HAS_FAILED.lock()
                        .expect("Failed to aquire HAS_FAILED lock, lock poisoned!");
                    *failed = true;
                }
            } else {
                ui_helper::success_bar(child_id);
            }

            let mut currently_running = CURRENTLY_RUNNING_THREADS.lock()
                .expect("Failed to aquire CURRENTLY_RUNNING_THREADS lock, lock poisoned!");
            *currently_running -= 1;
        });
        children.push(child);
    }
    for child in children {
        let _ = child.join();
    }

    if *HAS_FAILED.lock().expect("Failed to aquire HAS_FAILED lock, lock poisoned!") {
        println!("Some parts failed to download, please rerun.");
        process::exit(1);
    } else {
        file_helper::remove_footer_and_save(file_name, content_length);
    }
}
<|endoftext|>


<commit_before>extern crate regex;
extern crate irc;
extern crate xdg_basedir;
extern crate hyper;

mod github;

use regex::Regex;
use irc::client::prelude::*;
use irc::client::server::NetIrcServer;
use xdg_basedir::*;
use std::io::Read;

fn parse_post(post: &str) -> Option<String> {
    let client = hyper::client::Client::new();
    let urlregex = Regex::new(r"https?://\S+\.[:alpha:]{2,}").unwrap();

    if let Some(x) = urlregex.captures(post) {
        if let Ok(mut resp) = client.get(x.at(0).unwrap()).send() {
            let mut body = String::new();
            resp.read_to_string(&mut body).unwrap();
            let titleregex = Regex::new(r"<title>(.+)</title>").unwrap();
            if let Some(cap) = titleregex.captures(&body) {
                return Some(format!("Title: {}", cap.at(1).unwrap()));
            }
        }
    }

    let issueregex = Regex::new(r"([^ ()]+)/([^ ()]+)#(\d+)").unwrap();

    if let Some(cap) = issueregex.captures(post) {
        let user = cap.at(1).unwrap();
        let repo = cap.at(2).unwrap();
        let number = cap.at(3).unwrap();
        return github::get_display_text(user, repo, number).ok()
    }
    None
}

fn handle_message(server: &NetIrcServer, from: &str, to: &str, message: &str) {
    let nickname = server.config().nickname.as_ref().unwrap();

    if to == nickname && from == "ids1024" {
        let mut words = message.split_whitespace();
        let command = words.next().unwrap_or("");
        let parameter = words.next().unwrap_or("");
        match command {
            "join" => {
                server.send_join(parameter).unwrap();
            },
            "part" => {
                server.send(Command::PART(parameter.to_string(), None)).unwrap();
            },
            "quit" => {
                server.send_quit("").unwrap();
            }
            _ => {},
        }
    }

    if let Some(x) = parse_post(&message) {
        for line in x.lines() {
            server.send_privmsg(&to, &line).unwrap();
        }
    }
}

fn main() {
    let mut configpath = get_config_home().unwrap();
    configpath.push("idsbot/config.json");

    let config = Config::load(configpath).unwrap();
    let server = IrcServer::from_config(config).unwrap();
    server.identify().unwrap();

    for message in server.iter() {
        let message = message.unwrap();
        print!("{}", message.into_string());
        if message.command == "PRIVMSG" {
            let from = message.get_source_nickname().unwrap().to_owned();
            let to = &message.args[0];
            let content = message.suffix.unwrap();
            handle_message(&server, &from, to, &content);
        }
    }
}
<commit_msg>Add semicolon (idiomatic?)<commit_after>extern crate regex;
extern crate irc;
extern crate xdg_basedir;
extern crate hyper;

mod github;

use regex::Regex;
use irc::client::prelude::*;
use irc::client::server::NetIrcServer;
use xdg_basedir::*;
use std::io::Read;

fn parse_post(post: &str) -> Option<String> {
    let client = hyper::client::Client::new();
    let urlregex = Regex::new(r"https?://\S+\.[:alpha:]{2,}").unwrap();

    if let Some(x) = urlregex.captures(post) {
        if let Ok(mut resp) = client.get(x.at(0).unwrap()).send() {
            let mut body = String::new();
            resp.read_to_string(&mut body).unwrap();
            let titleregex = Regex::new(r"<title>(.+)</title>").unwrap();
            if let Some(cap) = titleregex.captures(&body) {
                return Some(format!("Title: {}", cap.at(1).unwrap()));
            }
        }
    }

    let issueregex = Regex::new(r"([^ ()]+)/([^ ()]+)#(\d+)").unwrap();

    if let Some(cap) = issueregex.captures(post) {
        let user = cap.at(1).unwrap();
        let repo = cap.at(2).unwrap();
        let number = cap.at(3).unwrap();
        return github::get_display_text(user, repo, number).ok();
    }
    None
}

fn handle_message(server: &NetIrcServer, from: &str, to: &str, message: &str) {
    let nickname = server.config().nickname.as_ref().unwrap();

    if to == nickname && from == "ids1024" {
        let mut words = message.split_whitespace();
        let command = words.next().unwrap_or("");
        let parameter = words.next().unwrap_or("");
        match command {
            "join" => {
                server.send_join(parameter).unwrap();
            },
            "part" => {
                server.send(Command::PART(parameter.to_string(), None)).unwrap();
            },
            "quit" => {
                server.send_quit("").unwrap();
            }
            _ => {},
        }
    }

    if let Some(x) = parse_post(&message) {
        for line in x.lines() {
            server.send_privmsg(&to, &line).unwrap();
        }
    }
}

fn main() {
    let mut configpath = get_config_home().unwrap();
    configpath.push("idsbot/config.json");

    let config = Config::load(configpath).unwrap();
    let server = IrcServer::from_config(config).unwrap();
    server.identify().unwrap();

    for message in server.iter() {
        let message = message.unwrap();
        print!("{}", message.into_string());
        if message.command == "PRIVMSG" {
            let from = message.get_source_nickname().unwrap().to_owned();
            let to = &message.args[0];
            let content = message.suffix.unwrap();
            handle_message(&server, &from, to, &content);
        }
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate rand;

mod tetris;

use piston::window::WindowSettings;
use piston::event::*;
use glutin_window::GlutinWindow as Glutin_Window;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use graphics::{ Transformed };
use piston::input::Button::{ Keyboard };
use piston::input::Input;
use piston::input::keyboard::Key;
use std::path::Path;

use tetris::*;

pub struct App {
    gl: GlGraphics,
    tetris: Tetris,
    elapsed_time: f64,
    cache: GlyphCache<'static>,
    should_redraw: bool
}

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const DARK_GRAY: [f32; 4] = [0.1, 0.1, 0.1, 1.0];
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const CYAN: [f32; 4] = [0.0, 1.0, 1.0, 1.0];
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const BLUE: [f32; 4] = [0.0, 0.0, 1.0, 1.0];
const ORANGE: [f32; 4] = [1.0, 0.5, 0.0, 1.0];
const YELLOW: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
const PURPLE: [f32; 4] = [0.5, 0.0, 1.0, 1.0];

fn get_shape_color(shape_index: i32) -> [f32; 4] {
    match shape_index {
        0 => PURPLE,
        1 => YELLOW,
        2 => RED,
        3 => GREEN,
        4 => ORANGE,
        5 => BLUE,
        6 => CYAN,
        _ => {
            BLACK
        }
    }
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        self.should_redraw = false;

        const CELL_SIZE: f64 = 30.0;
        const LEFT_MARGIN: f64 = 20f64;
        const TOP_MARGIN: f64 = 30f64;

        const STATUS_LEFT_MARGIN: f64 = 400f64;
        const STATUS_TOP_MARGIN: f64 = 100f64;
        const LINE_HEIGHT: f64 = 40f64;
        const STATUS_PREVIEW_GRID_HEIGHT: f64 = CELL_SIZE * 6f64;

        // so that we can access inside clojure
        let use_cache = &mut self.cache;
        let use_tetris = &mut self.tetris;

        self.gl.draw(args.viewport(), |c, gl| {
            // clear the viewport
            graphics::clear(BLACK, gl);

            // render the current score and level
            let mut text = graphics::Text::new(22);
            text.color = ORANGE;
            let mut transform = c.trans(STATUS_LEFT_MARGIN, STATUS_TOP_MARGIN);
            text.draw(&format!("Level: {}", use_tetris.get_level()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            text.draw(&format!("Score: {}", use_tetris.get_score()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            // render the next shape as a preview of what's coming next
            for point in use_tetris.get_next_shape().iter() {
                let square = graphics::rectangle::square(0f64, 0f64, CELL_SIZE);
                let color = get_shape_color(use_tetris.get_next_shape_index() as i32);
                // render the shape at col 2 and row 2
                let (x, y) = ((2 as i16 + point.x) as f64 * CELL_SIZE,
                    (2 as i16 + point.y) as f64 * CELL_SIZE);
                graphics::rectangle(color, square, transform.trans(x, y).transform, gl);
                let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state,
                    transform.trans(x, y).transform, gl);
            }
            transform = transform.trans(0f64, STATUS_PREVIEW_GRID_HEIGHT);

            // render GAME OVER text if necessary
            if use_tetris.get_game_over() {
                text.draw(&"GAME OVER", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press 'N' for a new game", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Use arrow keys to move and rotate", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press spacebar to drop", use_cache, &c.draw_state,
                    transform.transform, gl);
                // uncomment if drawing additional text in the status area
                //transform = transform.trans(0f64, LINE_HEIGHT);
            }

            // draw a white border around the game board
            let rect_border = graphics::Rectangle::new_border(WHITE, 1.5);
            rect_border.draw([
                LEFT_MARGIN,
                TOP_MARGIN,
                (CELL_SIZE * COL_COUNT as f64) + 1f64,
                (CELL_SIZE * ROW_COUNT as f64) + 1f64,
            ], &c.draw_state, c.transform, gl);

            // render each cell in the game board
            for col in 0..COL_COUNT as i32 {
                for row in 0..ROW_COUNT as i32 {
                    let cell = use_tetris.get_grid_cell(col, row);
                    if cell.cell_type != GridCellType::Void {
                        let (x, y) = (col as f64 * CELL_SIZE, row as f64 * CELL_SIZE);
                        let square = graphics::rectangle::square(0.0f64, 0.0f64, CELL_SIZE);
                        let color = match cell.cell_type {
                            GridCellType::Shape => get_shape_color(cell.shape_index),
                            GridCellType::Fixed => get_shape_color(cell.shape_index),
                            GridCellType::Ghost => DARK_GRAY,
                            _ => {
                                assert!(false);
                                BLACK
                            }
                        };
                        let transform = c.transform.trans(LEFT_MARGIN, TOP_MARGIN).trans(x, y);
                        graphics::rectangle(color, square, transform, gl);
                        let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                        tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state, transform, gl);
                    }
                }
            }
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        if self.tetris.get_game_over() {
            self.elapsed_time = 0.0;
        } else {
            // Here we increment the time elapsed between update()'s
            self.elapsed_time += args.dt;
            // if the elapsed time is now greater than the time allotted between ticks, then invoke tetris.tick()
            if self.elapsed_time > self.tetris.get_tick_time() as f64 {
                self.elapsed_time = 0.0;
                self.tetris.tick();
                self.should_redraw = true;
            }
        }
    }

    fn handle_input(&mut self, i: Input) {
        let prev_should_redraw = self.should_redraw;
        self.should_redraw = true;
        match i {
            Input::Press(Keyboard(Key::Left)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col - 1);
            },

            Input::Press(Keyboard(Key::Right)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col + 1);
            },

            Input::Press(Keyboard(Key::Up)) => {
                self.tetris.rotate(true);
            },

            Input::Press(Keyboard(Key::Down)) => {
                let row: i32 = self.tetris.get_row() + 1;
                self.tetris.set_row(row);
            },

            Input::Press(Keyboard(Key::Space)) => {
                let mut row: i32 = self.tetris.get_row() + 1;
                while self.tetris.set_row(row) {
                    row += 1;
                }
                // hard drop immediately spawns next shape
                self.tetris.tick();
            },

            Input::Press(Keyboard(Key::N)) => {
                self.tetris.start_game();
            },

            _ => {
                self.should_redraw = prev_should_redraw;
            }
        }
    }
}

fn main() {
    start_app();
}

fn start_app() {
    let opengl = OpenGL::_3_2;

    let window = Glutin_Window::new(
        opengl,
        WindowSettings::new("Piston Tetris", [1024, 768])
                       .exit_on_esc(true)
                       .vsync(true)
                       .samples(1)
    );

    let font_path = Path::new("FiraMono-Bold.ttf");

    let mut app = App {
        gl: GlGraphics::new(opengl),
        tetris: Tetris::new(),
        elapsed_time: 0.0,
        cache: GlyphCache::new(font_path).unwrap(),
        should_redraw: true,
    };

    for e in window.events().max_fps(30).ups(30) {
        match e {
            Event::Input(i) => {
                app.handle_input(i);
            }

            Event::Render(args) if app.should_redraw => {
                app.render(&args);
            }

            Event::Update(args) => {
                app.update(&args);
            }

            _ => {}
        }
    }
}<commit_msg>Allow cargo doc to show docs of tetris game<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate rand;

pub mod tetris;

use piston::window::WindowSettings;
use piston::event::*;
use glutin_window::GlutinWindow as Glutin_Window;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use graphics::{ Transformed };
use piston::input::Button::{ Keyboard };
use piston::input::Input;
use piston::input::keyboard::Key;
use std::path::Path;

use tetris::*;

struct App {
    gl: GlGraphics,
    tetris: Tetris,
    elapsed_time: f64,
    cache: GlyphCache<'static>,
    should_redraw: bool
}

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
const DARK_GRAY: [f32; 4] = [0.1, 0.1, 0.1, 1.0];
const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
const CYAN: [f32; 4] = [0.0, 1.0, 1.0, 1.0];
const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
const BLUE: [f32; 4] = [0.0, 0.0, 1.0, 1.0];
const ORANGE: [f32; 4] = [1.0, 0.5, 0.0, 1.0];
const YELLOW: [f32; 4] = [1.0, 1.0, 0.0, 1.0];
const PURPLE: [f32; 4] = [0.5, 0.0, 1.0, 1.0];

fn get_shape_color(shape_index: i32) -> [f32; 4] {
    match shape_index {
        0 => PURPLE,
        1 => YELLOW,
        2 => RED,
        3 => GREEN,
        4 => ORANGE,
        5 => BLUE,
        6 => CYAN,
        _ => {
            BLACK
        }
    }
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        self.should_redraw = false;

        const CELL_SIZE: f64 = 30.0;
        const LEFT_MARGIN: f64 = 20f64;
        const TOP_MARGIN: f64 = 30f64;

        const STATUS_LEFT_MARGIN: f64 = 400f64;
        const STATUS_TOP_MARGIN: f64 = 100f64;
        const LINE_HEIGHT: f64 = 40f64;
        const STATUS_PREVIEW_GRID_HEIGHT: f64 = CELL_SIZE * 6f64;

        // so that we can access inside clojure
        let use_cache = &mut self.cache;
        let use_tetris = &mut self.tetris;

        self.gl.draw(args.viewport(), |c, gl| {
            // clear the viewport
            graphics::clear(BLACK, gl);

            // render the current score and level
            let mut text = graphics::Text::new(22);
            text.color = ORANGE;
            let mut transform = c.trans(STATUS_LEFT_MARGIN, STATUS_TOP_MARGIN);
            text.draw(&format!("Level: {}", use_tetris.get_level()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            text.draw(&format!("Score: {}", use_tetris.get_score()), use_cache, &c.draw_state,
                transform.transform, gl);
            transform = transform.trans(0f64, LINE_HEIGHT);

            // render the next shape as a preview of what's coming next
            for point in use_tetris.get_next_shape().iter() {
                let square = graphics::rectangle::square(0f64, 0f64, CELL_SIZE);
                let color = get_shape_color(use_tetris.get_next_shape_index() as i32);
                // render the shape at col 2 and row 2
                let (x, y) = ((2 as i16 + point.x) as f64 * CELL_SIZE,
                    (2 as i16 + point.y) as f64 * CELL_SIZE);
                graphics::rectangle(color, square, transform.trans(x, y).transform, gl);
                let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state,
                    transform.trans(x, y).transform, gl);
            }
            transform = transform.trans(0f64, STATUS_PREVIEW_GRID_HEIGHT);

            // render GAME OVER text if necessary
            if use_tetris.get_game_over() {
                text.draw(&"GAME OVER", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press 'N' for a new game", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Use arrow keys to move and rotate", use_cache, &c.draw_state,
                    transform.transform, gl);
                transform = transform.trans(0f64, LINE_HEIGHT);

                text.draw(&"Press spacebar to drop", use_cache, &c.draw_state,
                    transform.transform, gl);
                // uncomment if drawing additional text in the status area
                //transform = transform.trans(0f64, LINE_HEIGHT);
            }

            // draw a white border around the game board
            let rect_border = graphics::Rectangle::new_border(WHITE, 1.5);
            rect_border.draw([
                LEFT_MARGIN,
                TOP_MARGIN,
                (CELL_SIZE * COL_COUNT as f64) + 1f64,
                (CELL_SIZE * ROW_COUNT as f64) + 1f64,
            ], &c.draw_state, c.transform, gl);

            // render each cell in the game board
            for col in 0..COL_COUNT as i32 {
                for row in 0..ROW_COUNT as i32 {
                    let cell = use_tetris.get_grid_cell(col, row);
                    if cell.cell_type != GridCellType::Void {
                        let (x, y) = (col as f64 * CELL_SIZE, row as f64 * CELL_SIZE);
                        let square = graphics::rectangle::square(0.0f64, 0.0f64, CELL_SIZE);
                        let color = match cell.cell_type {
                            GridCellType::Shape => get_shape_color(cell.shape_index),
                            GridCellType::Fixed => get_shape_color(cell.shape_index),
                            GridCellType::Ghost => DARK_GRAY,
                            _ => {
                                assert!(false);
                                BLACK
                            }
                        };
                        let transform = c.transform.trans(LEFT_MARGIN, TOP_MARGIN).trans(x, y);
                        graphics::rectangle(color, square, transform, gl);
                        let tetromino_border = graphics::Rectangle::new_border(DARK_GRAY, 1.0);
                        tetromino_border.draw([0f64, 0f64, CELL_SIZE, CELL_SIZE], &c.draw_state, transform, gl);
                    }
                }
            }
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        if self.tetris.get_game_over() {
            self.elapsed_time = 0.0;
        } else {
            // Here we increment the time elapsed between update()'s
            self.elapsed_time += args.dt;
            // if the elapsed time is now greater than the time allotted between ticks, then invoke tetris.tick()
            if self.elapsed_time > self.tetris.get_tick_time() as f64 {
                self.elapsed_time = 0.0;
                self.tetris.tick();
                self.should_redraw = true;
            }
        }
    }

    fn handle_input(&mut self, i: Input) {
        let prev_should_redraw = self.should_redraw;
        self.should_redraw = true;
        match i {
            Input::Press(Keyboard(Key::Left)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col - 1);
            },

            Input::Press(Keyboard(Key::Right)) => {
                let col: i32 = self.tetris.get_col();
                self.tetris.set_col(col + 1);
            },

            Input::Press(Keyboard(Key::Up)) => {
                self.tetris.rotate(true);
            },

            Input::Press(Keyboard(Key::Down)) => {
                let row: i32 = self.tetris.get_row() + 1;
                self.tetris.set_row(row);
            },

            Input::Press(Keyboard(Key::Space)) => {
                let mut row: i32 = self.tetris.get_row() + 1;
                while self.tetris.set_row(row) {
                    row += 1;
                }
                // hard drop immediately spawns next shape
                self.tetris.tick();
            },

            Input::Press(Keyboard(Key::N)) => {
                self.tetris.start_game();
            },

            _ => {
                self.should_redraw = prev_should_redraw;
            }
        }
    }
}

fn main() {
    start_app();
}

fn start_app() {
    let opengl = OpenGL::_3_2;

    let window = Glutin_Window::new(
        opengl,
        WindowSettings::new("Piston Tetris", [1024, 768])
                       .exit_on_esc(true)
                       .vsync(true)
                       .samples(1)
    );

    let font_path = Path::new("FiraMono-Bold.ttf");

    let mut app = App {
        gl: GlGraphics::new(opengl),
        tetris: Tetris::new(),
        elapsed_time: 0.0,
        cache: GlyphCache::new(font_path).unwrap(),
        should_redraw: true,
    };

    for e in window.events().max_fps(30).ups(30) {
        match e {
            Event::Input(i) => {
                app.handle_input(i);
            }

            Event::Render(args) if app.should_redraw => {
                app.render(&args);
            }

            Event::Update(args) => {
                app.update(&args);
            }

            _ => {}
        }
    }
}<|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("#", "");
    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.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("");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(rusqlite::params_from_iter(&row)).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).unwrap();
    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);
    }
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [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 = [
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
        ".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);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    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;
            }
        }
    }

    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>added functions to autocomplete (#547)<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("#", "");
    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.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("");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(rusqlite::params_from_iter(&row)).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).unwrap();
    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);
    }
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [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 = [
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
        "length", "coalesce", ".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);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    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;
            }
        }
    }

    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>#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
extern crate argparse;
extern crate env_logger;
extern crate hyper;
extern crate mozprofile;
extern crate mozrunner;
extern crate regex;
extern crate rustc_serialize;
#[macro_use]
extern crate webdriver;
extern crate zip;

use std::borrow::ToOwned;
use std::process::exit;
use std::net::{SocketAddr, IpAddr};
use std::str::FromStr;
use std::path::Path;

use argparse::{ArgumentParser, StoreTrue, Store};
use webdriver::server::start;

use marionette::{MarionetteHandler, BrowserLauncher, MarionetteSettings, extension_routes};

macro_rules! try_opt {
    ($expr:expr, $err_type:expr, $err_msg:expr) => ({
        match $expr {
            Some(x) => x,
            None => return Err(WebDriverError::new($err_type, $err_msg))
        }
    })
}

mod marionette;

struct Options {
    binary: String,
    webdriver_host: String,
    webdriver_port: u16,
    marionette_port: u16,
    connect_existing: bool,
    e10s: bool
}

fn parse_args() -> Options {
    let mut opts = Options {
        binary: "".to_owned(),
        webdriver_host: "127.0.0.1".to_owned(),
        webdriver_port: 4444u16,
        marionette_port: 2828u16,
        connect_existing: false,
        e10s: false
    };

    {
        let mut parser = ArgumentParser::new();
        parser.set_description("WebDriver to marionette proxy.");
        parser.refer(&mut opts.binary)
            .add_option(&["-b", "--binary"], Store,
                        "Path to the Firefox binary");
        parser.refer(&mut opts.webdriver_host)
            .add_option(&["--webdriver-host"], Store,
                        "Host to run webdriver server on");
        parser.refer(&mut opts.webdriver_port)
            .add_option(&["--webdriver-port"], Store,
                        "Port to run webdriver on");
        parser.refer(&mut opts.marionette_port)
            .add_option(&["--marionette-port"], Store,
                        "Port to run marionette on");
        parser.refer(&mut opts.connect_existing)
            .add_option(&["--connect-existing"], StoreTrue,
                        "Connect to an existing firefox process");
        parser.refer(&mut opts.e10s)
            .add_option(&["--e10s"], StoreTrue,
                        "Load Firefox with an e10s profile");
        parser.parse_args_or_exit();
    }

    if opts.binary == "" && !opts.connect_existing {
        println!("Must supply a binary path or --connect-existing\n");
        exit(1)
    }
    opts
}

fn main() {
    env_logger::init().unwrap();
    let opts = parse_args();

    let host = &opts.webdriver_host[..];
    let port = opts.webdriver_port;
    let addr = IpAddr::from_str(host).map(
        |x| SocketAddr::new(x, port)).unwrap_or_else(
        |_| {
            println!("Invalid host address");
            exit(1);
        }
        );

    let launcher = if opts.connect_existing {
        BrowserLauncher::None
    } else {
        BrowserLauncher::BinaryLauncher(Path::new(&opts.binary).to_path_buf())
    };

    let settings = MarionetteSettings::new(opts.marionette_port,
                                           launcher,
                                           opts.e10s);

    //TODO: what if binary isn't a valid path?
    start(addr, MarionetteHandler::new(settings), extension_routes());
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use marionette::{MarionetteSettings, MarionetteHandler, BrowserLauncher};
    use webdriver::command::CapabilitiesParameters;
    use rustc_serialize::json::Json;
    use std::fs::File;
    use rustc_serialize::base64::{ToBase64, Config, CharacterSet, Newline};
    use mozprofile::preferences::Pref;
    use std::io::Read;

    #[test]
    fn test_profile() {
        let mut profile_data = Vec::with_capacity(1024);
        let mut profile = File::open("src/tests/profile.zip").unwrap();
        profile.read_to_end(&mut profile_data).unwrap();
        let base64_config = Config {
            char_set: CharacterSet::Standard,
            newline: Newline::LF,
            pad: true,
            line_length: None
        };
        let encoded_profile = Json::String(profile_data.to_base64(base64_config));

        let desired: BTreeMap<String, Json> = BTreeMap::new();
        let mut required: BTreeMap<String, Json> = BTreeMap::new();
        required.insert("firefox_profile".into(), encoded_profile);
        let capabilities = CapabilitiesParameters {
            desired: desired,
            required: required
        };

        let handler = MarionetteHandler::new(
            MarionetteSettings::new(2828u16, BrowserLauncher::None, false));

        let mut gecko_profile = handler.load_profile(&capabilities).unwrap().unwrap();
        handler.set_prefs(&mut gecko_profile, true).unwrap();

        let prefs = gecko_profile.user_prefs().unwrap();

        println!("{:?}",prefs.prefs);

        assert_eq!(prefs.get("startup.homepage_welcome_url"),
                   Some(&Pref::new("data:text/html,PASS")));
        assert_eq!(prefs.get("marionette.defaultPrefs.enabled"),
                   Some(&Pref::new(true)));
    }

}
<commit_msg>Fix tests<commit_after>#[macro_use]
extern crate log;
#[macro_use]
extern crate lazy_static;
extern crate argparse;
extern crate env_logger;
extern crate hyper;
extern crate mozprofile;
extern crate mozrunner;
extern crate regex;
extern crate rustc_serialize;
#[macro_use]
extern crate webdriver;
extern crate zip;

use std::borrow::ToOwned;
use std::process::exit;
use std::net::{SocketAddr, IpAddr};
use std::str::FromStr;
use std::path::Path;

use argparse::{ArgumentParser, StoreTrue, Store};
use webdriver::server::start;

use marionette::{MarionetteHandler, BrowserLauncher, MarionetteSettings, extension_routes};

macro_rules! try_opt {
    ($expr:expr, $err_type:expr, $err_msg:expr) => ({
        match $expr {
            Some(x) => x,
            None => return Err(WebDriverError::new($err_type, $err_msg))
        }
    })
}

mod marionette;

struct Options {
    binary: String,
    webdriver_host: String,
    webdriver_port: u16,
    marionette_port: u16,
    connect_existing: bool,
    e10s: bool
}

fn parse_args() -> Options {
    let mut opts = Options {
        binary: "".to_owned(),
        webdriver_host: "127.0.0.1".to_owned(),
        webdriver_port: 4444u16,
        marionette_port: 2828u16,
        connect_existing: false,
        e10s: false
    };

    {
        let mut parser = ArgumentParser::new();
        parser.set_description("WebDriver to marionette proxy.");
        parser.refer(&mut opts.binary)
            .add_option(&["-b", "--binary"], Store,
                        "Path to the Firefox binary");
        parser.refer(&mut opts.webdriver_host)
            .add_option(&["--webdriver-host"], Store,
                        "Host to run webdriver server on");
        parser.refer(&mut opts.webdriver_port)
            .add_option(&["--webdriver-port"], Store,
                        "Port to run webdriver on");
        parser.refer(&mut opts.marionette_port)
            .add_option(&["--marionette-port"], Store,
                        "Port to run marionette on");
        parser.refer(&mut opts.connect_existing)
            .add_option(&["--connect-existing"], StoreTrue,
                        "Connect to an existing firefox process");
        parser.refer(&mut opts.e10s)
            .add_option(&["--e10s"], StoreTrue,
                        "Load Firefox with an e10s profile");
        parser.parse_args_or_exit();
    }

    if opts.binary == "" && !opts.connect_existing {
        println!("Must supply a binary path or --connect-existing\n");
        exit(1)
    }
    opts
}

fn main() {
    env_logger::init().unwrap();
    let opts = parse_args();

    let host = &opts.webdriver_host[..];
    let port = opts.webdriver_port;
    let addr = IpAddr::from_str(host).map(
        |x| SocketAddr::new(x, port)).unwrap_or_else(
        |_| {
            println!("Invalid host address");
            exit(1);
        }
        );

    let launcher = if opts.connect_existing {
        BrowserLauncher::None
    } else {
        BrowserLauncher::BinaryLauncher(Path::new(&opts.binary).to_path_buf())
    };

    let settings = MarionetteSettings::new(opts.marionette_port,
                                           launcher,
                                           opts.e10s);

    //TODO: what if binary isn't a valid path?
    start(addr, MarionetteHandler::new(settings), extension_routes());
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;
    use marionette::{MarionetteSettings, MarionetteHandler, BrowserLauncher};
    use webdriver::command::NewSessionParameters;
    use rustc_serialize::json::Json;
    use std::fs::File;
    use rustc_serialize::base64::{ToBase64, Config, CharacterSet, Newline};
    use mozprofile::preferences::Pref;
    use std::io::Read;

    #[test]
    fn test_profile() {
        let mut profile_data = Vec::with_capacity(1024);
        let mut profile = File::open("src/tests/profile.zip").unwrap();
        profile.read_to_end(&mut profile_data).unwrap();
        let base64_config = Config {
            char_set: CharacterSet::Standard,
            newline: Newline::LF,
            pad: true,
            line_length: None
        };
        let encoded_profile = Json::String(profile_data.to_base64(base64_config));

        let desired: BTreeMap<String, Json> = BTreeMap::new();
        let mut required: BTreeMap<String, Json> = BTreeMap::new();
        required.insert("firefox_profile".into(), encoded_profile);
        let capabilities = NewSessionParameters {
            desired: desired,
            required: required
        };

        let handler = MarionetteHandler::new(
            MarionetteSettings::new(2828u16, BrowserLauncher::None, false));

        let mut gecko_profile = handler.load_profile(&capabilities).unwrap().unwrap();
        handler.set_prefs(&mut gecko_profile, true).unwrap();

        let prefs = gecko_profile.user_prefs().unwrap();

        println!("{:?}",prefs.prefs);

        assert_eq!(prefs.get("startup.homepage_welcome_url"),
                   Some(&Pref::new("data:text/html,PASS")));
        assert_eq!(prefs.get("marionette.defaultPrefs.enabled"),
                   Some(&Pref::new(true)));
    }

}
<|endoftext|>


<commit_before>
use std::io;
use std::io::fs;
use std::os;
use std::io::process::{Command};
use std::path::Path;

mod ash;

fn main() {
  println!("ash: A shell");
  println!("Incredibly in beta");
  println!("May eat your left shoes.");

  let mut cwd = os::getcwd();

  loop {
    print!("{}", ash::format::format(&cwd));
    let rawinput = io::stdin().read_line().ok().expect("Error Occured");
    let input = rawinput.as_slice().trim();
    if input == "" { continue } //skip blank enters
    let opts: Vec<&str> = input.split_str(" ").collect();
    let (cmd, args) = (opts[0], opts.slice(1, opts.len()));
    match cmd {
      "cd" => {
        //set the current directory
        if args[0] == "~" {
          //go home
          cwd = os::homedir().unwrap();
          continue;
        }
        let path: Option<Path> = if args[0].starts_with("~") { // ~/projects
          match os::homedir() {
            Some(e) => {
              let dir = e.join(args[0].slice_from(2)); //[~/]
              Some(dir)
            }, //hacky but whatever
            None => Path::new_opt(args[0])
          }
        } else if args[0].starts_with(".") || !args[0].starts_with("/") { // ./bin or ../ash || cd src
          Some(cwd.join(args[0]))
        } else {
          Path::new_opt(args[0])
        };
        match path {
          Some(new) => {
            match fs::stat(&new) {
              Ok(stat) => {
                if stat.kind == io::TypeDirectory {
                  cwd = new
                }
              },
              Err(e) => println!("No such file or directory: \"{}\"", args[0])
            }
          }
          None => println!("Failed to locate path")
        }
      }
      _ => {
        let process = Command::new(cmd).cwd(&cwd).args(args).output();

        match process {
          Ok(output) => {
            println!("{}", String::from_utf8_lossy(output.output.as_slice()));

          },
          Err(e) => {
            println!("Error Occured: {}", e);
          },
        };
      }
    }
  }
}
<commit_msg>Add `exit` command to exit cleanly<commit_after>
use std::io;
use std::io::fs;
use std::os;
use std::io::process::{Command};
use std::path::Path;

mod ash;

fn main() {
  println!("ash: A shell");
  println!("Incredibly in beta");
  println!("May eat your left shoes.");

  let mut cwd = os::getcwd();

  loop {
    print!("{}", ash::format::format(&cwd));
    let rawinput = io::stdin().read_line().ok().expect("Error Occured");
    let input = rawinput.as_slice().trim();
    if input == "" { continue } //skip blank enters
    let opts: Vec<&str> = input.split_str(" ").collect();
    let (cmd, args) = (opts[0], opts.slice(1, opts.len()));
    match cmd {
      "cd" => {
        //set the current directory
        if args[0] == "~" {
          //go home
          cwd = os::homedir().unwrap();
          continue;
        }
        let path: Option<Path> = if args[0].starts_with("~") { // ~/projects
          match os::homedir() {
            Some(e) => {
              let dir = e.join(args[0].slice_from(2)); //[~/]
              Some(dir)
            }, //hacky but whatever
            None => Path::new_opt(args[0])
          }
        } else if args[0].starts_with(".") || !args[0].starts_with("/") { // ./bin or ../ash || cd src
          Some(cwd.join(args[0]))
        } else {
          Path::new_opt(args[0])
        };
        match path {
          Some(new) => {
            match fs::stat(&new) {
              Ok(stat) => {
                if stat.kind == io::TypeDirectory {
                  cwd = new
                }
              },
              Err(e) => println!("No such file or directory: \"{}\"", args[0])
            }
          }
          None => println!("Failed to locate path")
        }
      }
      "exit" => {
        println!("Goodbye!");
        break;
      }
      _ => {
        let process = Command::new(cmd).cwd(&cwd).args(args).output();

        match process {
          Ok(output) => {
            println!("{}", String::from_utf8_lossy(output.output.as_slice()));

          },
          Err(e) => {
            println!("Error Occured: {}", e);
          },
        };
      }
    }
  }
}
<|endoftext|>


<commit_before>use super::mpfr::Mpfr;

#[test]
fn test_set() {
	let mut a : Mpfr = From::<i64>::from(1000);
	let b : Mpfr = From::<i64>::from(5000);
	assert!(a != b);
	a.set(&b);
	assert!(a == b);
}

#[test]
fn test_eq() {
    let x: Mpfr = From::<f64>::from(1.234567);
    let y: Mpfr = From::<f64>::from(1.234567);
    let z: Mpfr = From::<f64>::from(1.234568);

    assert!(x == y);
    assert!(x != z);
    assert!(y != z);
}

#[test]
fn test_ord() {
    let x: Mpfr = From::<i64>::from(-1048576);
    let y: Mpfr = From::<i64>::from(2);
    let z: Mpfr = From::<i64>::from(1048576);

    assert!(x < y && x < z && y < z);
    assert!(x <= x && x <= y && x <= z && y <= z);
    assert!(z > y && z > x && y > x);
    assert!(z >= z && z >= y && z >= x && y >= x);
}

#[test]
#[should_panic]
fn test_div_zero() {
    let x: Mpfr = From::<i64>::from(1);
    let y = Mpfr::zero(1);
    x / y;
}

#[test]
fn test_clone() {
    let a: Mpfr = From::<i64>::from(100);
    let b = a.clone();
    assert!(b == a);
}

#[test]
fn test_add() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<i64>::from(35);

	assert!(a + b == result);
}

#[test]
fn test_sub() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<i64>::from(-5);

	assert!(a - b == result);
}

#[test]
fn test_mul() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<i64>::from(300);

	assert!(a * b == result);
}

#[test]
fn test_div() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<f64>::from(0.75);

	assert!(a / b == result);
}<commit_msg>Added tests for new functions<commit_after>use super::mpfr::Mpfr;

#[test]
fn test_set() {
	let mut a : Mpfr = From::<i64>::from(1000);
	let b : Mpfr = From::<i64>::from(5000);
	assert!(a != b);
	a.set(&b);
	assert!(a == b);
}

#[test]
fn test_eq() {
    let x: Mpfr = From::<f64>::from(1.234567);
    let y: Mpfr = From::<f64>::from(1.234567);
    let z: Mpfr = From::<f64>::from(1.234568);

    assert!(x == y);
    assert!(x != z);
    assert!(y != z);
}

#[test]
fn test_ord() {
    let x: Mpfr = From::<i64>::from(-1048576);
    let y: Mpfr = From::<i64>::from(2);
    let z: Mpfr = From::<i64>::from(1048576);

    assert!(x < y && x < z && y < z);
    assert!(x <= x && x <= y && x <= z && y <= z);
    assert!(z > y && z > x && y > x);
    assert!(z >= z && z >= y && z >= x && y >= x);
}

#[test]
#[should_panic]
fn test_div_zero() {
    let x: Mpfr = From::<i64>::from(1);
    let y = Mpfr::zero(1);
    x / y;
}

#[test]
fn test_clone() {
    let a: Mpfr = From::<i64>::from(100);
    let b = a.clone();
    assert!(b == a);
}

#[test]
fn test_add() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<i64>::from(35);

	assert!(a + b == result);
}

#[test]
fn test_sub() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<i64>::from(-5);

	assert!(a - b == result);
}

#[test]
fn test_mul() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<i64>::from(300);

	assert!(a * b == result);
}

#[test]
fn test_mul_d() {
	let a: Mpfr = From::<i64>::from(15);
	let result: Mpfr = From::<f64>::from(37.5);

	assert!(&a * 2.5 == result);
}

#[test]
fn test_div() {
	let a: Mpfr = From::<i64>::from(15);
	let b: Mpfr = From::<i64>::from(20);
	let result: Mpfr = From::<f64>::from(0.75);

	assert!(a / b == result);
}

#[test]
fn test_div_d() {
	let a: Mpfr = From::<i64>::from(15);
	let result: Mpfr = From::<i64>::from(3);

	assert!(&a / 5.0 == result);
}

#[test]
fn test_rounding() {
	let a: Mpfr = From::<f64>::from(2.4999);
	let b: Mpfr = From::<f64>::from(2.5);
	let two: Mpfr = From::<i64>::from(2);
	let three: Mpfr = From::<i64>::from(3);

	assert!(a.floor() == two);
	assert!(a.round() == two);
	assert!(a.ceil() == three);

	assert!(b.floor() == two);
	assert!(b.round() == three);
	assert!(b.ceil() == three);
}

#[test]
fn test_pow_root() {
	let a: Mpfr = From::<f64>::from(2.654);
	let two: Mpfr = From::<i64>::from(2);
	let three: Mpfr = From::<i64>::from(3);
	let asq = &a*&a;
	let acb = &a*&a*&a;

	assert!(a.pow(&two) == asq);
	assert!(a.pow(&three) == acb);
	assert!(asq.sqrt() == a);
	assert!(acb.cbrt() == a);
	assert!(asq.root(2) == a);
	assert!(acb.root(3) == a);
}

#[test]
fn test_exp_log() {
	let a: Mpfr = From::<i64>::from(1);
	let b: Mpfr = From::<f64>::from(2.718281828459045);

	assert!(a.exp() == b);
	assert!(b.log() == a);
}<|endoftext|>