<commit_before>#[macro_use]
extern crate lazy_static;

extern crate clap;
extern crate qrcode;
extern crate termion;
extern crate image;
extern crate regex;

use clap::{App, Arg, SubCommand};
use qrcode::{QrCode, EcLevel};
use termion::color;

mod payloads;

const WIFI_COMMAND: &'static str = "wifi";
const MAIL_COMMAND: &'static str = "mail";
const SMS_COMMAND: &'static str = "sms";
const MMS_COMMAND: &'static str = "mms";
const GEO_COMMAND: &'static str = "geo";
const PHONE_COMMAND: &'static str = "phone";
const SKYPE_COMMAND: &'static str = "skype";
const URL_COMMAND: &'static str = "url";
const BOOKMARK_COMMAND: &'static str = "bookmark";
const BITCOIN_COMMAND: &'static str = "bitcoin";
const GIRO_COMMAND: &'static str = "giro";
const CALENDAR_COMMAND: &'static str = "calendar";

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
*/
fn main() {
    let app = App::new("qrterm")
        .version("0.1")
        .author("Lukas R. <lukas@bootsmann-games.de>")
        .about("Generates and displays terminal friendly QR-Codes from input strings")
        .arg(Arg::with_name("safe_zone") //TODO: change this into an off switch
            .global(true)
            .required(false)
            .short("s")
            .long("safe-zone")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(false)
            )
            //TODO: subcmds are not working like expected, if you have one the system assumes you have many
        .subcommand(SubCommand::with_name(WIFI_COMMAND)
            .about("formats to a wifi access string")
            .arg(Arg::with_name("ssid").required(true))
            .arg(Arg::with_name("pwd").required(true))
            .arg(Arg::with_name("mode")
                .possible_values(&["WEP", "WPA", "nopass"])
                .default_value("WPA")
                .value_name("MODE"))
            .arg(Arg::with_name("hidden")
                .required(false)
                .possible_values(&["true", "false"])
                .default_value("false")
                .value_name("HIDDEN")))
        .subcommand(SubCommand::with_name(MAIL_COMMAND)
            .about("formats to a mail adress string")
            .arg(Arg::with_name("receiver").required(true))
            .arg(Arg::with_name("subject"))
            .arg(Arg::with_name("message"))
            .arg(Arg::with_name("encoding")
                .possible_values(&["MAILTO", "MATMSG", "SMTP"])
                .default_value("MAILTO")
                .value_name("ENCODING")))
        .subcommand(SubCommand::with_name(URL_COMMAND)
            .about("formats to an URL")
            .arg(Arg::with_name("url")
                .required(true)
                .value_name("URL")))
        .subcommand(SubCommand::with_name(PHONE_COMMAND)
            .about("formats to a phone number")
            .arg(Arg::with_name("number")
                .required(true)
                .value_name("NUMBER")))
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required_unless_one(&[WIFI_COMMAND, MAIL_COMMAND, URL_COMMAND, PHONE_COMMAND]));

    let matches = app.get_matches();

    let payload: String;
    if let Some(sub) = matches.subcommand_matches(WIFI_COMMAND) {
        let auth = match sub.value_of("mode") {
            Some("WEP") => payloads::Authentication::WEP,
            Some("WPA") => payloads::Authentication::WPA,
            _ => payloads::Authentication::nopass,
        };
        payload = payloads::wifi_string(sub.value_of("ssid").unwrap(),
                                        sub.value_of("pwd").unwrap(),
                                        &auth,
                                        sub.value_of("hidden").unwrap() == "true");
    } else if let Some(sub) = matches.subcommand_matches(MAIL_COMMAND) {
        let encoding = match sub.value_of("encoding") {
            Some("MAILTO") => payloads::MailEncoding::MAILTO,
            Some("MATMSG") => payloads::MailEncoding::MATMSG,
            Some("SMTP") => payloads::MailEncoding::SMTP,
            _ => payloads::MailEncoding::MAILTO,
        };
        payload = payloads::mail_string(sub.value_of("receiver").unwrap(),
                                        sub.value_of("subject").unwrap(),
                                        sub.value_of("message").unwrap(),
                                        &encoding);
    } else if let Some(sub) = matches.subcommand_matches(URL_COMMAND) {
        payload = payloads::url_string(sub.value_of("url").unwrap());
    } else if let Some(sub) = matches.subcommand_matches(PHONE_COMMAND) {
        payload = payloads::phone_string(sub.value_of("phone").unwrap());
    } else {
        payload = String::from(matches.value_of("INPUT").unwrap());
    }

    let safe: bool = match matches.occurrences_of("safe_zone") {
        0 => true,
        _ => false,
    };

    let code = QrCode::with_error_correction_level(payload, EcLevel::H).unwrap();

    let bit_array = code.to_vec();

    let w = code.width();
    let wide = w + 6;

    //Draw the first white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    for (i, item) in bit_array.iter().enumerate() {
        //left safe zone
        if safe && i % w == 0 {
            print!("{}      ", color::Bg(color::LightWhite));
        }

        if *item {
            print!("{}  ", color::Bg(color::Black));
        } else {
            print!("{}  ", color::Bg(color::LightWhite));
        }

        if (i + 1) % w == 0 {
            if safe {
                //draw right safe zone
                println!("{}      {}",
                         color::Bg(color::LightWhite),
                         color::Bg(color::Reset));
            } else {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    //Draw the last white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }
}
<commit_msg>disabled unused commands for now<commit_after>#[macro_use]
extern crate lazy_static;

extern crate clap;
extern crate qrcode;
extern crate termion;
extern crate image;
extern crate regex;

use clap::{App, Arg, SubCommand};
use qrcode::{QrCode, EcLevel};
use termion::color;

mod payloads;

const WIFI_COMMAND: &'static str = "wifi";
const MAIL_COMMAND: &'static str = "mail";
// const SMS_COMMAND: &'static str = "sms";
// const MMS_COMMAND: &'static str = "mms";
// const GEO_COMMAND: &'static str = "geo";
const PHONE_COMMAND: &'static str = "phone";
// const SKYPE_COMMAND: &'static str = "skype";
const URL_COMMAND: &'static str = "url";
// const BOOKMARK_COMMAND: &'static str = "bookmark";
// const BITCOIN_COMMAND: &'static str = "bitcoin";
// const GIRO_COMMAND: &'static str = "giro";
// const CALENDAR_COMMAND: &'static str = "calendar";

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
*/
fn main() {
    let app = App::new("qrterm")
        .version("0.1")
        .author("Lukas R. <lukas@bootsmann-games.de>")
        .about("Generates and displays terminal friendly QR-Codes from input strings")
        .arg(Arg::with_name("safe_zone") //TODO: change this into an off switch
            .global(true)
            .required(false)
            .short("s")
            .long("safe-zone")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(false)
            )
            //TODO: subcmds are not working like expected, if you have one the system assumes you have many
        .subcommand(SubCommand::with_name(WIFI_COMMAND)
            .about("formats to a wifi access string")
            .arg(Arg::with_name("ssid").required(true))
            .arg(Arg::with_name("pwd").required(true))
            .arg(Arg::with_name("mode")
                .possible_values(&["WEP", "WPA", "nopass"])
                .default_value("WPA")
                .value_name("MODE"))
            .arg(Arg::with_name("hidden")
                .required(false)
                .possible_values(&["true", "false"])
                .default_value("false")
                .value_name("HIDDEN")))
        .subcommand(SubCommand::with_name(MAIL_COMMAND)
            .about("formats to a mail adress string")
            .arg(Arg::with_name("receiver").required(true))
            .arg(Arg::with_name("subject"))
            .arg(Arg::with_name("message"))
            .arg(Arg::with_name("encoding")
                .possible_values(&["MAILTO", "MATMSG", "SMTP"])
                .default_value("MAILTO")
                .value_name("ENCODING")))
        .subcommand(SubCommand::with_name(URL_COMMAND)
            .about("formats to an URL")
            .arg(Arg::with_name("url")
                .required(true)
                .value_name("URL")))
        .subcommand(SubCommand::with_name(PHONE_COMMAND)
            .about("formats to a phone number")
            .arg(Arg::with_name("number")
                .required(true)
                .value_name("NUMBER")))
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required_unless_one(&[WIFI_COMMAND, MAIL_COMMAND, URL_COMMAND, PHONE_COMMAND]));

    let matches = app.get_matches();

    let payload: String;
    if let Some(sub) = matches.subcommand_matches(WIFI_COMMAND) {
        let auth = match sub.value_of("mode") {
            Some("WEP") => payloads::Authentication::WEP,
            Some("WPA") => payloads::Authentication::WPA,
            _ => payloads::Authentication::nopass,
        };
        payload = payloads::wifi_string(sub.value_of("ssid").unwrap(),
                                        sub.value_of("pwd").unwrap(),
                                        &auth,
                                        sub.value_of("hidden").unwrap() == "true");
    } else if let Some(sub) = matches.subcommand_matches(MAIL_COMMAND) {
        let encoding = match sub.value_of("encoding") {
            Some("MAILTO") => payloads::MailEncoding::MAILTO,
            Some("MATMSG") => payloads::MailEncoding::MATMSG,
            Some("SMTP") => payloads::MailEncoding::SMTP,
            _ => payloads::MailEncoding::MAILTO,
        };
        payload = payloads::mail_string(sub.value_of("receiver").unwrap(),
                                        sub.value_of("subject").unwrap(),
                                        sub.value_of("message").unwrap(),
                                        &encoding);
    } else if let Some(sub) = matches.subcommand_matches(URL_COMMAND) {
        payload = payloads::url_string(sub.value_of("url").unwrap());
    } else if let Some(sub) = matches.subcommand_matches(PHONE_COMMAND) {
        payload = payloads::phone_string(sub.value_of("phone").unwrap());
    } else {
        payload = String::from(matches.value_of("INPUT").unwrap());
    }

    let safe: bool = match matches.occurrences_of("safe_zone") {
        0 => true,
        _ => false,
    };

    let code = QrCode::with_error_correction_level(payload, EcLevel::H).unwrap();

    let bit_array = code.to_vec();

    let w = code.width();
    let wide = w + 6;

    //Draw the first white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    for (i, item) in bit_array.iter().enumerate() {
        //left safe zone
        if safe && i % w == 0 {
            print!("{}      ", color::Bg(color::LightWhite));
        }

        if *item {
            print!("{}  ", color::Bg(color::Black));
        } else {
            print!("{}  ", color::Bg(color::LightWhite));
        }

        if (i + 1) % w == 0 {
            if safe {
                //draw right safe zone
                println!("{}      {}",
                         color::Bg(color::LightWhite),
                         color::Bg(color::Reset));
            } else {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    //Draw the last white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(all(test, feature = "nightly"), feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;

#[cfg(not(test))]
use racer::Match;
#[cfg(not(test))]
use racer::util::{getline, path_exists};
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;

pub mod racer;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }
    println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete(match_found: &Fn(Match)) {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[2].parse::<usize>() {
        Ok(linenum) => {
            // input: linenum, colnum, fname
            if args.len() < 5 {
                println!("Provide more arguments!");
                print_usage();
                std::process::exit(1);
            }
            let charnum = args[3].parse::<usize>().unwrap();
            let fname = &args[4];
            let fpath = Path::new(fname);
            let src = racer::load_file(&fpath);
            let line = &*getline(&fpath, linenum);
            let (start, pos) = racer::util::expand_ident(line, charnum);
            println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

            let point = scopes::coords_to_point(&*src, linenum, charnum);
            for m in racer::complete_from_file(&*src, &fpath, point) {
                match_found(m);
            }
        }
        Err(_) => {
            // input: a command line string passed in
            let arg = &args[2];
            let it = arg.split("::");
            let p: Vec<&str> = it.collect();

            for m in do_file_search(p[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_found(m);
                } else {
                    for m in do_external_search(&p[1..], &m.filepath, m.point, racer::SearchType::StartsWith, racer::Namespace::BothNamespaces) {
                        match_found(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &*getline(&path, linenum);
    let (start, pos) = racer::util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];
    let fpath = Path::new(fname);
    let src = racer::load_file(&fpath);
    let pos = scopes::coords_to_point(&*src, linenum, charnum);

    racer::find_definition(&*src, &fpath, pos).map(match_fn);
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname", program);
    println!("or:    {} find-definition linenum charnum fname", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !path_exists(f) {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !f.ends_with("src") {
                println!("RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn main() {
    check_rust_src_env_var();

    // PD: for now install a simple logger
    log::set_logger(|max_log_level| {
        max_log_level.set(log::LogLevelFilter::Warn);
        Box::new(racer::ghetto_logger::SimpleLogger)
    }).unwrap();

    let args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    let command = &args[1][..];
    match command {
        "prefix" => prefix(),
        "complete" => complete(&match_fn),
        "complete-with-snippet" => complete(&match_with_snippet_fn),
        "find-definition" => find_definition(),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<commit_msg>Change RUST_SRC_PATH check to look for /libstd under the first path. Fix for #253<commit_after>#![cfg_attr(all(test, feature = "nightly"), feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;

#[cfg(not(test))]
use racer::Match;
#[cfg(not(test))]
use racer::util::{getline, path_exists};
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;

pub mod racer;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }
    println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn complete(match_found: &Fn(Match)) {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[2].parse::<usize>() {
        Ok(linenum) => {
            // input: linenum, colnum, fname
            if args.len() < 5 {
                println!("Provide more arguments!");
                print_usage();
                std::process::exit(1);
            }
            let charnum = args[3].parse::<usize>().unwrap();
            let fname = &args[4];
            let fpath = Path::new(fname);
            let src = racer::load_file(&fpath);
            let line = &*getline(&fpath, linenum);
            let (start, pos) = racer::util::expand_ident(line, charnum);
            println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

            let point = scopes::coords_to_point(&*src, linenum, charnum);
            for m in racer::complete_from_file(&*src, &fpath, point) {
                match_found(m);
            }
        }
        Err(_) => {
            // input: a command line string passed in
            let arg = &args[2];
            let it = arg.split("::");
            let p: Vec<&str> = it.collect();

            for m in do_file_search(p[0], &Path::new(".")) {
                if p.len() == 1 {
                    match_found(m);
                } else {
                    for m in do_external_search(&p[1..], &m.filepath, m.point, racer::SearchType::StartsWith, racer::Namespace::BothNamespaces) {
                        match_found(m);
                    }
                }
            }
        }
    }
}

#[cfg(not(test))]
fn prefix() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &*getline(&path, linenum);
    let (start, pos) = racer::util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() < 5 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[2].parse::<usize>().unwrap();
    let charnum = args[3].parse::<usize>().unwrap();
    let fname = &args[4];
    let fpath = Path::new(fname);
    let src = racer::load_file(&fpath);
    let pos = scopes::coords_to_point(&*src, linenum, charnum);

    racer::find_definition(&*src, &fpath, pos).map(match_fn);
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname", program);
    println!("or:    {} find-definition linenum charnum fname", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !path_exists(f) {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !path_exists(f.join("libstd")) {
                println!("Unable to find libstd under RUST_SRC_PATH. N.B. RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn main() {
    check_rust_src_env_var();

    // PD: for now install a simple logger
    log::set_logger(|max_log_level| {
        max_log_level.set(log::LogLevelFilter::Warn);
        Box::new(racer::ghetto_logger::SimpleLogger)
    }).unwrap();

    let args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    let command = &args[1][..];
    match command {
        "prefix" => prefix(),
        "complete" => complete(&match_fn),
        "complete-with-snippet" => complete(&match_with_snippet_fn),
        "find-definition" => find_definition(),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>extern crate alpm;
extern crate clap;
extern crate curl;
extern crate env_logger;
extern crate itertools;
extern crate json;
#[macro_use]
extern crate log;
extern crate select;

use clap::{Arg, App};
use curl::easy::Easy;
use itertools::Itertools;
use select::document::Document;
use select::predicate::Name;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::default::Default;
use std::str;

#[derive(Debug)]
struct ASA {
    cve: Vec<String>,
    version: Option<String>,
}

impl Default for ASA {
    fn default() -> ASA {
        ASA {
            cve: Vec::new(),
            version: None,
        }
    }
}

#[derive(Debug)]
struct Options {
    format: Option<String>,
    quiet: u64,
    upgradable_only: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            format: None,
            quiet: 0,
            upgradable_only: false
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args = App::new("arch-audit")
                        .version("0.1.2")
                        .arg(Arg::with_name("format")
                             .short("f")
                             .long("format")
                             .takes_value(true)
                             .help("Specify a format to control the output. Placeholders are %n (pkgname) and %c (CVEs)"))
                        .arg(Arg::with_name("quiet")
                             .short("q")
                             .long("quiet")
                             .multiple(true)
                             .help("Show only vulnerable package names and their versions"))
                        .arg(Arg::with_name("upgradable")
                             .short("u")
                             .long("upgradable")
                             .help("Show only packages that have already been fixed"))
                        .get_matches();

    let options = Options {
        format: {
            if args.is_present("format") {
                Some(args.value_of("format").unwrap().to_string())
            } else {
                None
            } },
        quiet: args.occurrences_of("quiet"),
        upgradable_only: args.is_present("upgradable"),
    };

    let mut wikipage = String::new();
    {
        info!("Downloading CVE wiki page...");
        let wikipage_url = "https://wiki.archlinux.org/api.php?format=json&action=parse&page=CVE&section=5";

        let mut easy = Easy::new();
        easy.url(wikipage_url).unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            wikipage.push_str(str::from_utf8(data).unwrap());
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }

    let json = json::parse(wikipage.as_str()).unwrap();
    let document = Document::from(json["parse"]["text"]["*"].as_str().unwrap());

    let mut infos: HashMap<String, Vec<_>> = HashMap::new();
    for tr in document.find(Name("tbody")).find(Name("tr")).iter() {
        let tds = tr.find(Name("td"));

        match tds.first() {
            Some(td) => {
                let mut next = tds.next().next();
                let pkgname = next.first().unwrap().text().trim().to_string();
                next = next.next().next().next().next().next().next();
                let info = ASA {
                    cve: td.text().split_whitespace().filter(|s| s.starts_with("CVE")).map(|s| s.to_string()).collect(),
                    version: {
                        let v = next.first().unwrap().text().trim().to_string();
                        if !v.is_empty() && v != "?".to_string() && v != "-".to_string() { Some(v) } else { None }
                    },
                };
                next = next.next().next().next().next();
                let status = next.first().unwrap().text().trim().to_string();

                if !status.starts_with("Invalid") && !status.starts_with("Not Affected") {
                  if !infos.contains_key(&pkgname) {
                      infos.insert(pkgname.clone(), Vec::new());
                  }

                  infos.get_mut(&pkgname).unwrap().push(info);
                }
            },
            None => {},
        };
    }

    let pacman = alpm::Alpm::new().unwrap();
    for (pkg, cves) in infos {
        match pacman.query_package_version(pkg.clone()) {
            Ok(v) => {
                info!("Found installed version {} for package {}", v, pkg);
                for cve in cves {
                    match cve.version {
                        Some(version) => {
                            info!("Comparing with fixed version {}", version);
                            match pacman.vercmp(v.clone(), version.clone()).unwrap() {
                                Ordering::Less => { print_asa(&options, &pkg, cve.cve, Some(version) ) },
                                _ => {},
                            };
                        },
                        None => { print_asa(&options, &pkg, cve.cve, None) },
                    };
                };
            },
            Err(_) => { debug!("Package {} not installed", pkg) },
        }
    }
}

fn print_asa(options: &Options, pkgname: &String, cve: Vec<String>, version: Option<String>) {
    let msg = format!("Package {} is affected by {:?}", pkgname, cve);

    match version {
        Some(v) => {
            if options.quiet == 1 {
                println!("{}>={}", pkgname, v);
            } else if options.quiet >= 2 {
                println!("{}", pkgname);
            } else {
                match options.format {
                    Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                    None => { println!("{}. Update to {}!", msg, v) },
                }
            }
        }
        None => {
            if !options.upgradable_only {
                if options.quiet > 0 {
                    println!("{}", pkgname);
                } else {
                    match options.format {
                        Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                        None => { println!("{}. VULNERABLE!", msg) },
                    }
                }
            }
        }
    }
}
<commit_msg>Code refactoring<commit_after>extern crate alpm;
extern crate clap;
extern crate curl;
extern crate env_logger;
extern crate itertools;
extern crate json;
#[macro_use]
extern crate log;
extern crate select;

use clap::{Arg, App};
use curl::easy::Easy;
use itertools::Itertools;
use select::document::Document;
use select::predicate::Name;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::default::Default;
use std::str;

#[derive(Debug)]
struct ASA {
    cve: Vec<String>,
    version: Option<String>,
}

impl Default for ASA {
    fn default() -> ASA {
        ASA {
            cve: Vec::new(),
            version: None,
        }
    }
}

#[derive(Debug)]
struct Options {
    format: Option<String>,
    quiet: u64,
    upgradable_only: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            format: None,
            quiet: 0,
            upgradable_only: false
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let args = App::new("arch-audit")
                        .version("0.1.2")
                        .arg(Arg::with_name("format")
                             .short("f")
                             .long("format")
                             .takes_value(true)
                             .help("Specify a format to control the output. Placeholders are %n (pkgname) and %c (CVEs)"))
                        .arg(Arg::with_name("quiet")
                             .short("q")
                             .long("quiet")
                             .multiple(true)
                             .help("Show only vulnerable package names and their versions"))
                        .arg(Arg::with_name("upgradable")
                             .short("u")
                             .long("upgradable")
                             .help("Show only packages that have already been fixed"))
                        .get_matches();

    let options = Options {
        format: { match args.value_of("format") {
            Some(f) => { Some(f.to_string()) },
            None => { None },
            } },
        quiet: args.occurrences_of("quiet"),
        upgradable_only: args.is_present("upgradable"),
    };

    let mut wikipage = String::new();
    {
        info!("Downloading CVE wiki page...");
        let wikipage_url = "https://wiki.archlinux.org/api.php?format=json&action=parse&page=CVE&section=5";

        let mut easy = Easy::new();
        easy.url(wikipage_url).unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
            wikipage.push_str(str::from_utf8(data).unwrap());
            Ok(data.len())
        }).unwrap();
        transfer.perform().unwrap();
    }

    let mut infos: HashMap<String, Vec<_>> = HashMap::new();
    {
        let json = json::parse(wikipage.as_str()).unwrap();
        let document = Document::from(json["parse"]["text"]["*"].as_str().unwrap());

        for tr in document.find(Name("tbody")).find(Name("tr")).iter() {
            let tds = tr.find(Name("td"));

            match tds.first() {
                Some(td) => {
                    let mut next = tds.next().next();
                    let pkgname = next.first().unwrap().text().trim().to_string();
                    next = next.next().next().next().next().next().next();
                    let info = ASA {
                        cve: td.text().split_whitespace().filter(|s| s.starts_with("CVE")).map(|s| s.to_string()).collect(),
                        version: {
                            let v = next.first().unwrap().text().trim().to_string();
                            if !v.is_empty() && v != "?".to_string() && v != "-".to_string() { Some(v) } else { None }
                        },
                    };
                    next = next.next().next().next().next();
                    let status = next.first().unwrap().text().trim().to_string();

                    if !status.starts_with("Invalid") && !status.starts_with("Not Affected") {
                      if !infos.contains_key(&pkgname) {
                          infos.insert(pkgname.clone(), Vec::new());
                      }

                      infos.get_mut(&pkgname).unwrap().push(info);
                    }
                },
                None => {},
            };
        }
    }

    let pacman = alpm::Alpm::new().unwrap();
    for (pkg, cves) in infos {
        match pacman.query_package_version(pkg.clone()) {
            Ok(v) => {
                info!("Found installed version {} for package {}", v, pkg);
                for cve in cves {
                    match cve.version {
                        Some(version) => {
                            info!("Comparing with fixed version {}", version);
                            match pacman.vercmp(v.clone(), version.clone()).unwrap() {
                                Ordering::Less => { print_asa(&options, &pkg, cve.cve, Some(version) ) },
                                _ => {},
                            };
                        },
                        None => { print_asa(&options, &pkg, cve.cve, None) },
                    };
                };
            },
            Err(_) => { debug!("Package {} not installed", pkg) },
        }
    }
}

fn print_asa(options: &Options, pkgname: &String, cve: Vec<String>, version: Option<String>) {
    let msg = format!("Package {} is affected by {:?}", pkgname, cve);

    match version {
        Some(v) => {
            if options.quiet == 1 {
                println!("{}>={}", pkgname, v);
            } else if options.quiet >= 2 {
                println!("{}", pkgname);
            } else {
                match options.format {
                    Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                    None => { println!("{}. Update to {}!", msg, v) },
                }
            }
        }
        None => {
            if !options.upgradable_only {
                if options.quiet > 0 {
                    println!("{}", pkgname);
                } else {
                    match options.format {
                        Some(ref f) => { println!("{}", f.replace("%n", pkgname).replace("%c", cve.iter().join(",").as_str())) },
                        None => { println!("{}. VULNERABLE!", msg) },
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate ghqrs;
extern crate clap;

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

fn main() {
  let matches = App::new("ghqrs")
    .about("Remote management")
    .version("0.0.1")
    .author("Yusuke Sasaki <yusuke.sasaki.nuem@gmail.com>")
    .subcommand(SubCommand::with_name("list")
      .about("List locally cloned repositories")
      .arg(Arg::with_name("exact")
        .short("e")
        .long("exact")
        .help("Perform an exact match"))
      .arg(Arg::with_name("fullpath")
        .short("p")
        .long("full-path")
        .help("print full paths"))
      .arg(Arg::with_name("unique")
        .long("unique")
        .help("Print unique subpaths"))
      .arg(Arg::with_name("query")))
    .subcommand(SubCommand::with_name("root")
      .about("Show repositories's root")
      .arg(Arg::with_name("all")
        .long("all")
        .help("Show all roots")))
    .get_matches();

  let exitcode = match matches.subcommand_name() {
    Some(ref s) => {
      let ref matches = matches.subcommand_matches(s).unwrap();
      match *s {
        "list" => {
          let exact = matches.is_present("exact");
          let fullpath = matches.is_present("fullpath");
          let unique = matches.is_present("unique");
          let query = matches.value_of("query").map(|s| s.to_owned());
          ghqrs::command_list(exact, fullpath, unique, query)
        }
        "root" => {
          let all = matches.is_present("all");
          ghqrs::command_root(all)
        }
        _ => panic!("invalid subcommand: {}", s),
      }
    }
    None => panic!("Invalid subcommand"),
  };
  std::process::exit(exitcode);
}
<commit_msg>wip: add short option<commit_after>extern crate ghqrs;
extern crate clap;

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

fn main() {
  let matches = App::new("ghqrs")
    .about("Remote management")
    .version("0.0.1")
    .author("Yusuke Sasaki <yusuke.sasaki.nuem@gmail.com>")
    .subcommand(SubCommand::with_name("list")
      .about("List locally cloned repositories")
      .arg(Arg::with_name("exact")
        .short("e")
        .long("exact")
        .help("Perform an exact match"))
      .arg(Arg::with_name("fullpath")
        .short("p")
        .long("full-path")
        .help("print full paths"))
      .arg(Arg::with_name("unique")
        .long("unique")
        .help("Print unique subpaths"))
      .arg(Arg::with_name("query")))
    .subcommand(SubCommand::with_name("root")
      .about("Show repositories's root")
      .arg(Arg::with_name("all")
        .short("a")
        .long("all")
        .help("Show all roots")))
    .get_matches();

  let exitcode = match matches.subcommand_name() {
    Some(ref s) => {
      let ref matches = matches.subcommand_matches(s).unwrap();
      match *s {
        "list" => {
          let exact = matches.is_present("exact");
          let fullpath = matches.is_present("fullpath");
          let unique = matches.is_present("unique");
          let query = matches.value_of("query").map(|s| s.to_owned());
          ghqrs::command_list(exact, fullpath, unique, query)
        }
        "root" => {
          let all = matches.is_present("all");
          ghqrs::command_root(all)
        }
        _ => panic!("invalid subcommand: {}", s),
      }
    }
    None => panic!("Invalid subcommand"),
  };
  std::process::exit(exitcode);
}
<|endoftext|>


<commit_before>use std::ffi::OsStr;
use std::path::PathBuf;

fn home() -> PathBuf {
    std::env::home_dir().unwrap()
}

fn sbt_launch_dir() -> PathBuf {
    let mut p = PathBuf::from(home());
    p.push(".sbt/launchers");
    p
}

fn jar_file(sbt_version: &str) -> PathBuf {
    let mut p = PathBuf::from(sbt_launch_dir());
    p.push(sbt_version);
    p.push("sbt-launch.jar");
    p
}

fn sbt_version() -> String {
    "0.13.13".to_string()
}

fn sbt_jar() -> PathBuf {
    jar_file(&sbt_version())
}

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

fn main() {
    let sbt_jar = sbt_jar();

    let java_cmd = OsStr::new("java");
    let extra_jvm_opts = [OsStr::new("-Xms512m"), OsStr::new("-Xmx1536m"), OsStr::new("-Xss2m")];
    let java_args: [&OsStr; 0] = [];
    let sbt_commands: [&OsStr; 0] = [];
    let residual_args = [OsStr::new("shell")];

    let mut exec_args: Vec<&OsStr> = Vec::new();
    exec_args.push(java_cmd);
    exec_args.extend_from_slice(&extra_jvm_opts);
    exec_args.extend_from_slice(&java_args);
    exec_args.extend_from_slice(&[OsStr::new("-jar"), sbt_jar.as_os_str()]);
    exec_args.extend_from_slice(&sbt_commands);
    exec_args.extend_from_slice(&residual_args);
    let exec_args = exec_args;

    exec_runner(&exec_args)
}
<commit_msg>Found how to define strs & map to OsStrs<commit_after>use std::ffi::OsStr;
use std::path::PathBuf;

fn home() -> PathBuf {
    std::env::home_dir().unwrap()
}

fn sbt_launch_dir() -> PathBuf {
    let mut p = PathBuf::from(home());
    p.push(".sbt/launchers");
    p
}

fn jar_file(sbt_version: &str) -> PathBuf {
    let mut p = PathBuf::from(sbt_launch_dir());
    p.push(sbt_version);
    p.push("sbt-launch.jar");
    p
}

fn sbt_version() -> String {
    "0.13.13".to_string()
}

fn sbt_jar() -> PathBuf {
    jar_file(&sbt_version())
}

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

fn main() {
    let sbt_jar = sbt_jar();

    let java_cmd = "java";
    let extra_jvm_opts = ["-Xms512m", "-Xmx1536m", "-Xss2m"];
    let java_args: [&OsStr; 0] = [];
    let sbt_commands: [&OsStr; 0] = [];
    let residual_args = ["shell"];

    let mut exec_args: Vec<&OsStr> = Vec::new();
    exec_args.push(OsStr::new(java_cmd));
    exec_args.extend_from_slice(&extra_jvm_opts.iter().map(|x| OsStr::new(x)).collect::<Vec<_>>());
    exec_args.extend_from_slice(&java_args.iter().map(|x| OsStr::new(x)).collect::<Vec<_>>());
    exec_args.extend_from_slice(&[OsStr::new("-jar"), sbt_jar.as_os_str()]);
    exec_args.extend_from_slice(&sbt_commands.iter().map(|x| OsStr::new(x)).collect::<Vec<_>>());
    exec_args.extend_from_slice(&residual_args.iter().map(|x| OsStr::new(x)).collect::<Vec<_>>());
    let exec_args = exec_args;

    exec_runner(&exec_args)
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;
extern crate x11;

use std::ffi::{ CStr, CString };
use std::os::raw::{c_int, c_char, c_long, c_ulong, c_void};
use std::ptr;
use std::convert::From;

use x11::xlib;
use x11::xlib::{BadAccess, Display, XErrorEvent, XOpenDisplay, XDefaultRootWindow,
                XSetErrorHandler};

mod debug;
mod keys;
mod layout;
mod window;

use window::Window;
use layout::{Layout, TiledLayout};
use keys::Key;

struct Config {
    keys: Vec<Key>,
    layout: Box<Layout>,
}

pub struct RustWindowManager {
    display: *mut Display,
    root: xlib::Window,

    config: Config,

    stack: Vec<Window>,
    // Focus is an index into the stack. We could do better and use the borrow checker to ensure
    // that it doesn't point at the wrong data when an item is added/removed from the stack.
    focus: Option<usize>
}

impl RustWindowManager {
    fn new(config: Config) -> Result<Self, String> {
        let (display, root) = unsafe {
            let display: *mut xlib::Display = xlib::XOpenDisplay(ptr::null_mut());
            if display.is_null() {
                return Err("XOpenDisplay() returned null".to_owned());
            }

            let root: xlib::Window = xlib::XDefaultRootWindow(display);
            if root == 0 {
                return Err("XDefaultRootWindow returned 0".to_owned());
            }

            (display, root)
        };

        // Install ourselves as the WM.
        unsafe {
            // It's tricky to get state from the error handler to here, so we install a special handler
            // while becoming the WM that panics on error.
            XSetErrorHandler(Some(debug::error_handler_init));
            xlib::XSelectInput(display,
                            root,
                            xlib::SubstructureNotifyMask | xlib::SubstructureRedirectMask);
            xlib::XSync(display, 0);

            // If we get this far, then our error handler didn't panic. Set a more useful error handler.
            XSetErrorHandler(Some(debug::error_handler));
        }

        Ok(RustWindowManager {
            display: display,
            root: root,

            config: config,

            stack: Vec::new(),
            focus: None,
        })
    }

    fn layout(&mut self) -> Result<(), String> {
        let (width, height) = unsafe {
            let mut attrs: xlib::XWindowAttributes = std::mem::zeroed();
            xlib::XGetWindowAttributes(self.display, self.root, &mut attrs);
            info!("Root window has geometry: {}x{}", attrs.width, attrs.height);
            (attrs.width, attrs.height)
        };

        self.config.layout.layout(width, height, &mut self.stack)
    }

    fn get_focused(&self) -> Option<&Window> {
        self.focus.map(|i| &self.stack[i])
    }
}

fn get_wm_protocols(window: &Window) -> Vec<String> {
    let mut atoms: *mut c_ulong = ptr::null_mut();
    let mut count: c_int = 0;
    unsafe {
        xlib::XGetWMProtocols(window.display, window.xwindow, &mut atoms, &mut count);
    }

    if atoms.is_null() {
        error!("XGetWMProtocols returned null pointer");
        return Vec::new();
    }
    if count == 0 {
        return Vec::new();
    }

    let mut pointers: Vec<*mut c_char> = Vec::with_capacity(count as usize);
    let protocols: Vec<String> = unsafe {
        xlib::XGetAtomNames(window.display, atoms, count, pointers.as_mut_ptr());
        pointers.set_len(count as usize);
        pointers.iter()
            .map(|buffer| CStr::from_ptr(*buffer).to_str().unwrap().to_owned())
            .collect()
    };

    unsafe {
        for pointer in pointers.iter() {
            xlib::XFree(*pointer as *mut c_void);
        }
        xlib::XFree(atoms as *mut c_void);
    }

    protocols
}

fn intern_atom(display: *mut xlib::Display, s: &str) -> xlib::Atom {
    // Note: it is important that the CString is bound to a variable to ensure adequate lifetime.
    let cstring = CString::new(s).unwrap();
    let ptr = cstring.as_ptr() as *const c_char;
    unsafe {
        xlib::XInternAtom(display, ptr, 0)
    }
}

fn close_window(wm: &RustWindowManager) {
    if let Some(window) = wm.get_focused() {
        // Does it support WM_DELETE_WINDOW ICCCM protocol?
        // TODO: Avoid converting atoms to strings.
        let protocols = get_wm_protocols(window);
        let has_wm_delete_window = protocols.contains(&"WM_DELETE_WINDOW".to_owned());

        if !has_wm_delete_window {
            error!("Could not close window as it doesn't support WM_DELETE_WINDOW");
        }

        let ATOM_WM_PROTOCOLS = intern_atom(wm.display, "WM_PROTOCOLS");
        let ATOM_WM_DELETE_WINDOW = intern_atom(wm.display, "WM_DELETE_WINDOW");
        debug!("Atoms: {} {}", ATOM_WM_PROTOCOLS, ATOM_WM_DELETE_WINDOW);

        info!("Sending WM_DELETE_WINDOW to {}", window.xwindow);
        let mut client_message = xlib::XClientMessageEvent {
            type_: xlib::ClientMessage,
            serial: 0,
            send_event: 0,
            display: ptr::null_mut(),
            window: window.xwindow,
            message_type: ATOM_WM_PROTOCOLS,
            format: 32,
            data: xlib::ClientMessageData::new(),
        };
        client_message.data.set_long(0, ATOM_WM_DELETE_WINDOW as c_long);
        client_message.data.set_long(1, xlib::CurrentTime as c_long);
        let mut event = xlib::XEvent::from(client_message);
        unsafe {
            xlib::XSendEvent(wm.display, window.xwindow, 0, xlib::NoEventMask, &mut event);
        }
        info!("Sent WM_DELETE_WINDOW to {}", window.xwindow);
    }
}

fn main() {
    env_logger::init().unwrap();

    let keys = vec![Key {
                        mod_mask: xlib::Mod4Mask,
                        keysym: x11::keysym::XK_T,
                        handler: Box::new(close_window),
                    }];
    let layout = Box::new(TiledLayout {});
    let config = Config { keys: keys, layout: layout };

    let mut wm = RustWindowManager::new(config).unwrap();

    unsafe {
        loop {
            let mut event = xlib::XEvent { pad: [0; 24] };
            xlib::XNextEvent(wm.display, &mut event);
            info!("Received event: {}", debug::xevent_to_str(&event));

            match event.get_type() {
                // Pass through ConfigureRequests unchanged.
                xlib::ConfigureRequest => {
                    let event = xlib::XConfigureRequestEvent::from(event);

                    let mut changes = xlib::XWindowChanges {
                        x: event.x,
                        y: event.y,
                        width: event.width,
                        height: event.height,
                        border_width: event.border_width,
                        sibling: event.above,
                        stack_mode: event.detail,
                    };
                    xlib::XConfigureWindow(wm.display, event.window, event.value_mask as u32, &mut changes);
                }

                xlib::MapRequest => {
                    let event = xlib::XMapRequestEvent::from(event);
                    let mut window = Window {
                        display: wm.display,
                        xwindow: event.window,
                    };
                    window.grab_keys(&wm.config.keys);

                    xlib::XSelectInput(wm.display, window.xwindow, xlib::EnterWindowMask);

                    wm.stack.push(window);

                    wm.layout();

                    // TODO: Make this into a method on Win?
                    xlib::XMapWindow(wm.display, event.window);

                }

                xlib::DestroyNotify => {
                    let event = xlib::XDestroyWindowEvent::from(event);

                    wm.stack.iter().position(|ref w| w.xwindow == event.window).map(|index| wm.stack.remove(index));

                    wm.layout();
                }

                xlib::KeyPress => {
                    let event = xlib::XKeyEvent::from(event);

                    for key in wm.config.keys.iter() {
                        let keycode = xlib::XKeysymToKeycode(wm.display, key.keysym as u64) as u32;
                        debug!("KeyPress: state={}, keycode={}", event.state, event.keycode);

                        // TODO: Allow extra mod keys to be pressed at the same time. (Add test!)
                        if (event.state & key.mod_mask != 0) && event.keycode == keycode {
                            info!("KeyPress matches key: {}", key);
                            (key.handler)(&wm);
                            break;
                        }
                    }

                }

                xlib::EnterNotify => {
                    let event = xlib::XEnterWindowEvent::from(event);

                    wm.focus = wm.stack.iter().position(|ref w| w.xwindow == event.window);
                    debug!("EnterNotify: {:?}", wm.focus);
                }

                _ => {}
            }

            println!("Stack: {:?}", wm.stack);
        }

    };
    println!("Hello, world!");
}
<commit_msg>Use xlib:: for all Xlib types.<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;
extern crate x11;

use std::ffi::{ CStr, CString };
use std::os::raw::{c_int, c_char, c_long, c_ulong, c_void};
use std::ptr;
use std::convert::From;

use x11::xlib;

mod debug;
mod keys;
mod layout;
mod window;

use window::Window;
use layout::{Layout, TiledLayout};
use keys::Key;

struct Config {
    keys: Vec<Key>,
    layout: Box<Layout>,
}

pub struct RustWindowManager {
    display: *mut xlib::Display,
    root: xlib::Window,

    config: Config,

    stack: Vec<Window>,
    // Focus is an index into the stack. We could do better and use the borrow checker to ensure
    // that it doesn't point at the wrong data when an item is added/removed from the stack.
    focus: Option<usize>
}

impl RustWindowManager {
    fn new(config: Config) -> Result<Self, String> {
        let (display, root) = unsafe {
            let display: *mut xlib::Display = xlib::XOpenDisplay(ptr::null_mut());
            if display.is_null() {
                return Err("XOpenDisplay() returned null".to_owned());
            }

            let root: xlib::Window = xlib::XDefaultRootWindow(display);
            if root == 0 {
                return Err("XDefaultRootWindow returned 0".to_owned());
            }

            (display, root)
        };

        // Install ourselves as the WM.
        unsafe {
            // It's tricky to get state from the error handler to here, so we install a special handler
            // while becoming the WM that panics on error.
            xlib::XSetErrorHandler(Some(debug::error_handler_init));
            xlib::XSelectInput(display,
                            root,
                            xlib::SubstructureNotifyMask | xlib::SubstructureRedirectMask);
            xlib::XSync(display, 0);

            // If we get this far, then our error handler didn't panic. Set a more useful error handler.
            xlib::XSetErrorHandler(Some(debug::error_handler));
        }

        Ok(RustWindowManager {
            display: display,
            root: root,

            config: config,

            stack: Vec::new(),
            focus: None,
        })
    }

    fn layout(&mut self) -> Result<(), String> {
        let (width, height) = unsafe {
            let mut attrs: xlib::XWindowAttributes = std::mem::zeroed();
            xlib::XGetWindowAttributes(self.display, self.root, &mut attrs);
            info!("Root window has geometry: {}x{}", attrs.width, attrs.height);
            (attrs.width, attrs.height)
        };

        self.config.layout.layout(width, height, &mut self.stack)
    }

    fn get_focused(&self) -> Option<&Window> {
        self.focus.map(|i| &self.stack[i])
    }
}

fn get_wm_protocols(window: &Window) -> Vec<String> {
    let mut atoms: *mut c_ulong = ptr::null_mut();
    let mut count: c_int = 0;
    unsafe {
        xlib::XGetWMProtocols(window.display, window.xwindow, &mut atoms, &mut count);
    }

    if atoms.is_null() {
        error!("XGetWMProtocols returned null pointer");
        return Vec::new();
    }
    if count == 0 {
        return Vec::new();
    }

    let mut pointers: Vec<*mut c_char> = Vec::with_capacity(count as usize);
    let protocols: Vec<String> = unsafe {
        xlib::XGetAtomNames(window.display, atoms, count, pointers.as_mut_ptr());
        pointers.set_len(count as usize);
        pointers.iter()
            .map(|buffer| CStr::from_ptr(*buffer).to_str().unwrap().to_owned())
            .collect()
    };

    unsafe {
        for pointer in pointers.iter() {
            xlib::XFree(*pointer as *mut c_void);
        }
        xlib::XFree(atoms as *mut c_void);
    }

    protocols
}

fn intern_atom(display: *mut xlib::Display, s: &str) -> xlib::Atom {
    // Note: it is important that the CString is bound to a variable to ensure adequate lifetime.
    let cstring = CString::new(s).unwrap();
    let ptr = cstring.as_ptr() as *const c_char;
    unsafe {
        xlib::XInternAtom(display, ptr, 0)
    }
}

fn close_window(wm: &RustWindowManager) {
    if let Some(window) = wm.get_focused() {
        // Does it support WM_DELETE_WINDOW ICCCM protocol?
        // TODO: Avoid converting atoms to strings.
        let protocols = get_wm_protocols(window);
        let has_wm_delete_window = protocols.contains(&"WM_DELETE_WINDOW".to_owned());

        if !has_wm_delete_window {
            error!("Could not close window as it doesn't support WM_DELETE_WINDOW");
        }

        let ATOM_WM_PROTOCOLS = intern_atom(wm.display, "WM_PROTOCOLS");
        let ATOM_WM_DELETE_WINDOW = intern_atom(wm.display, "WM_DELETE_WINDOW");
        debug!("Atoms: {} {}", ATOM_WM_PROTOCOLS, ATOM_WM_DELETE_WINDOW);

        info!("Sending WM_DELETE_WINDOW to {}", window.xwindow);
        let mut client_message = xlib::XClientMessageEvent {
            type_: xlib::ClientMessage,
            serial: 0,
            send_event: 0,
            display: ptr::null_mut(),
            window: window.xwindow,
            message_type: ATOM_WM_PROTOCOLS,
            format: 32,
            data: xlib::ClientMessageData::new(),
        };
        client_message.data.set_long(0, ATOM_WM_DELETE_WINDOW as c_long);
        client_message.data.set_long(1, xlib::CurrentTime as c_long);
        let mut event = xlib::XEvent::from(client_message);
        unsafe {
            xlib::XSendEvent(wm.display, window.xwindow, 0, xlib::NoEventMask, &mut event);
        }
        info!("Sent WM_DELETE_WINDOW to {}", window.xwindow);
    }
}

fn main() {
    env_logger::init().unwrap();

    let keys = vec![Key {
                        mod_mask: xlib::Mod4Mask,
                        keysym: x11::keysym::XK_T,
                        handler: Box::new(close_window),
                    }];
    let layout = Box::new(TiledLayout {});
    let config = Config { keys: keys, layout: layout };

    let mut wm = RustWindowManager::new(config).unwrap();

    unsafe {
        loop {
            let mut event = xlib::XEvent { pad: [0; 24] };
            xlib::XNextEvent(wm.display, &mut event);
            info!("Received event: {}", debug::xevent_to_str(&event));

            match event.get_type() {
                // Pass through ConfigureRequests unchanged.
                xlib::ConfigureRequest => {
                    let event = xlib::XConfigureRequestEvent::from(event);

                    let mut changes = xlib::XWindowChanges {
                        x: event.x,
                        y: event.y,
                        width: event.width,
                        height: event.height,
                        border_width: event.border_width,
                        sibling: event.above,
                        stack_mode: event.detail,
                    };
                    xlib::XConfigureWindow(wm.display, event.window, event.value_mask as u32, &mut changes);
                }

                xlib::MapRequest => {
                    let event = xlib::XMapRequestEvent::from(event);
                    let mut window = Window {
                        display: wm.display,
                        xwindow: event.window,
                    };
                    window.grab_keys(&wm.config.keys);

                    xlib::XSelectInput(wm.display, window.xwindow, xlib::EnterWindowMask);

                    wm.stack.push(window);

                    wm.layout();

                    // TODO: Make this into a method on Win?
                    xlib::XMapWindow(wm.display, event.window);

                }

                xlib::DestroyNotify => {
                    let event = xlib::XDestroyWindowEvent::from(event);

                    wm.stack.iter().position(|ref w| w.xwindow == event.window).map(|index| wm.stack.remove(index));

                    wm.layout();
                }

                xlib::KeyPress => {
                    let event = xlib::XKeyEvent::from(event);

                    for key in wm.config.keys.iter() {
                        let keycode = xlib::XKeysymToKeycode(wm.display, key.keysym as u64) as u32;
                        debug!("KeyPress: state={}, keycode={}", event.state, event.keycode);

                        // TODO: Allow extra mod keys to be pressed at the same time. (Add test!)
                        if (event.state & key.mod_mask != 0) && event.keycode == keycode {
                            info!("KeyPress matches key: {}", key);
                            (key.handler)(&wm);
                            break;
                        }
                    }

                }

                xlib::EnterNotify => {
                    let event = xlib::XEnterWindowEvent::from(event);

                    wm.focus = wm.stack.iter().position(|ref w| w.xwindow == event.window);
                    debug!("EnterNotify: {:?}", wm.focus);
                }

                _ => {}
            }

            println!("Stack: {:?}", wm.stack);
        }

    };
    println!("Hello, world!");
}
<|endoftext|>


<commit_before>extern crate specs;

use specs::Join;
use std::io::prelude::*;
use std::io;
use std::io::BufReader;
use std::fs::File;

static MAP: &'static str = include_str!("../map");

#[derive(Copy, Clone, Debug, PartialEq)]
struct Tile {
    c: char,
}

impl specs::Component for Tile {
    type Storage = specs::VecStorage<Tile>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct PlayerController;

#[derive(Copy, Clone, Debug, PartialEq)]
struct NonPlayerController;

#[derive(Copy, Clone, Debug, PartialEq)]
struct RenderController;

#[derive(Copy, Clone, Debug, PartialEq)]
struct ImmovableController;

impl specs::Component for PlayerController {
    type Storage = specs::VecStorage<PlayerController >;
}

impl specs::Component for NonPlayerController {
    type Storage = specs::VecStorage<NonPlayerController >;
}

impl specs::Component for RenderController {
    type Storage = specs::VecStorage<RenderController >;
}

impl specs::Component for ImmovableController {
    type Storage = specs::VecStorage<ImmovableController>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct Position {
    x: i32,
    y: i32,
}

impl specs::Component for Position {
    type Storage = specs::VecStorage<Position>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct Velocity {
    dx: i32,
    dy: i32,
}

impl specs::Component for Velocity {
    type Storage = specs::VecStorage<Velocity>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct Size {
    w: i32,
    h: i32,
}

impl specs::Component for Size {
    type Storage = specs::VecStorage<Size>;
}

#[derive(Clone, Debug, PartialEq)]
struct WorldMap(Vec<char>);

#[derive(Clone, Debug)]
struct Command(String);

//#[cfg(not(feature="parallel"))]
//fn main() {
//}
//
//#[cfg(feature="parallel")]
fn main() {
    let map_width = 10;
    let height = 10;
    let mut lines: Vec<&str> = MAP.lines().collect();
    let map_settings = lines.remove(0);
    for word in map_settings.split_whitespace() {
    }
    let map: Vec<char> = lines.iter().flat_map(|line| line.chars()).collect();

    let mut planner = {
        let mut w = specs::World::new();
        w.register::<Size>();
        w.register::<Tile>();
        w.register::<Position>();
        w.register::<Velocity>();
        w.register::<PlayerController>();
        w.register::<NonPlayerController>();
        w.register::<RenderController>();
        w.register::<ImmovableController>();

        // Entities
        let _player = w.create_now()
            .with(Tile { c: 'X' })
            .with(Velocity { dx: 0, dy: 0 })
            .with(Position { x: 0, y: 0 })
            .with(PlayerController)
            .with(Size { w: 1, h: 1 })
            .build();

        let _view = w.create_now()
            .with(Position { x: 0, y: 0 })
            .with(Size { w: 10, h: 10 })
            .with(RenderController)
            .build();

        for (i, tile) in map.iter().enumerate() {
            let _map_tile = w.create_now()
                .with(ImmovableController)
                .with(Size { w: 1, h: 1 })
                .with(Position { x: i as i32 % map_width, y: i as i32 / map_width, })
                .with(Tile { c: tile.clone() })
                .build();
        }

        // resources can be installed, these are nothing fancy, but allow you
        // to pass data to systems and follow the same sync strategy as the
        // component storage does.
        w.add_resource(Command(String::new()));

        // Planner is used to run systems on the specified world with a specified number of threads
        (specs::Planner::<()>::new(w, 4))
    };
    loop {
        planner.run_custom(|arg| {
            let (mut positions, velocities) = arg.fetch(|w| {
                (w.write::<Position>(), w.read::<Velocity>())
            });

            for (mut p, v) in (&mut positions, &velocities).iter() {
                p.x += v.dx;
                p.y += v.dy;
                println!("{:?}", p);
            }
        });

        planner.wait();

        // render view
        planner.run_custom(|arg| {
            let (tiles, positions) = arg.fetch(|w| {
                (w.read::<Tile>(), w.read::<Position>())
            });
            let mut output = vec![vec![' ';11];10];

            for (tile, position) in (&tiles, &positions).iter() {
                //println!("{:?} {:?}", tile, position);
                output[position.y as usize].insert(position.x as usize, tile.c);
            }
            for out in output {
                let out: String = out.into_iter().collect();
                println!("{}", out);
            }
        });

        planner.wait();

        // set view
        planner.run_custom(|arg| {
            let (mut positions, players, views, map_objects, sizes, entities) = arg.fetch(|w| {
                (w.write::<Position>(), w.read::<PlayerController>(), w.read::<RenderController>(),
                w.read::<ImmovableController>(), w.read::<Size>(),
                w.entities())
            });

            let mut pos = (None, None);
            for (_, position) in (&players, &positions).iter() {
                pos.0 = Some(position.x);
                pos.1 = Some(position.y);
                break;
            }

            if let (Some(x), Some(y)) = pos {
                for (_, size, entity) in (&views, &sizes, &entities).iter() {
                    let view_pos = positions.get_mut(entity)
                        .expect("render controller expect position component");
                    let w = size.w / 2;
                    let h = size.h / 2;
                    if x > w { view_pos.x = x - (size.w / 2); }
                    if y > h { view_pos.y = y - (size.h / 2); }
                }
            }
        });

        // get input
        planner.run_custom(|arg| {
            let mut cmd = arg.fetch(|w| {
                (w.write_resource::<Command>())
            });
            let mut input = String::new();
            if let Ok(_) = io::stdin().read_line(&mut input) {
                cmd.0 = input;
            }
        });

        planner.wait();

        // process input
        planner.run_custom(|arg| {
            let (mut velocities, players, cmds, entities) = arg.fetch(|w| {
                (w.write::<Velocity>(), w.read::<PlayerController>(),
                 w.read_resource::<Command>(), w.entities())
            });
            let mut commands: Vec<&str> = cmds.0.split_whitespace()
                .rev()
                .collect();

            for (_, entity) in (&players, &entities).iter() {
                let velocity = velocities.get_mut(entity)
                    .expect("player controller expect velocity");
                let mut dx = 0;
                let mut dy = 0;
                while let Some(word) = commands.pop() {
                    match word {
                        "left" | "l" => {
                            if let Some(val) = commands.pop() {
                                dx -= val.parse::<i32>().unwrap_or(1);
                            } else {
                                dx -= 1;
                            }
                        }
                        "right" | "r" => {
                            if let Some(val) = commands.pop() {
                                dx += val.parse::<i32>().unwrap_or(1);
                            } else {
                                dx += 1;
                            }
                        }
                        "up" | "u" => {
                            if let Some(val) = commands.pop() {
                                dy -= val.parse::<i32>().unwrap_or(1);
                            } else {
                                dy -= 1;
                            }
                        }
                        "down" | "d" => {
                            if let Some(val) = commands.pop() {
                                dy += val.parse::<i32>().unwrap_or(1);
                            } else {
                                dy += 1;
                            }
                        }
                        _ => {}
                    }
                }
                velocity.dx += dx;
                velocity.dy += dy;
                println!("{:?}", velocity);
            }
        });

        planner.wait();
    }
}
<commit_msg>Fix render with replacement.<commit_after>extern crate specs;

use specs::Join;
use std::io::prelude::*;
use std::io;
use std::io::BufReader;
use std::fs::File;

static MAP: &'static str = include_str!("../map");

#[derive(Copy, Clone, Debug, PartialEq)]
struct Tile {
    c: char,
}

impl specs::Component for Tile {
    type Storage = specs::VecStorage<Tile>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct PlayerController;

#[derive(Copy, Clone, Debug, PartialEq)]
struct NonPlayerController;

#[derive(Copy, Clone, Debug, PartialEq)]
struct RenderController;

#[derive(Copy, Clone, Debug, PartialEq)]
struct ImmovableController;

impl specs::Component for PlayerController {
    type Storage = specs::VecStorage<PlayerController >;
}

impl specs::Component for NonPlayerController {
    type Storage = specs::VecStorage<NonPlayerController >;
}

impl specs::Component for RenderController {
    type Storage = specs::VecStorage<RenderController >;
}

impl specs::Component for ImmovableController {
    type Storage = specs::VecStorage<ImmovableController>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct Position {
    x: i32,
    y: i32,
}

impl specs::Component for Position {
    type Storage = specs::VecStorage<Position>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct Velocity {
    dx: i32,
    dy: i32,
}

impl specs::Component for Velocity {
    type Storage = specs::VecStorage<Velocity>;
}

#[derive(Copy, Clone, Debug, PartialEq)]
struct Size {
    w: i32,
    h: i32,
}

impl specs::Component for Size {
    type Storage = specs::VecStorage<Size>;
}

#[derive(Clone, Debug, PartialEq)]
struct WorldMap(Vec<char>);

#[derive(Clone, Debug)]
struct Command(String);

//#[cfg(not(feature="parallel"))]
//fn main() {
//}
//
//#[cfg(feature="parallel")]
fn main() {
    let map_width = 10;
    let height = 10;
    let mut lines: Vec<&str> = MAP.lines().collect();
    let map_settings = lines.remove(0);
    for word in map_settings.split_whitespace() {
    }
    let map: Vec<char> = lines.iter().flat_map(|line| line.chars()).collect();

    let mut planner = {
        let mut w = specs::World::new();
        w.register::<Size>();
        w.register::<Tile>();
        w.register::<Position>();
        w.register::<Velocity>();
        w.register::<PlayerController>();
        w.register::<NonPlayerController>();
        w.register::<RenderController>();
        w.register::<ImmovableController>();

        // Entities
        let _player = w.create_now()
            .with(Tile { c: 'X' })
            .with(Velocity { dx: 0, dy: 0 })
            .with(Position { x: 0, y: 0 })
            .with(PlayerController)
            .with(Size { w: 1, h: 1 })
            .build();

        let _view = w.create_now()
            .with(Position { x: 0, y: 0 })
            .with(Size { w: 10, h: 10 })
            .with(RenderController)
            .build();

        for (i, tile) in map.iter().enumerate() {
            let _map_tile = w.create_now()
                .with(ImmovableController)
                .with(Size { w: 1, h: 1 })
                .with(Position { x: i as i32 % map_width, y: i as i32 / map_width, })
                .with(Tile { c: tile.clone() })
                .build();
        }

        // resources can be installed, these are nothing fancy, but allow you
        // to pass data to systems and follow the same sync strategy as the
        // component storage does.
        w.add_resource(Command(String::new()));

        // Planner is used to run systems on the specified world with a specified number of threads
        (specs::Planner::<()>::new(w, 4))
    };
    loop {
        planner.run_custom(|arg| {
            let (mut positions, velocities) = arg.fetch(|w| {
                (w.write::<Position>(), w.read::<Velocity>())
            });

            for (mut p, v) in (&mut positions, &velocities).iter() {
                p.x += v.dx;
                p.y += v.dy;
                println!("{:?}", p);
            }
        });

        planner.wait();

        // render view
        planner.run_custom(|arg| {
            let (tiles, positions, players, map_objects) = arg.fetch(|w| {
                (w.read::<Tile>(), w.read::<Position>(), w.read::<PlayerController>(),
                w.read::<ImmovableController>())
            });
            let mut output = vec![vec![' ';10];10];

            for (tile, position, _) in (&tiles, &positions, &map_objects).iter() {
                //println!("{:?} {:?}", tile, position);
                let _ = output[position.y as usize].remove(position.x as usize);
                output[position.y as usize].insert(position.x as usize, tile.c);
            }
            for (tile, position, _) in (&tiles, &positions, &players).iter() {
                //println!("{:?} {:?}", tile, position);
                let _ = output[position.y as usize].remove(position.x as usize);
                output[position.y as usize].insert(position.x as usize, tile.c);
            }
            for out in output {
                let out: String = out.into_iter().collect();
                println!("{}", out);
            }
        });

        planner.wait();

        // set view
        planner.run_custom(|arg| {
            let (mut positions, players, views, map_objects, sizes, entities) = arg.fetch(|w| {
                (w.write::<Position>(), w.read::<PlayerController>(), w.read::<RenderController>(),
                w.read::<ImmovableController>(), w.read::<Size>(),
                w.entities())
            });

            let mut pos = (None, None);
            for (_, position) in (&players, &positions).iter() {
                pos.0 = Some(position.x);
                pos.1 = Some(position.y);
                break;
            }

            if let (Some(x), Some(y)) = pos {
                for (_, size, entity) in (&views, &sizes, &entities).iter() {
                    let view_pos = positions.get_mut(entity)
                        .expect("render controller expect position component");
                    let w = size.w / 2;
                    let h = size.h / 2;
                    if x > w { view_pos.x = x - (size.w / 2); }
                    if y > h { view_pos.y = y - (size.h / 2); }
                }
            }
        });

        // get input
        planner.run_custom(|arg| {
            let mut cmd = arg.fetch(|w| {
                (w.write_resource::<Command>())
            });
            let mut input = String::new();
            if let Ok(_) = io::stdin().read_line(&mut input) {
                cmd.0 = input;
            }
        });

        planner.wait();

        // process input
        planner.run_custom(|arg| {
            let (mut velocities, players, cmds, entities) = arg.fetch(|w| {
                (w.write::<Velocity>(), w.read::<PlayerController>(),
                 w.read_resource::<Command>(), w.entities())
            });
            let mut commands: Vec<&str> = cmds.0.split_whitespace()
                .rev()
                .collect();

            for (_, entity) in (&players, &entities).iter() {
                let velocity = velocities.get_mut(entity)
                    .expect("player controller expect velocity");
                let mut dx = 0;
                let mut dy = 0;
                while let Some(word) = commands.pop() {
                    match word {
                        "left" | "l" => {
                            if let Some(val) = commands.pop() {
                                dx -= val.parse::<i32>().unwrap_or(1);
                            } else {
                                dx -= 1;
                            }
                        }
                        "right" | "r" => {
                            if let Some(val) = commands.pop() {
                                dx += val.parse::<i32>().unwrap_or(1);
                            } else {
                                dx += 1;
                            }
                        }
                        "up" | "u" => {
                            if let Some(val) = commands.pop() {
                                dy -= val.parse::<i32>().unwrap_or(1);
                            } else {
                                dy -= 1;
                            }
                        }
                        "down" | "d" => {
                            if let Some(val) = commands.pop() {
                                dy += val.parse::<i32>().unwrap_or(1);
                            } else {
                                dy += 1;
                            }
                        }
                        _ => {}
                    }
                }
                velocity.dx += dx;
                velocity.dy += dy;
                println!("{:?}", velocity);
            }
        });

        planner.wait();
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

use std::time::Duration;
use std::path::PathBuf;

use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(name = "RRG", about = "A GRR agent rewritten in Rust.")]
pub struct Opts {
    #[structopt(long="log-verbosity", name="LEVEL", default_value="info",
                help="Specifies the level of log verbosity")]
    pub log_verbosity: Verbosity,

    #[structopt(long="log-std", name="STD",
                help="Enables logging to the specified standard stream")]
    pub log_std: Option<Std>,

    #[structopt(long="log-file", name="FILE",
                help="Enables logging to the specified file")]
    pub log_file: Option<PathBuf>,

    #[structopt(long="heartbeat-rate", name="DURATION", default_value="5s",
                parse(try_from_str = humantime::parse_duration),
                help="Specifies the frequency of heartbeat messages")]
    pub heartbeat_rate: Duration,
}

pub fn from_args() -> Opts {
    Opts::from_args()
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Verbosity {
    level: log::LevelFilter,
}

impl Verbosity {

    pub fn level(&self) -> log::LevelFilter {
        self.level
    }
}

impl std::str::FromStr for Verbosity {

    type Err = String; // TODO.

    fn from_str(string: &str) -> std::result::Result<Verbosity, String> {
        use log::LevelFilter::*;

        let level = match string {
            "quiet" => Off,
            "error" => Error,
            "warn" => Warn,
            "info" => Info,
            "debug" => Debug,
            "trace" => Trace,
            _ => return Err(format!("invalid verbosity choice '{}'", string)),
        };

        Ok(Verbosity {
            level: level,
        })
    }
}

// TODO: This should just be a wrapper around `simplelog::TerminalMode`, but
// it does not implement standard traits. So, for now, we just re-implement it
// like that.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Std {
    Out,
    Err,
    Mix,
}

impl Std {

    pub fn mode(&self) -> simplelog::TerminalMode {
        use simplelog::TerminalMode::*;

        match self {
            Std::Out => Stdout,
            Std::Err => Stderr,
            Std::Mix => Mixed,
        }
    }
}

impl std::str::FromStr for Std {

    type Err = String; // TODO.

    fn from_str(string: &str) -> std::result::Result<Std, String> {
        match string {
            "out" => Ok(Std::Out),
            "err" => Ok(Std::Err),
            "mix" => Ok(Std::Mix),
            _ => Err(format!("invalid std choice '{}'", string)),
        }
    }
}
<commit_msg>Write docs for command-line options.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Structured specification of command-line arguments.
//!
//! This module specifies all command-line arguments that RRG offers and exposes
//! functions for parsing them into a high-level structure.
//!
//! Ideally, only one instance of this high-level structure should ever be
//! created (using the [`from_args`] function). Then this instance should be
//! shared through the entire lifetime of a program and explicitly passed to
//! functions that care about it.
//!
//! [`from_args`]: fn.from_args.html

use std::time::Duration;
use std::path::PathBuf;

use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(name = "RRG", about = "A GRR agent rewritten in Rust.")]
pub struct Opts {
    /// A level of log verbosity.
    #[structopt(long="log-verbosity", name="LEVEL", default_value="info",
                help="Specifies the level of log verbosity")]
    pub log_verbosity: Verbosity,

    /// A standard stream to log into.
    #[structopt(long="log-std", name="STD",
                help="Enables logging to the specified standard stream")]
    pub log_std: Option<Std>,

    /// A path to the file to log into.
    #[structopt(long="log-file", name="FILE",
                help="Enables logging to the specified file")]
    pub log_file: Option<PathBuf>,

    /// A frequence of heartbeat messages to send to the Fleetspeak client.
    #[structopt(long="heartbeat-rate", name="DURATION", default_value="5s",
                parse(try_from_str = humantime::parse_duration),
                help="Specifies the frequency of heartbeat messages")]
    pub heartbeat_rate: Duration,
}

/// Parses command-line arguments.
///
/// This is a just a convenience function intended to be used as a shortcut for
/// creating instances of [`Opts`]. Ideally, it should be called only once in
/// the entire lifetime of the agent.
///
/// [`Opts`]: struct.Opts.html
pub fn from_args() -> Opts {
    Opts::from_args()
}

/// A type representing level of log verbosity.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Verbosity {
    level: log::LevelFilter,
}

impl Verbosity {

    /// Yields a corresponding log filter.
    pub fn level(&self) -> log::LevelFilter {
        self.level
    }
}

impl std::str::FromStr for Verbosity {

    type Err = String; // TODO.

    fn from_str(string: &str) -> std::result::Result<Verbosity, String> {
        use log::LevelFilter::*;

        let level = match string {
            "quiet" => Off,
            "error" => Error,
            "warn" => Warn,
            "info" => Info,
            "debug" => Debug,
            "trace" => Trace,
            _ => return Err(format!("invalid verbosity choice '{}'", string)),
        };

        Ok(Verbosity {
            level: level,
        })
    }
}

// TODO: This should just be a wrapper around `simplelog::TerminalMode`, but
// it does not implement standard traits. So, for now, we just re-implement it
// like that.
/// A type listing different options for logging to standard streams.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Std {
    /// Log to the standard output.
    Out,
    /// Log to the standard error.
    Err,
    /// Log errors to the standard error, not-errors to the standard output.
    Mix,
}

impl Std {

    /// Yields a corresponding terminal mode.
    pub fn mode(&self) -> simplelog::TerminalMode {
        use simplelog::TerminalMode::*;

        match self {
            Std::Out => Stdout,
            Std::Err => Stderr,
            Std::Mix => Mixed,
        }
    }
}

impl std::str::FromStr for Std {

    type Err = String; // TODO.

    fn from_str(string: &str) -> std::result::Result<Std, String> {
        match string {
            "out" => Ok(Std::Out),
            "err" => Ok(Std::Err),
            "mix" => Ok(Std::Mix),
            _ => Err(format!("invalid std choice '{}'", string)),
        }
    }
}
<|endoftext|>


<commit_before>//! A simple connection pool

use std::cell::RefCell;
use sync::MutexArc;

use {PostgresNotifications,
     PostgresCancelData,
     PostgresConnection,
     NormalPostgresStatement,
     PostgresTransaction,
     SslMode};
use error::{PostgresConnectError, PostgresError};
use types::ToSql;

struct InnerConnectionPool {
    url: ~str,
    ssl: SslMode,
    pool: ~[PostgresConnection],
}

impl InnerConnectionPool {
    fn new_connection(&mut self) -> Option<PostgresConnectError> {
        match PostgresConnection::try_connect(self.url, &self.ssl) {
            Ok(conn) => {
                self.pool.push(conn);
                None
            }
            Err(err) => Some(err)
        }
    }
}

/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
#[deriving(Clone)]
pub struct PostgresConnectionPool {
    priv pool: MutexArc<InnerConnectionPool>
}

impl PostgresConnectionPool {
    /// Attempts to create a new pool with the specified number of connections.
    ///
    /// Returns an error if the specified number of connections cannot be
    /// created.
    pub fn try_new(url: &str, ssl: SslMode, pool_size: uint)
            -> Result<PostgresConnectionPool, PostgresConnectError> {
        let mut pool = InnerConnectionPool {
            url: url.to_owned(),
            ssl: ssl,
            pool: ~[],
        };

        for _ in range(0, pool_size) {
            match pool.new_connection() {
                None => (),
                Some(err) => return Err(err)
            }
        }

        Ok(PostgresConnectionPool {
            pool: MutexArc::new(pool)
        })
    }

    /// A convenience function wrapping `try_new`.
    ///
    /// # Failure
    ///
    /// Fails if the pool cannot be created.
    pub fn new(url: &str, ssl: SslMode, pool_size: uint)
            -> PostgresConnectionPool {
        match PostgresConnectionPool::try_new(url, ssl, pool_size) {
            Ok(pool) => pool,
            Err(err) => fail!("Unable to initialize pool: {}", err.to_str())
        }
    }

    /// Retrieves a connection from the pool.
    ///
    /// If all connections are in use, blocks until one becomes available.
    pub fn get_connection(&self) -> PooledPostgresConnection {
        let conn = self.pool.access_cond(|pool, cvar| {
            while pool.pool.is_empty() {
                cvar.wait();
            }

            pool.pool.pop().unwrap()
        });

        PooledPostgresConnection {
            pool: self.clone(),
            conn: Some(conn)
        }
    }
}

/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
    priv pool: PostgresConnectionPool,
    // TODO remove the Option wrapper when drop takes self by value
    priv conn: Option<PostgresConnection>
}

impl Drop for PooledPostgresConnection {
    fn drop(&mut self) {
        let conn = RefCell::new(self.conn.take());
        self.pool.pool.access(|pool| {
            pool.pool.push(conn.with_mut(|r| r.take_unwrap()));
        })
    }
}

impl PooledPostgresConnection {
    /// Like `PostgresConnection::try_prepare`.
    pub fn try_prepare<'a>(&'a self, query: &str)
            -> Result<NormalPostgresStatement<'a>, PostgresError> {
        self.conn.get_ref().try_prepare(query)
    }

    /// Like `PostgresConnection::prepare`.
    pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> {
        self.conn.get_ref().prepare(query)
    }

    /// Like `PostgresConnection::try_execute`.
    pub fn try_execute(&self, query: &str, params: &[&ToSql])
            -> Result<uint, PostgresError> {
        self.conn.get_ref().try_execute(query, params)
    }

    /// Like `PostgresConnection::execute`.
    pub fn execute(&self, query: &str, params: &[&ToSql]) -> uint {
        self.conn.get_ref().execute(query, params)
    }

    /// Like `PostgresConnection::try_transaction`.
    pub fn try_transaction<'a>(&'a self)
            -> Result<PostgresTransaction<'a>, PostgresError> {
        self.conn.get_ref().try_transaction()
    }

    /// Like `PostgresConnection::transaction`.
    pub fn transaction<'a>(&'a self) -> PostgresTransaction<'a> {
        self.conn.get_ref().transaction()
    }

    /// Like `PostgresConnection::notifications`.
    pub fn notifications<'a>(&'a self) -> PostgresNotifications<'a> {
        self.conn.get_ref().notifications()
    }

    /// Like `PostgresConnection::cancel_data`.
    pub fn cancel_data(&self) -> PostgresCancelData {
        self.conn.get_ref().cancel_data()
    }

    /// Like `PostgresConnection::is_desynchronized`.
    pub fn is_desynchronized(&self) -> bool {
        self.conn.get_ref().is_desynchronized()
    }
}
<commit_msg>Remove an extra to_str<commit_after>//! A simple connection pool

use std::cell::RefCell;
use sync::MutexArc;

use {PostgresNotifications,
     PostgresCancelData,
     PostgresConnection,
     NormalPostgresStatement,
     PostgresTransaction,
     SslMode};
use error::{PostgresConnectError, PostgresError};
use types::ToSql;

struct InnerConnectionPool {
    url: ~str,
    ssl: SslMode,
    pool: ~[PostgresConnection],
}

impl InnerConnectionPool {
    fn new_connection(&mut self) -> Option<PostgresConnectError> {
        match PostgresConnection::try_connect(self.url, &self.ssl) {
            Ok(conn) => {
                self.pool.push(conn);
                None
            }
            Err(err) => Some(err)
        }
    }
}

/// A simple fixed-size Postgres connection pool.
///
/// It can be shared across tasks.
#[deriving(Clone)]
pub struct PostgresConnectionPool {
    priv pool: MutexArc<InnerConnectionPool>
}

impl PostgresConnectionPool {
    /// Attempts to create a new pool with the specified number of connections.
    ///
    /// Returns an error if the specified number of connections cannot be
    /// created.
    pub fn try_new(url: &str, ssl: SslMode, pool_size: uint)
            -> Result<PostgresConnectionPool, PostgresConnectError> {
        let mut pool = InnerConnectionPool {
            url: url.to_owned(),
            ssl: ssl,
            pool: ~[],
        };

        for _ in range(0, pool_size) {
            match pool.new_connection() {
                None => (),
                Some(err) => return Err(err)
            }
        }

        Ok(PostgresConnectionPool {
            pool: MutexArc::new(pool)
        })
    }

    /// A convenience function wrapping `try_new`.
    ///
    /// # Failure
    ///
    /// Fails if the pool cannot be created.
    pub fn new(url: &str, ssl: SslMode, pool_size: uint)
            -> PostgresConnectionPool {
        match PostgresConnectionPool::try_new(url, ssl, pool_size) {
            Ok(pool) => pool,
            Err(err) => fail!("Unable to initialize pool: {}", err)
        }
    }

    /// Retrieves a connection from the pool.
    ///
    /// If all connections are in use, blocks until one becomes available.
    pub fn get_connection(&self) -> PooledPostgresConnection {
        let conn = self.pool.access_cond(|pool, cvar| {
            while pool.pool.is_empty() {
                cvar.wait();
            }

            pool.pool.pop().unwrap()
        });

        PooledPostgresConnection {
            pool: self.clone(),
            conn: Some(conn)
        }
    }
}

/// A Postgres connection pulled from a connection pool.
///
/// It will be returned to the pool when it falls out of scope, even due to
/// task failure.
pub struct PooledPostgresConnection {
    priv pool: PostgresConnectionPool,
    // TODO remove the Option wrapper when drop takes self by value
    priv conn: Option<PostgresConnection>
}

impl Drop for PooledPostgresConnection {
    fn drop(&mut self) {
        let conn = RefCell::new(self.conn.take());
        self.pool.pool.access(|pool| {
            pool.pool.push(conn.with_mut(|r| r.take_unwrap()));
        })
    }
}

impl PooledPostgresConnection {
    /// Like `PostgresConnection::try_prepare`.
    pub fn try_prepare<'a>(&'a self, query: &str)
            -> Result<NormalPostgresStatement<'a>, PostgresError> {
        self.conn.get_ref().try_prepare(query)
    }

    /// Like `PostgresConnection::prepare`.
    pub fn prepare<'a>(&'a self, query: &str) -> NormalPostgresStatement<'a> {
        self.conn.get_ref().prepare(query)
    }

    /// Like `PostgresConnection::try_execute`.
    pub fn try_execute(&self, query: &str, params: &[&ToSql])
            -> Result<uint, PostgresError> {
        self.conn.get_ref().try_execute(query, params)
    }

    /// Like `PostgresConnection::execute`.
    pub fn execute(&self, query: &str, params: &[&ToSql]) -> uint {
        self.conn.get_ref().execute(query, params)
    }

    /// Like `PostgresConnection::try_transaction`.
    pub fn try_transaction<'a>(&'a self)
            -> Result<PostgresTransaction<'a>, PostgresError> {
        self.conn.get_ref().try_transaction()
    }

    /// Like `PostgresConnection::transaction`.
    pub fn transaction<'a>(&'a self) -> PostgresTransaction<'a> {
        self.conn.get_ref().transaction()
    }

    /// Like `PostgresConnection::notifications`.
    pub fn notifications<'a>(&'a self) -> PostgresNotifications<'a> {
        self.conn.get_ref().notifications()
    }

    /// Like `PostgresConnection::cancel_data`.
    pub fn cancel_data(&self) -> PostgresCancelData {
        self.conn.get_ref().cancel_data()
    }

    /// Like `PostgresConnection::is_desynchronized`.
    pub fn is_desynchronized(&self) -> bool {
        self.conn.get_ref().is_desynchronized()
    }
}
<|endoftext|>