<commit_before>//! A Rust snippet runner.
//!
//! Please see [readme](https://github.com/stevedonovan/runner/blob/master/readme.md)
extern crate easy_shortcuts as es;
extern crate lapp;
use es::traits::*;
use std::process;
use std::env;
use std::fs;
use std::path::PathBuf;
use std::collections::HashMap;
use std::io::Write;

mod crate_utils;
mod platform;

use platform::{open,edit,EXE,SO};

fn rustup_lib() -> String {
    es::shell("rustc --print sysroot") + "/lib"
}

// this will be initially written to ~/.cargo/.runner/prelude and
// can then be edited.
const PRELUDE: &'static str = "
#![allow(unused_imports)]
#![allow(dead_code)]
use std::fs;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::env;
use std::path::{PathBuf,Path};
#[allow(unused_macros)]
macro_rules! debug {
    ($x:expr) => {
        println!(\"{} = {:?}\",stringify!($x),$x);
    }
}

";

fn runner_directory() -> PathBuf {
    let mut home = crate_utils::cargo_home();
    home.push(".runner");
    home
}

fn cargo(args: &[&str]) -> bool {
    let res = process::Command::new("cargo")
        .args(args)
        .status()
        .or_die("can't run cargo");
    res.success()
}

const STATIC_CACHE: &str = "static-cache";
const DYNAMIC_CACHE: &str = "dy-cache";

fn static_cache_dir() -> PathBuf {
    runner_directory().join(STATIC_CACHE)
}

fn static_cache_dir_check(args: &lapp::Args) -> PathBuf {
    let static_cache = static_cache_dir();
    if ! static_cache.exists() {
        args.quit("please build static cache with --create first");
    }
    static_cache
}

fn build_static_cache() -> bool {
    cargo(&["build"]) &&
    cargo(&["build","--release"]) &&
    cargo(&["doc"])
}

fn create_static_cache(crates: &[String], create: bool) {
    use std::io::prelude::*;
    let mut home = runner_directory();
    env::set_current_dir(&home).or_die("cannot change to home directory");
    if create {
        if ! cargo(&["new","--bin",STATIC_CACHE]) {
            es::quit("cannot create static cache");
        }
    }
    home.push(STATIC_CACHE);
    env::set_current_dir(&home).or_die("could not change to static cache directory");
    let tmpfile = env::temp_dir().join("Cargo.toml");
    fs::copy("Cargo.toml",&tmpfile).or_die("cannot back up Cargo.toml");
    {
        let mut deps = fs::OpenOptions::new().append(true)
            .open("Cargo.toml").or_die("could not append to Cargo.toml");
        for c in crates {
            write!(deps,"{}=\"*\"\n",c).or_die("could not modify Cargo.toml");
        }
    }
    if ! build_static_cache() {
        println!("Error occurred - restoring Cargo.toml");
        fs::copy(&tmpfile,"Cargo.toml").or_die("cannot restore Cargo.toml");
    }
}

// this is always called first and has the important role to ensure that
// runner's directory structure is created properly.
fn get_prelude() -> String {
    let home = runner_directory();
    let pristine = ! home.is_dir();
    if pristine {
        fs::create_dir(&home).or_die("cannot create runner directory");
    }
    let prelude = home.join("prelude");
    let bin = home.join("bin");
    if pristine {
        es::write_all(&prelude,PRELUDE);
        fs::create_dir(&home.join(DYNAMIC_CACHE)).or_die("cannot create dynamic cache");
    }
    if pristine || ! bin.is_dir() {
        fs::create_dir(&bin).or_die("cannot create output directory");
    }
    es::read_to_string(&prelude)
}

fn get_cache(build_static: bool, optimize: bool) -> PathBuf {
    let mut home = runner_directory();
    let scache;
    let cache = if build_static {
        let dir = if optimize {"release"} else {"debug"};
        scache = format!("{}/target/{}/deps",STATIC_CACHE,dir);
        &scache
    } else {DYNAMIC_CACHE};
    home.push(cache);
    home
}

fn add_aliases(aliases: Vec<String>) {
    if aliases.len() == 0 { return; }
    let alias_file = runner_directory().join("alias");
    let mut f = if alias_file.is_file() {
        fs::OpenOptions::new().append(true).open(&alias_file)
    } else {
        fs::File::create(&alias_file)
    }.or_die("cannot open runner alias file");

    for crate_alias in aliases {
        write!(f,"{}\n",crate_alias).or_die("cannot write to runner alias file");
    }
}

fn get_aliases() -> HashMap<String,String> {
    let alias_file = runner_directory().join("alias");
    if ! alias_file.is_file() { return HashMap::new(); }
	es::lines(es::open(&alias_file))
      .filter_map(|s| s.split_at_delim('=').trim()) // split into (String,String)
	  .to_map()
}

fn massage_snippet(code: String, prelude: String, extern_crates: Vec<String>, wild_crates: Vec<String>) -> String {
    fn indent_line(line: &str) -> String {
        format!("    {}\n",line)
    }
    let mut prefix = prelude;
    let mut body = String::new();
    {
        if extern_crates.len() > 0 {
            let aliases = get_aliases();
            for c in extern_crates {
                prefix += &if let Some(aliased) = aliases.get(&c) {
                    format!("extern crate {} as {};",aliased,c)
                } else {
                    format!("extern crate {};",c)
                };
            }
            for c in wild_crates {
                prefix += &format!("use {}::*;",c);
            }
        }
        let mut lines = code.lines();
        let mut first = true;
        for line in lines.by_ref() {
            let line = line.trim_left();
            if first { // files may start with #! shebang...
                if line.starts_with("#!") {
                    continue;
                }
                first = false;
            }
            // crate import, use should go at the top.
            // Particularly need to force crate-level attributes to the top
            // - currently only 'macro_use'.
            if line.starts_with("//") || line.starts_with("#[macro_use") ||
                line.starts_with("extern ") || line.starts_with("use ") {
                prefix += line;
                prefix.push('\n');
            } else
            if line.len() > 0 {
                body += &indent_line(line);
                break;
            }
        }
        // and indent the rest!
        body.extend(lines.map(indent_line));
    }

    format!("{}
use std::error::Error;
fn run() -> Result<(),Box<Error>> {{
{}    Ok(())
}}
fn main() {{
    run().unwrap();
}}
        ",prefix,body)

}

const USAGE: &str = "
Compile and run small Rust snippets
  -s, --static build statically (default is dynamic)
  -O, --optimize optimized static build
  -e, --expression evaluate an expression
  -i, --iterator evaluate an iterator
  -n, --lines evaluate expression over stdin; 'line' is defined
  -x, --extern... (string) add an extern crate to the snippet
  -X, --wild... (string) like -x but implies wildcard use

  Cache Management:
  --create (string...) initialize the static cache with crates
  --add  (string...) add new crates to the cache (after --create)
  --edit  edit the static cache Cargo.toml
  --build rebuild the static cache
  --doc  display documentation
  --edit-prelude edit the default prelude for snippets
  --alias (string...) crate aliases in form alias=crate_name (used with -x)

  Dynamic compilation:
  -P, --crate-path show path of crate source in Cargo cache
  -C, --compile  compile crate dynamically (limited)
  --cfg... (string) pass configuration variables to rustc
  --libc  link dynamically against libc (special case)

  <program> (string) Rust program, snippet or expression
  <args> (string...) arguments to pass to program
";

fn main() {
    let args = lapp::parse_args(USAGE);
    let prelude = get_prelude();

    let aliases = args.get_strings("alias");
    if aliases.len() > 0 {
        add_aliases(aliases);
        return;
    }

    if args.get_bool("edit-prelude") {
        let rdir = runner_directory().join("prelude");
        edit(&rdir);
        return;
    }

    // Static Cache Management
    let crates = args.get_strings("create");
    if crates.len() > 0 {
        create_static_cache(&crates,true);
        return;
    }
    let crates = args.get_strings("add");
    if crates.len() > 0 {
        static_cache_dir_check(&args);
        create_static_cache(&crates,false);
        return;
    }

    if args.get_bool("edit") || args.get_bool("build") || args.get_bool("doc") {
        let static_cache = static_cache_dir_check(&args);
        if args.get_bool("build") {
            env::set_current_dir(&static_cache).or_die("static cache wasn't a directory?");
            build_static_cache();
        } else
        if args.get_bool("doc") {
            let docs = static_cache.join("target/doc/static_cache/index.html");
            open(&docs);
        } else {
            let toml = static_cache.join("Cargo.toml");
            edit(&toml);
        }
        return;
    }

    let first_arg = args.get_string("program");
    let file = PathBuf::from(&first_arg);

    // Dynamically linking crates (experimental!)
    if args.get_bool("crate-path") || args.get_bool("compile") {
        let (crate_path,crate_name) = if file.exists() {
            let filename = crate_utils::path_file_name(&file);
            if file.is_dir() { // assumed to be Cargo directory
                if ! file.join("Cargo.toml").exists() {
                    args.quit(&format!("not a Cargo project directory: {}",file.display()));
                }
                (file.join("src/lib.rs"), filename)
            } else { // should be just a Rust source file
                if file.extension().or_die("expecting extension") != "rs" {
                    args.quit("expecting Rust source file");
                }
                let name = crate_utils::path_file_name(&file.with_extension(""));
                (file, name)
            }
        } else {
            (crate_utils::cache_path(&first_arg).join("src/lib.rs"), first_arg)
        };
        if args.get_bool("crate-path") {
            println!("{}",crate_utils::cache_path(&crate_name).display());
        } else {
            let valid_crate_name = crate_name.replace('-',"_");
            let cache = get_cache(false, false);
            let mut builder = process::Command::new("rustc");
                builder.args(&["-C","prefer-dynamic"]).args(&["-C","debuginfo=0"])
                .arg("-L").arg(&cache)
                .args(&["--crate-type","dylib"])
                .arg("--out-dir").arg(&cache)
                .arg("--crate-name").arg(&valid_crate_name)
                .arg(crate_path);
           for c in args.get_strings("cfg") {
                builder.arg("--cfg").arg(&c);
           }
           if args.get_bool("libc") {
                builder.arg("--extern").arg(&format!("libc={}/liblibc.{}",cache.display(),SO));
           }
           builder.status().or_die("can't run rustc");
        }
        return;
    }

    let build_static = args.get_bool("static");
    let optimize = args.get_bool("optimize");

    // we'll pass rest of arguments to program
    let program_args = args.get_strings("args");

    let cache = get_cache(build_static, optimize);

    let mut snippet = false;
    let mut code = if args.get_bool("expression") {
        // Evaluating an expression: just print it out.
        format!("println!(\"{{:?}}\",{});", first_arg)
    } else
    if args.get_bool("iterator") {
        // The expression is anything that implements IntoIterator
        format!("let iter = {};\n for val in iter {{ println!(\"{{:?}}\",val);}}", first_arg)
    } else
    if args.get_bool("lines") {
        // The variable 'line' is available to an expression, evaluated for each line in stdin
        format!("
            let stdin = io::stdin();
            for line in stdin.lock().lines() {{
                let line = line?;
                let val = {};
                println!(\"{{:?}}\",val);
            }}
            ", first_arg)
    } else { // otherwise, just a file
        snippet = true;
        es::read_to_string(&file)
    };

    // proper Rust programs are accepted (this is a bit rough)
    if code.find("fn main").is_none() {
        let mut extern_crates = args.get_strings("extern");
        let wild_crates = args.get_strings("wild");
        if wild_crates.len() > 0 {
            extern_crates.extend(wild_crates.iter().cloned());
        }
        code = massage_snippet(code,prelude, extern_crates, wild_crates);
    }

    // we are going to put the expanded source and resulting exe in the runner bin dir
    let mut out_file = runner_directory().join("bin");
    if snippet {
        out_file.push(&file);
        out_file.set_extension("rs");
    } else {
        out_file.push("tmp.rs");
    }
    let mut program = out_file.clone();
    program.set_extension(EXE);

    es::write_all(&out_file,&code);

    let mut builder = process::Command::new("rustc");
    if ! build_static {
        builder.args(&["-C","prefer-dynamic"]).args(&["-C","debuginfo=0"]);
    } else {
        builder.arg(if optimize {"-O"} else {"-g"});
    }
    builder.arg("-L").arg(&cache);
    let status = builder.arg("-o").arg(&program)
        .arg(&out_file)
        .status().or_die("can't run rustc");
    if ! status.success() {
        return;
    }

    let mut builder = process::Command::new(&program);
    if ! build_static {
        builder.env("LD_LIBRARY_PATH",format!("{}:{}",rustup_lib(),cache.display()));
    }
    builder.args(&program_args)
        .status()
        .or_die(&format!("can't run program {:?}",program));

}

<commit_msg>--extern also used for explicitly linking crate; 'proper' programs are not copied to the runner bin dir<commit_after>//! A Rust snippet runner.
//!
//! Please see [readme](https://github.com/stevedonovan/runner/blob/master/readme.md)
extern crate easy_shortcuts as es;
extern crate lapp;
use es::traits::*;
use std::process;
use std::env;
use std::fs;
use std::path::PathBuf;
use std::collections::HashMap;
use std::io::Write;

mod crate_utils;
mod platform;

use platform::{open,edit,EXE,SO};

fn rustup_lib() -> String {
    es::shell("rustc --print sysroot") + "/lib"
}

// this will be initially written to ~/.cargo/.runner/prelude and
// can then be edited.
const PRELUDE: &'static str = "
#![allow(unused_imports)]
#![allow(dead_code)]
use std::fs;
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::env;
use std::path::{PathBuf,Path};
#[allow(unused_macros)]
macro_rules! debug {
    ($x:expr) => {
        println!(\"{} = {:?}\",stringify!($x),$x);
    }
}

";

fn runner_directory() -> PathBuf {
    let mut home = crate_utils::cargo_home();
    home.push(".runner");
    home
}

fn cargo(args: &[&str]) -> bool {
    let res = process::Command::new("cargo")
        .args(args)
        .status()
        .or_die("can't run cargo");
    res.success()
}

const STATIC_CACHE: &str = "static-cache";
const DYNAMIC_CACHE: &str = "dy-cache";

fn static_cache_dir() -> PathBuf {
    runner_directory().join(STATIC_CACHE)
}

fn static_cache_dir_check(args: &lapp::Args) -> PathBuf {
    let static_cache = static_cache_dir();
    if ! static_cache.exists() {
        args.quit("please build static cache with --create first");
    }
    static_cache
}

fn build_static_cache() -> bool {
    cargo(&["build"]) &&
    cargo(&["build","--release"]) &&
    cargo(&["doc"])
}

fn create_static_cache(crates: &[String], create: bool) {
    use std::io::prelude::*;
    let mut home = runner_directory();
    env::set_current_dir(&home).or_die("cannot change to home directory");
    if create {
        if ! cargo(&["new","--bin",STATIC_CACHE]) {
            es::quit("cannot create static cache");
        }
    }
    home.push(STATIC_CACHE);
    env::set_current_dir(&home).or_die("could not change to static cache directory");
    let tmpfile = env::temp_dir().join("Cargo.toml");
    fs::copy("Cargo.toml",&tmpfile).or_die("cannot back up Cargo.toml");
    {
        let mut deps = fs::OpenOptions::new().append(true)
            .open("Cargo.toml").or_die("could not append to Cargo.toml");
        for c in crates {
            write!(deps,"{}=\"*\"\n",c).or_die("could not modify Cargo.toml");
        }
    }
    if ! build_static_cache() {
        println!("Error occurred - restoring Cargo.toml");
        fs::copy(&tmpfile,"Cargo.toml").or_die("cannot restore Cargo.toml");
    }
}

// this is always called first and has the important role to ensure that
// runner's directory structure is created properly.
fn get_prelude() -> String {
    let home = runner_directory();
    let pristine = ! home.is_dir();
    if pristine {
        fs::create_dir(&home).or_die("cannot create runner directory");
    }
    let prelude = home.join("prelude");
    let bin = home.join("bin");
    if pristine {
        es::write_all(&prelude,PRELUDE);
        fs::create_dir(&home.join(DYNAMIC_CACHE)).or_die("cannot create dynamic cache");
    }
    if pristine || ! bin.is_dir() {
        fs::create_dir(&bin).or_die("cannot create output directory");
    }
    es::read_to_string(&prelude)
}

fn get_cache(build_static: bool, optimize: bool) -> PathBuf {
    let mut home = runner_directory();
    let scache;
    let cache = if build_static {
        let dir = if optimize {"release"} else {"debug"};
        scache = format!("{}/target/{}/deps",STATIC_CACHE,dir);
        &scache
    } else {DYNAMIC_CACHE};
    home.push(cache);
    home
}

fn add_aliases(aliases: Vec<String>) {
    if aliases.len() == 0 { return; }
    let alias_file = runner_directory().join("alias");
    let mut f = if alias_file.is_file() {
        fs::OpenOptions::new().append(true).open(&alias_file)
    } else {
        fs::File::create(&alias_file)
    }.or_die("cannot open runner alias file");

    for crate_alias in aliases {
        write!(f,"{}\n",crate_alias).or_die("cannot write to runner alias file");
    }
}

fn get_aliases() -> HashMap<String,String> {
    let alias_file = runner_directory().join("alias");
    if ! alias_file.is_file() { return HashMap::new(); }
	es::lines(es::open(&alias_file))
      .filter_map(|s| s.split_at_delim('=').trim()) // split into (String,String)
	  .to_map()
}

fn massage_snippet(code: String, prelude: String, extern_crates: Vec<String>, wild_crates: Vec<String>) -> String {
    fn indent_line(line: &str) -> String {
        format!("    {}\n",line)
    }
    let mut prefix = prelude;
    let mut body = String::new();
    {
        if extern_crates.len() > 0 {
            let aliases = get_aliases();
            for c in extern_crates {
                prefix += &if let Some(aliased) = aliases.get(&c) {
                    format!("extern crate {} as {};",aliased,c)
                } else {
                    format!("extern crate {};",c)
                };
            }
            for c in wild_crates {
                prefix += &format!("use {}::*;",c);
            }
        }
        let mut lines = code.lines();
        let mut first = true;
        for line in lines.by_ref() {
            let line = line.trim_left();
            if first { // files may start with #! shebang...
                if line.starts_with("#!") {
                    continue;
                }
                first = false;
            }
            // crate import, use should go at the top.
            // Particularly need to force crate-level attributes to the top
            // - currently only 'macro_use'.
            if line.starts_with("//") || line.starts_with("#[macro_use") ||
                line.starts_with("extern ") || line.starts_with("use ") {
                prefix += line;
                prefix.push('\n');
            } else
            if line.len() > 0 {
                body += &indent_line(line);
                break;
            }
        }
        // and indent the rest!
        body.extend(lines.map(indent_line));
    }

    format!("{}
use std::error::Error;
fn run() -> Result<(),Box<Error>> {{
{}    Ok(())
}}
fn main() {{
    run().unwrap();
}}
        ",prefix,body)

}

const USAGE: &str = "
Compile and run small Rust snippets
  -s, --static build statically (default is dynamic)
  -O, --optimize optimized static build
  -e, --expression evaluate an expression
  -i, --iterator evaluate an iterator
  -n, --lines evaluate expression over stdin; 'line' is defined
  -x, --extern... (string) add an extern crate to the snippet
  -X, --wild... (string) like -x but implies wildcard use

  Cache Management:
  --create (string...) initialize the static cache with crates
  --add  (string...) add new crates to the cache (after --create)
  --edit  edit the static cache Cargo.toml
  --build rebuild the static cache
  --doc  display documentation
  --edit-prelude edit the default prelude for snippets
  --alias (string...) crate aliases in form alias=crate_name (used with -x)

  Dynamic compilation:
  -P, --crate-path show path of crate source in Cargo cache
  -C, --compile  compile crate dynamically (limited)
  --cfg... (string) pass configuration variables to rustc
  --libc  link dynamically against libc (special case)

  <program> (string) Rust program, snippet or expression
  <args> (string...) arguments to pass to program
";

fn main() {
    let args = lapp::parse_args(USAGE);
    let prelude = get_prelude();

    let aliases = args.get_strings("alias");
    if aliases.len() > 0 {
        add_aliases(aliases);
        return;
    }

    if args.get_bool("edit-prelude") {
        let rdir = runner_directory().join("prelude");
        edit(&rdir);
        return;
    }

    // Static Cache Management
    let crates = args.get_strings("create");
    if crates.len() > 0 {
        create_static_cache(&crates,true);
        return;
    }
    let crates = args.get_strings("add");
    if crates.len() > 0 {
        static_cache_dir_check(&args);
        create_static_cache(&crates,false);
        return;
    }

    if args.get_bool("edit") || args.get_bool("build") || args.get_bool("doc") {
        let static_cache = static_cache_dir_check(&args);
        if args.get_bool("build") {
            env::set_current_dir(&static_cache).or_die("static cache wasn't a directory?");
            build_static_cache();
        } else
        if args.get_bool("doc") {
            let docs = static_cache.join("target/doc/static_cache/index.html");
            open(&docs);
        } else {
            let toml = static_cache.join("Cargo.toml");
            edit(&toml);
        }
        return;
    }

    let first_arg = args.get_string("program");
    let file = PathBuf::from(&first_arg);

    // Dynamically linking crates (experimental!)
    if args.get_bool("crate-path") || args.get_bool("compile") {
        let (crate_path,crate_name) = if file.exists() {
            let filename = crate_utils::path_file_name(&file);
            if file.is_dir() { // assumed to be Cargo directory
                if ! file.join("Cargo.toml").exists() {
                    args.quit(&format!("not a Cargo project directory: {}",file.display()));
                }
                (file.join("src/lib.rs"), filename)
            } else { // should be just a Rust source file
                if file.extension().or_die("expecting extension") != "rs" {
                    args.quit("expecting Rust source file");
                }
                let name = crate_utils::path_file_name(&file.with_extension(""));
                (file, name)
            }
        } else {
            (crate_utils::cache_path(&first_arg).join("src/lib.rs"), first_arg)
        };
        if args.get_bool("crate-path") {
            println!("{}",crate_utils::cache_path(&crate_name).display());
        } else {
            let valid_crate_name = crate_name.replace('-',"_");
            let cache = get_cache(false, false);
            let mut builder = process::Command::new("rustc");
                builder.args(&["-C","prefer-dynamic"]).args(&["-C","debuginfo=0"])
                .arg("-L").arg(&cache)
                .args(&["--crate-type","dylib"])
                .arg("--out-dir").arg(&cache)
                .arg("--crate-name").arg(&valid_crate_name)
                .arg(crate_path);
           for c in args.get_strings("cfg") {
                builder.arg("--cfg").arg(&c);
           }
           // implicit linking works fine, until it doesn't
           let mut extern_crates = args.get_strings("extern");
           if args.get_bool("libc") { // libc is such a special case
                extern_crates.push("libc".into());
           }
           for c in  extern_crates {
                let ext = format!("{}={}/lib{}.{}",c,cache.display(),c,SO);
                builder.arg("--extern").arg(&ext);
           }
           builder.status().or_die("can't run rustc");
        }
        return;
    }

    let build_static = args.get_bool("static");
    let optimize = args.get_bool("optimize");

    // we'll pass rest of arguments to program
    let program_args = args.get_strings("args");

    let cache = get_cache(build_static, optimize);

    let mut snippet = false;
    let mut code = if args.get_bool("expression") {
        // Evaluating an expression: just print it out.
        format!("println!(\"{{:?}}\",{});", first_arg)
    } else
    if args.get_bool("iterator") {
        // The expression is anything that implements IntoIterator
        format!("let iter = {};\n for val in iter {{ println!(\"{{:?}}\",val);}}", first_arg)
    } else
    if args.get_bool("lines") {
        // The variable 'line' is available to an expression, evaluated for each line in stdin
        format!("
            let stdin = io::stdin();
            for line in stdin.lock().lines() {{
                let line = line?;
                let val = {};
                println!(\"{{:?}}\",val);
            }}
            ", first_arg)
    } else { // otherwise, just a file
        snippet = true;
        es::read_to_string(&file)
    };

    // ALL executables go into the Runner bin directory...
    let mut bin = runner_directory().join("bin");

    // proper Rust programs are accepted (this is a bit rough)
    let proper = code.find("fn main").is_some();
    let (rust_file, program) = if ! proper {
        // otherwise we must create a proper program from the snippet
        // and write this as a file in the Runner bin directory...
        let mut extern_crates = args.get_strings("extern");
        let wild_crates = args.get_strings("wild");
        if wild_crates.len() > 0 {
            extern_crates.extend(wild_crates.iter().cloned());
        }
        code = massage_snippet(code,prelude, extern_crates, wild_crates);
        if snippet {
            bin.push(&file);
            bin.set_extension("rs");
        } else {
            bin.push("tmp.rs");
        }
        es::write_all(&bin,&code);
        let program = bin.with_extension(EXE);
        (bin, program)
    } else {
        bin.push(&file);
        let program = bin.with_extension(EXE);
        (file, program)
    };

    // We now have a proper Rust file to compile
    let mut builder = process::Command::new("rustc");
    if ! build_static { // stripped-down dynamic link
        builder.args(&["-C","prefer-dynamic"]).args(&["-C","debuginfo=0"]);
    } else { // static debug build
        builder.arg(if optimize {"-O"} else {"-g"});
    }
    // implicitly linking against crates in the dynamic or static cache
    builder.arg("-L").arg(&cache);
    let status = builder.arg("-o").arg(&program)
        .arg(rust_file)
        .status().or_die("can't run rustc");
    if ! status.success() {
        return;
    }

    // Finally run the compiled program
    let mut builder = process::Command::new(&program);
    if ! build_static {
        builder.env("LD_LIBRARY_PATH",format!("{}:{}",rustup_lib(),cache.display()));
    }
    builder.args(&program_args)
        .status()
        .or_die(&format!("can't run program {:?}",program));

}

<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate clap;
extern crate hyper;
extern crate hyper_native_tls;

mod gitignore;

use std::fs::{File, OpenOptions, create_dir, read_dir};
use std::io::{BufReader, Result, Error, ErrorKind};
use std::io::prelude::*;
use std::path::Path;
use std::process::{exit, Command};
use std::env;

use clap::{App, SubCommand};

#[derive(Deserialize)]
struct Config {
    mkdir: Option<Vec<String>>,
    touch: Option<Vec<String>>,
    exec: Option<Vec<String>>,
    gitignore: Option<Vec<String>>,
}

fn main() {
    let matches = App::new("Skeleton")
        .version("0.1")
        .author("Valentin B. <mail@mail.mail>")
        .about("Skeleton project manager")
        .args_from_usage("-l, --lang=<LANG>  'Set language configuration'")
        .subcommand(SubCommand::with_name("new")
                        .about("create new project")
                        .arg_from_usage("<NAME>   'The project name'"))
        .subcommand(SubCommand::with_name("init").about("initialize existing project"))
        .get_matches();
    let lang = matches.value_of("lang").unwrap();

    if let Some(matches) = matches.subcommand_matches("new") {
        println!("doing new {}", matches.value_of("NAME").unwrap());
    }

    let mut config_path = match env::home_dir() {
        Some(path) => {
            match path.to_str() {
                Some(p) => p.to_string(),
                None => {
                    println!("Could not resolve $HOME");
                    exit(1);
                }
            }
        }
        None => {
            println!("Could not resolve $HOME");
            exit(1);
        }
    };

    config_path.push_str("/.skeleton/");
    config_path.push_str(lang);
    config_path.push_str(".toml");

    let config: Config = match parse_config(config_path) {
        Ok(c) => c,
        Err(err) => {
            println!("Error while parsing config! {:?}", err);
            exit(1);
        }
    };

    if let Some(subcmd) = matches.subcommand_matches("new") {
        let name = subcmd.value_of("NAME").unwrap();
        if file_exists(&name.to_string()) {
            println!("A file or directory with that name already exists");
            exit(1);
        } else {
            match create_dir(name.clone()) {
                Ok(_) => println!("Created directory '{}'", name),
                Err(e) => {
                    println!("Could not create direcotry '{}'. {:?}", name, e);
                    exit(1);
                }
            }
            if let Err(_) = env::set_current_dir(Path::new(&*name)) {
                println!("Could not change directory!");
                exit(1);
            }
        }
    }

    if !dir_is_empty(&".".to_string()) {
        println!("Direcotry is not empty!");
        exit(1);
    }

    if let Some(dirs) = config.mkdir {
        for dir in dirs {
            if !file_exists(&dir) {
                match create_dir(dir.clone()) {
                    Ok(_) => println!("Created directory '{}'", dir),
                    Err(e) => println!("Could not create directory '{}'. {:?}", dir, e),
                }
            } else {
                println!("Directory '{}' already exists", dir);
            }
        }
    }

    if let Some(gi) = config.gitignore {
        let ign = gitignore::get_gitignore(gi).unwrap();
        let file = OpenOptions::new()
            .create_new(true)
            .append(true)
            .open("gitignore");
        if let Ok(mut file) = file {
            writeln!(file, "{}", ign);
        } else {
            println!("Could not write .gitignore");
        }
    }

    if let Some(fnames) = config.touch {
        for file in fnames {
            if !create_file(&file) {
                println!("Could not create file '{}'", file);
            }
        }
    }

    if let Some(cmds) = config.exec {
        for cmd in cmds {
            println!("Executing '{}'", cmd);
            match exec(&cmd) {
                Ok((out, err)) => {
                    println!("stdout: {}", out);
                    println!("stderr: {}", err);
                }
                Err(e) => println!("Failed to execute: {:?}", e),
            }
        }
    }
}

fn dir_is_empty(dir: &String) -> bool {
    let paths = read_dir(dir).unwrap();

    for _ in paths {
        return false;
    }
    true
}

fn file_exists(name: &String) -> bool {
    Path::new(&name).exists()
}

fn exec(cmd: &String) -> Result<(String, String)> {
    #[cfg(unix)]
    let shell = "sh";
    #[cfg(unix)]
    let arg1 = "-c";
    #[cfg(windows)]
    let shell = "cmd.exe";
    #[cfg(windows)]
    let arg1 = "/C";

    let out = match Command::new(shell).arg(arg1).arg(cmd).output() {
        Ok(o) => o,
        Err(e) => return Err(e),
    };

    let stdout = match String::from_utf8(out.stdout) {
        Ok(so) => so,
        Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)),
    };

    let stderr = match String::from_utf8(out.stderr) {
        Ok(se) => se,
        Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)),
    };

    Ok((stdout, stderr))
}

fn create_file(file_name: &String) -> bool {
    !file_exists(&file_name) &&
    match OpenOptions::new()
              .append(true)
              .create(true)
              .open(file_name) {
        Ok(_) => true,
        Err(_) => false,
    }
}

fn parse_config(file_name: String) -> Result<Config> {
    let file = File::open(file_name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    match toml::from_str(&contents) {
        Ok(c) => Ok(c),
        Err(err) => Err(Error::new(ErrorKind::InvalidInput, err)),
    }
}

#[test]
fn test_file_exists() {
    assert!(file_exists(&"test/foo.toml".to_string()));
    assert!(!file_exists(&"test/none".to_string()));
}

#[test]
fn test_parse_config() {
    let conf = parse_config("test/foo.toml".to_string()).unwrap();
    let gi = conf.gitignore.unwrap();
    assert_eq!(gi, vec!["rust".to_string(), "vim".to_string()]);

    let mkd = conf.mkdir.unwrap();
    assert_eq!(mkd, vec!["b".to_string()]);

    let touch = conf.touch.unwrap();
    assert_eq!(touch, vec!["a".to_string()]);

    let exec = conf.exec.unwrap();
    assert_eq!(exec, vec!["touch asdf".to_string()]);
}

#[test]
fn test_exec() {
    let (stdout, stderr) = exec(&"echo -n test".to_string()).unwrap();
    assert_eq!(stdout, "test".to_string());
    assert_eq!(stderr, "".to_string());
    let (stdout, stderr) = exec(&"echo -n test 1>&2".to_string()).unwrap();
    assert_eq!(stdout, "".to_string());
    assert_eq!(stderr, "test".to_string());
}

#[test]
fn test_dir_is_empty() {
    let is_empty = dir_is_empty(&"./test".to_string());
    assert!(!is_empty);
}
<commit_msg>Add include tag to config struct<commit_after>#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate clap;
extern crate hyper;
extern crate hyper_native_tls;

mod gitignore;

use std::fs::{File, OpenOptions, create_dir, read_dir};
use std::io::{BufReader, Result, Error, ErrorKind};
use std::io::prelude::*;
use std::path::Path;
use std::process::{exit, Command};
use std::env;

use clap::{App, SubCommand};

#[derive(Deserialize)]
struct Config {
    mkdir: Option<Vec<String>>,
    touch: Option<Vec<String>>,
    exec: Option<Vec<String>>,
    gitignore: Option<Vec<String>>,
    include: Option<Vec<String>>,
}

fn main() {
    let matches = App::new("Skeleton")
        .version("0.1")
        .author("Valentin B. <mail@mail.mail>")
        .about("Skeleton project manager")
        .args_from_usage("-l, --lang=<LANG>  'Set language configuration'")
        .subcommand(SubCommand::with_name("new")
                        .about("create new project")
                        .arg_from_usage("<NAME>   'The project name'"))
        .subcommand(SubCommand::with_name("init").about("initialize existing project"))
        .get_matches();
    let lang = matches.value_of("lang").unwrap();

    if let Some(matches) = matches.subcommand_matches("new") {
        println!("doing new {}", matches.value_of("NAME").unwrap());
    }

    let mut config_path = match env::home_dir() {
        Some(path) => {
            match path.to_str() {
                Some(p) => p.to_string(),
                None => {
                    println!("Could not resolve $HOME");
                    exit(1);
                }
            }
        }
        None => {
            println!("Could not resolve $HOME");
            exit(1);
        }
    };

    config_path.push_str("/.skeleton/");
    config_path.push_str(lang);
    config_path.push_str(".toml");

    let config: Config = match parse_config(config_path) {
        Ok(c) => c,
        Err(err) => {
            println!("Error while parsing config! {:?}", err);
            exit(1);
        }
    };

    if let Some(subcmd) = matches.subcommand_matches("new") {
        let name = subcmd.value_of("NAME").unwrap();
        if file_exists(&name.to_string()) {
            println!("A file or directory with that name already exists");
            exit(1);
        } else {
            match create_dir(name.clone()) {
                Ok(_) => println!("Created directory '{}'", name),
                Err(e) => {
                    println!("Could not create direcotry '{}'. {:?}", name, e);
                    exit(1);
                }
            }
            if let Err(_) = env::set_current_dir(Path::new(&*name)) {
                println!("Could not change directory!");
                exit(1);
            }
        }
    }

    if !dir_is_empty(&".".to_string()) {
        println!("Direcotry is not empty!");
        exit(1);
    }

    if let Some(dirs) = config.mkdir {
        for dir in dirs {
            if !file_exists(&dir) {
                match create_dir(dir.clone()) {
                    Ok(_) => println!("Created directory '{}'", dir),
                    Err(e) => println!("Could not create directory '{}'. {:?}", dir, e),
                }
            } else {
                println!("Directory '{}' already exists", dir);
            }
        }
    }

    if let Some(gi) = config.gitignore {
        let ign = gitignore::get_gitignore(gi).unwrap();
        let file = OpenOptions::new()
            .create_new(true)
            .append(true)
            .open("gitignore");
        if let Ok(mut file) = file {
            writeln!(file, "{}", ign);
        } else {
            println!("Could not write .gitignore");
        }
    }

    if let Some(fnames) = config.touch {
        for file in fnames {
            if !create_file(&file) {
                println!("Could not create file '{}'", file);
            }
        }
    }

    if let Some(cmds) = config.exec {
        for cmd in cmds {
            println!("Executing '{}'", cmd);
            match exec(&cmd) {
                Ok((out, err)) => {
                    println!("stdout: {}", out);
                    println!("stderr: {}", err);
                }
                Err(e) => println!("Failed to execute: {:?}", e),
            }
        }
    }
}

fn dir_is_empty(dir: &String) -> bool {
    let paths = read_dir(dir).unwrap();

    for _ in paths {
        return false;
    }
    true
}

fn file_exists(name: &String) -> bool {
    Path::new(&name).exists()
}

fn exec(cmd: &String) -> Result<(String, String)> {
    #[cfg(unix)]
    let shell = "sh";
    #[cfg(unix)]
    let arg1 = "-c";
    #[cfg(windows)]
    let shell = "cmd.exe";
    #[cfg(windows)]
    let arg1 = "/C";

    let out = match Command::new(shell).arg(arg1).arg(cmd).output() {
        Ok(o) => o,
        Err(e) => return Err(e),
    };

    let stdout = match String::from_utf8(out.stdout) {
        Ok(so) => so,
        Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)),
    };

    let stderr = match String::from_utf8(out.stderr) {
        Ok(se) => se,
        Err(e) => return Err(Error::new(ErrorKind::InvalidInput, e)),
    };

    Ok((stdout, stderr))
}

fn create_file(file_name: &String) -> bool {
    !file_exists(&file_name) &&
    match OpenOptions::new()
              .append(true)
              .create(true)
              .open(file_name) {
        Ok(_) => true,
        Err(_) => false,
    }
}

fn parse_config(file_name: String) -> Result<Config> {
    let file = File::open(file_name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    match toml::from_str(&contents) {
        Ok(c) => Ok(c),
        Err(err) => Err(Error::new(ErrorKind::InvalidInput, err)),
    }
}

#[test]
fn test_file_exists() {
    assert!(file_exists(&"test/foo.toml".to_string()));
    assert!(!file_exists(&"test/none".to_string()));
}

#[test]
fn test_parse_config() {
    let conf = parse_config("test/foo.toml".to_string()).unwrap();
    let gi = conf.gitignore.unwrap();
    assert_eq!(gi, vec!["rust".to_string(), "vim".to_string()]);

    let mkd = conf.mkdir.unwrap();
    assert_eq!(mkd, vec!["b".to_string()]);

    let touch = conf.touch.unwrap();
    assert_eq!(touch, vec!["a".to_string()]);

    let exec = conf.exec.unwrap();
    assert_eq!(exec, vec!["touch asdf".to_string()]);
}

#[test]
fn test_exec() {
    let (stdout, stderr) = exec(&"echo -n test".to_string()).unwrap();
    assert_eq!(stdout, "test".to_string());
    assert_eq!(stderr, "".to_string());
    let (stdout, stderr) = exec(&"echo -n test 1>&2".to_string()).unwrap();
    assert_eq!(stdout, "".to_string());
    assert_eq!(stderr, "test".to_string());
}

#[test]
fn test_dir_is_empty() {
    let is_empty = dir_is_empty(&"./test".to_string());
    assert!(!is_empty);
}
<|endoftext|>


<commit_before>use crate::compiler::Compiler;
use mrdovm::assemble_and_run;
use std::fs;
use structopt::StructOpt;

pub mod compiler;
pub mod expression_parsers;
pub mod factor_parsers;
pub mod operand_parsers;
pub mod operator_parsers;
pub mod program_parser;
pub mod term_parsers;
pub mod tokens;
pub mod visitor;

#[derive(StructOpt)]
struct CLI {
    #[structopt(parse(from_os_str))]
    program: Option<std::path::PathBuf>,
    repl_mode: Option<String>,
}

enum ReplMode {
    Assembler,
    HighLevel,
}

fn main() {
    let args = CLI::from_args();

    let mut compiler = Compiler::new();

    match args.program {
        Some(p) => {
            let source = read_file(&p);
            let assembly = compiler.compile(&source);

            println!("assembly\n{}\nEOF", assembly);

            assemble_and_run(&assembly);
        }
        None => {
            let repl_mode = match args.repl_mode {
                Some(mode) => match mode.as_str() {
                    "assembly" => ReplMode::Assembler,
                    "highlevel" => ReplMode::HighLevel,
                    _ => ReplMode::HighLevel,
                },
                None => ReplMode::HighLevel,
            };
            run_repl(repl_mode);
        }
    }
}

// TODO: add high-level REPL to mrdo.

fn read_file(tmp: &std::path::PathBuf) -> String {
    let contents = fs::read_to_string(tmp);
    match contents {
        Ok(_) => contents.unwrap(),
        Err(e) => {
            println!("Error reading file {:?}: {:?}", tmp.to_str(), e);
            std::process::exit(1);
        }
    }
}

// TODO:
fn run_repl(_mode: ReplMode) {}
<commit_msg>separate assembler from vm<commit_after>use crate::compiler::Compiler;
use mrdoasm::Assembler;
use mrdovm::run;
use std::fs;
use structopt::StructOpt;

pub mod compiler;
pub mod expression_parsers;
pub mod factor_parsers;
pub mod operand_parsers;
pub mod operator_parsers;
pub mod program_parser;
pub mod term_parsers;
pub mod tokens;
pub mod visitor;

#[derive(StructOpt)]
struct CLI {
    #[structopt(parse(from_os_str))]
    program: Option<std::path::PathBuf>,
    repl_mode: Option<String>,
}

enum ReplMode {
    Assembler,
    HighLevel,
}

fn main() {
    let args = CLI::from_args();

    let mut compiler = Compiler::new();

    match args.program {
        Some(p) => {
            let source = read_file(&p);
            let assembly = compiler.compile(&source);

            println!("assembly\n{}\nEOF", assembly);
            let mut asm = Assembler::new();
            let program = asm.assemble(&assembly);
            match program {
                Ok(p) => {
                    if let Err(e) = run(&p) {
                        println!("vm error: {:?}", e);
                        std::process::exit(1);
                    }
                }
                Err(e) => {
                    println!("assembler error: {:?}", e);
                    std::process::exit(1);
                }
            }
        }
        None => {
            let repl_mode = match args.repl_mode {
                Some(mode) => match mode.as_str() {
                    "assembly" => ReplMode::Assembler,
                    "highlevel" => ReplMode::HighLevel,
                    _ => ReplMode::HighLevel,
                },
                None => ReplMode::HighLevel,
            };
            run_repl(repl_mode);
        }
    }
}

// TODO: add high-level REPL to mrdo.

fn read_file(tmp: &std::path::PathBuf) -> String {
    let contents = fs::read_to_string(tmp);
    match contents {
        Ok(_) => contents.unwrap(),
        Err(e) => {
            println!("Error reading file {:?}: {:?}", tmp.to_str(), e);
            std::process::exit(1);
        }
    }
}

// TODO:
fn run_repl(_mode: ReplMode) {}
<|endoftext|>


<commit_before>struct Philosopher {
    name: String
}

impl Philosopher {
    fn new(name: &str) -> Philosopher {
        Philosopher {
            name: name.to_string()
        }
    }

    fn eat(&self) {
        println!("{} is done eating.", self.name);
    }
}

fn main() {
    let philosophers = vec![
        Philosopher::new("Judith Butler"),
        Philosopher::new("Gilles Deleuze"),
        Philosopher::new("Karl Marx"),
        Philosopher::new("Emma Goldman"),
        Philosopher::new("Michel Foucault"),
    ];
}
<commit_msg>Call `eat()` on every philosopher in the vector<commit_after>struct Philosopher {
    name: String
}

impl Philosopher {
    fn new(name: &str) -> Philosopher {
        Philosopher {
            name: name.to_string()
        }
    }

    fn eat(&self) {
        println!("{} is done eating.", self.name);
    }
}

fn main() {
    let philosophers = vec![
        Philosopher::new("Judith Butler"),
        Philosopher::new("Gilles Deleuze"),
        Philosopher::new("Karl Marx"),
        Philosopher::new("Emma Goldman"),
        Philosopher::new("Michel Foucault"),
    ];

    for p in &philosophers {
        p.eat();
    }
}
<|endoftext|>


<commit_before>#![feature(globs)]
#![feature(macro_rules)]

extern crate xml;

use std::io::{File, BufferedReader};
use std::default::Default;
use std::num::from_str_radix;

use xml::reader::EventReader;
use fromxml::{FromXml, XmlIter};

mod fromxml;

deriving_fromxml! {
    struct Device {
        vendor:Option<String>,
        vendorID:Option<String>,
        licenseText:Option<String>,
        series:Option<String>,
        version:Option<String>,
        description:Option<String>,
        cpu:Option<CPU>,
        peripherals: Vec<Peripheral>,
    }
}

deriving_fromxml! {
    struct Peripheral {
        name: String,
        version:Option<String>,
        description:Option<String>,
        groupName:Option<String>,
        prependToName:Option<String>,
        baseAddress:Option<String>,
        access:Option<String>,
        interrupt:Option<Interrupt>,
        registers: Vec<Regs>,
    }
}

deriving_fromxml! {
    struct Interrupt {
        name: String,
        value:Option<uint>,
    }
}

deriving_fromxml! {
    enum Regs {
        register(Register),
        cluster(Cluster),
    }
}

deriving_fromxml! {
    struct Register {
        name: String,
        dim:Option<uint>,
        dimIncrement:Option<String>,
        description:Option<String>,
        addressOffset:Option<String>,
        size:Option<uint>,
        access:Option<String>,
        fields: Vec<Field>,
    }
}

#[deriving(Default, Show)]
struct Cluster {
    name: String,
    registers: Vec<Register>,
}

impl ::fromxml::FromXml for Cluster {
    fn from_xml(iter: &mut ::fromxml::XmlIter) -> Result<Cluster, ()> {
        let mut obj = Cluster{..Default::default()};
        try!(iter.each_child(|iter| {
            match iter.tag_name() {
                    "name" => obj.name = try!(::fromxml::FromXml::from_xml(iter)),
                    "register" => obj.registers.push(try!(::fromxml::FromXml::from_xml(iter))),
                    _ => try!(iter.skip_node())
            }
            Ok(())
        }));
        Ok(obj)
    }
}

deriving_fromxml! {
    struct Field {
        name: String,
        description:Option<String>,
        bitOffset:Option<uint>,
        bitWidth:Option<uint>,
        access:Option<String>,
        enumeratedValues: Vec<EnumeratedValue>,
    }
}

deriving_fromxml! {
    struct EnumeratedValue {
        name: String,
        value: String,
        description:Option<String>,
    }
}

deriving_fromxml! {
    struct CPU {
        name:Option<String>,
        revision:Option<String>,
    }
}

fn parse_num(s: &str) -> Option<u32> {
    if s.slice_to(2) == "0x" {
        from_str_radix(s.slice_from(2), 16)
    } else {
        from_str_radix(s, 10)
    }
}

fn write_doc_comment(doc: Option<&String>) {
    if let Some(d) = doc {
        print!(" //= {}", d);
    }
}

fn write_device(device: &Device) {
    for peripheral in device.peripherals.iter() {
        write_peripheral(peripheral);
    }
}

fn write_peripheral(peripheral: &Peripheral) {
    let mut registers = vec![];

    println!("ioregs!({} = {{", peripheral.name);
    for register in peripheral.registers.iter() {
        match *register {
            Regs::register(ref r) => registers.push(r),
            Regs::cluster(ref c) => {
                let mut cluster_regs: Vec<_> = c.registers.iter().collect();

                println!("    // cluster: {}", c.name);
                write_registers(&mut *cluster_regs);
            }
        }
    }
    write_registers(&mut *registers);
    println!("}});")
}

fn write_registers(registers: &mut[&Register]) {
    registers.as_mut_slice().sort_by(|a, b| {
        let a = a.addressOffset.as_ref().map(|x| parse_num(x.as_slice()));
        let b = b.addressOffset.as_ref().map(|x| parse_num(x.as_slice()));
        a.cmp(&b)
    });

    for &r in registers.iter() {
        write_register(r);
    }
}

fn write_register(register: &Register) {
    if let (Some(dim), Some(dim_increment)) = (register.dim, register.dimIncrement.as_ref()) {
        println!("    // repeat: {} increment {}", dim, dim_increment);
    }
    let offset = register.addressOffset.as_ref().map_or("", |x| x.as_slice());
    let size = register.size.unwrap_or(0);
    print!("    {} => reg{} {} {{", offset, size, register.name);
    write_doc_comment(register.description.as_ref());
    print!("\n");

    for field in register.fields.iter() {
        write_field(field);
    }
    println!("    }}");
}

fn write_field(field: &Field) {
    let lsb = field.bitOffset.unwrap();
    let width = field.bitWidth.unwrap();
    if field.name == "RESERVED" { return }

    print!("         {}", lsb);

    if width > 1 {
        print!("..{}", lsb + width - 1);
    }

    print!(" => {}", field.name);

    if field.enumeratedValues.len() == 0 {
        print!(",");
    } else {
        print!(" {{");
    }

    write_doc_comment(field.description.as_ref());
    print!("\n");

    if field.enumeratedValues.len() != 0 {
        for en in field.enumeratedValues.iter() {
            if en.name.len() == 0 { continue } // TODO: this is a <name>, not an <enumeratedValues>
            print!("             {} => {},", en.value, en.name);
            write_doc_comment(en.description.as_ref());
            print!("\n");
        }
        println!("         }}");
    }
}

fn main() {
    let file = File::open(&Path::new("file.xml")).unwrap();
    let reader = BufferedReader::new(file);

    let mut parser = EventReader::new(reader);
    let mut iter = XmlIter::new(parser.events()).unwrap();
    let device: Device = FromXml::from_xml(&mut iter).unwrap();

    write_device(&device);
}
<commit_msg>Added support for bitRange tag '[bit_end:bit_start]'<commit_after>#![feature(globs)]
#![feature(macro_rules)]

extern crate xml;

use std::io::{File, BufferedReader};
use std::default::Default;
use std::num::from_str_radix;

use xml::reader::EventReader;
use fromxml::{FromXml, XmlIter};

mod fromxml;

deriving_fromxml! {
    struct Device {
        vendor:Option<String>,
        vendorID:Option<String>,
        licenseText:Option<String>,
        series:Option<String>,
        version:Option<String>,
        description:Option<String>,
        cpu:Option<CPU>,
        peripherals: Vec<Peripheral>,
    }
}

deriving_fromxml! {
    struct Peripheral {
        name: String,
        version:Option<String>,
        description:Option<String>,
        groupName:Option<String>,
        prependToName:Option<String>,
        baseAddress:Option<String>,
        access:Option<String>,
        interrupt:Option<Interrupt>,
        registers: Vec<Regs>,
    }
}

deriving_fromxml! {
    struct Interrupt {
        name: String,
        value:Option<uint>,
    }
}

deriving_fromxml! {
    enum Regs {
        register(Register),
        cluster(Cluster),
    }
}

deriving_fromxml! {
    struct Register {
        name: String,
        dim:Option<uint>,
        dimIncrement:Option<String>,
        description:Option<String>,
        addressOffset:Option<String>,
        size:Option<uint>,
        access:Option<String>,
        fields: Vec<Field>,
    }
}

#[deriving(Default, Show)]
struct Cluster {
    name: String,
    registers: Vec<Register>,
}

impl ::fromxml::FromXml for Cluster {
    fn from_xml(iter: &mut ::fromxml::XmlIter) -> Result<Cluster, ()> {
        let mut obj = Cluster{..Default::default()};
        try!(iter.each_child(|iter| {
            match iter.tag_name() {
                    "name" => obj.name = try!(::fromxml::FromXml::from_xml(iter)),
                    "register" => obj.registers.push(try!(::fromxml::FromXml::from_xml(iter))),
                    _ => try!(iter.skip_node())
            }
            Ok(())
        }));
        Ok(obj)
    }
}

deriving_fromxml! {
    struct Field {
        name: String,
        description:Option<String>,
        bitOffset:Option<uint>,
        bitWidth:Option<uint>,
        bitRange:Option<String>,
        access:Option<String>,
        enumeratedValues: Vec<EnumeratedValue>,
    }
}

deriving_fromxml! {
    struct EnumeratedValue {
        name: String,
        value: String,
        description:Option<String>,
    }
}

deriving_fromxml! {
    struct CPU {
        name:Option<String>,
        revision:Option<String>,
    }
}

fn parse_num(s: &str) -> Option<u32> {
    if s.slice_to(2) == "0x" {
        from_str_radix(s.slice_from(2), 16)
    } else {
        from_str_radix(s, 10)
    }
}

fn write_doc_comment(doc: Option<&String>) {
    if let Some(d) = doc {
        print!(" //= {}", d);
    }
}

fn write_device(device: &Device) {
    for peripheral in device.peripherals.iter() {
        write_peripheral(peripheral);
    }
}

fn write_peripheral(peripheral: &Peripheral) {
    let mut registers = vec![];

    println!("ioregs!({} = {{", peripheral.name);
    for register in peripheral.registers.iter() {
        match *register {
            Regs::register(ref r) => registers.push(r),
            Regs::cluster(ref c) => {
                let mut cluster_regs: Vec<_> = c.registers.iter().collect();

                println!("    // cluster: {}", c.name);
                write_registers(&mut *cluster_regs);
            }
        }
    }
    write_registers(&mut *registers);
    println!("}});")
}

fn write_registers(registers: &mut[&Register]) {
    registers.as_mut_slice().sort_by(|a, b| {
        let a = a.addressOffset.as_ref().map(|x| parse_num(x.as_slice()));
        let b = b.addressOffset.as_ref().map(|x| parse_num(x.as_slice()));
        a.cmp(&b)
    });

    for &r in registers.iter() {
        write_register(r);
    }
}

fn write_register(register: &Register) {
    if let (Some(dim), Some(dim_increment)) = (register.dim, register.dimIncrement.as_ref()) {
        println!("    // repeat: {} increment {}", dim, dim_increment);
    }
    let offset = register.addressOffset.as_ref().map_or("", |x| x.as_slice());
    let size = register.size.unwrap_or(0);
    print!("    {} => reg{} {} {{", offset, size, register.name);
    write_doc_comment(register.description.as_ref());
    print!("\n");

    for field in register.fields.iter() {
        write_field(field);
    }
    println!("    }}");
}

fn write_field(field: &Field) {
    if field.name == "RESERVED" { return }

    let (lsb, width) = if let Some(ref br) = field.bitRange {
        let split: Vec<&str> = br.as_slice().split(':').collect();
        assert_eq!(split.len(), 2);
        let end: uint = split[0].slice_from(1).parse().unwrap();
        let start: uint = split[1].slice_to(split[1].len()-1).parse().unwrap();
        (start, end-start+1)
    } else {
        (field.bitOffset.unwrap(), field.bitWidth.unwrap())
    };

    print!("         {}", lsb);

    if width > 1 {
        print!("..{}", lsb + width - 1);
    }

    print!(" => {}", field.name);

    if field.enumeratedValues.len() == 0 {
        print!(",");
    } else {
        print!(" {{");
    }

    write_doc_comment(field.description.as_ref());
    print!("\n");

    if field.enumeratedValues.len() != 0 {
        for en in field.enumeratedValues.iter() {
            if en.name.len() == 0 { continue } // TODO: this is a <name>, not an <enumeratedValues>
            print!("             {} => {},", en.value, en.name);
            write_doc_comment(en.description.as_ref());
            print!("\n");
        }
        println!("         }}");
    }
}

fn main() {
    let file = File::open(&Path::new("file.xml")).unwrap();
    let reader = BufferedReader::new(file);

    let mut parser = EventReader::new(reader);
    let mut iter = XmlIter::new(parser.events()).unwrap();
    let device: Device = FromXml::from_xml(&mut iter).unwrap();

    write_device(&device);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate conrod;
extern crate xml;
extern crate piston_window;
extern crate find_folder;

use std::fs::File;
use std::io::Read;

use conrod::{Theme, Widget};
use piston_window::*;

use xml::{Parser, ElementBuilder};

/// Conrod is backend agnostic. Here, we define the `piston_window` backend to use for our `Ui`.
type Backend = (piston_window::G2dTexture<'static>, piston_window::Glyphs);
type Ui = conrod::Ui<Backend>;
type UiCell<'a> = conrod::UiCell<'a, Backend>;

// mod doc;

fn main() {

    let mut file = File::open("tests/documents/testrect.svg").unwrap();

    let mut file_string = String::new();
    if let Err(err) = file.read_to_string(&mut file_string) {
        println!("Reading failed: {}", err);
        std::process::exit(1);
    };
    let mut parser = Parser::new();
    let mut eb = ElementBuilder::new();

    parser.feed_str(&file_string);
    let doc = parser.filter_map(|x| eb.handle_event(x));

    // Construct the window.
    let mut window: PistonWindow = WindowSettings::new("Inkrust", [720, 360])
                                       .opengl(piston_window::OpenGL::V3_2)
                                       .samples(4)
                                       .exit_on_esc(true)
                                       .build()
                                       .unwrap();

    // Construct our `Ui`.
    let mut ui = {
        let assets = find_folder::Search::KidsThenParents(3, 5)
                         .for_folder("assets")
                         .unwrap();
        let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
        let theme = Theme::default();
        let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.clone()).unwrap();
        Ui::new(glyph_cache, theme)
    };

    window.set_ups(60);

    for elem in doc {
        let e = elem.unwrap();

        println!("{}", e);
    }

    // Poll events from the window.
    while let Some(event) = window.next() {
        ui.handle_event(event.clone());
        event.update(|_| ui.set_widgets(set_ui));
        window.draw_2d(&event, |c, g| ui.draw_if_changed(c, g));
    }

    // Declare the `WidgetId`s and instantiate the widgets.
    fn set_ui(ref mut ui: UiCell) {
        use conrod::{Canvas, Circle, Line, Oval, PointPath, Polygon, Positionable, Rectangle};
        use std::iter::once;

        // Generate a unique const `WidgetId` for each widget.
        widget_ids!{
	        CANVAS,
	        LINE,
	        POINT_PATH,
	        RECTANGLE_FILL,
	        RECTANGLE_OUTLINE,
	        TRAPEZOID,
	        OVAL_FILL,
	        OVAL_OUTLINE,
	        CIRCLE,
	    };

        // The background canvas upon which we'll place our widgets.
        Canvas::new().pad(80.0).set(CANVAS, ui);

        Line::centred([-40.0, -40.0], [40.0, 40.0]).top_left_of(CANVAS).set(LINE, ui);

        let left = [-40.0, -40.0];
        let top = [0.0, 40.0];
        let right = [40.0, -40.0];
        let points = once(left).chain(once(top)).chain(once(right));
        PointPath::centred(points).down(80.0).set(POINT_PATH, ui);

        Rectangle::fill([80.0, 80.0]).down(80.0).set(RECTANGLE_FILL, ui);

        Rectangle::outline([80.0, 80.0]).down(80.0).set(RECTANGLE_OUTLINE, ui);

        let bl = [-40.0, -40.0];
        let tl = [-20.0, 40.0];
        let tr = [20.0, 40.0];
        let br = [40.0, -40.0];
        let points = once(bl).chain(once(tl)).chain(once(tr)).chain(once(br));
        Polygon::centred_fill(points).right_from(LINE, 80.0).set(TRAPEZOID, ui);

        Oval::fill([40.0, 80.0]).down(80.0).align_middle_x().set(OVAL_FILL, ui);

        Oval::outline([80.0, 40.0]).down(100.0).align_middle_x().set(OVAL_OUTLINE, ui);

        Circle::fill(40.0).down(100.0).align_middle_x().set(CIRCLE, ui);
    }
}
<commit_msg>Trying to pass document reference into rendering update.<commit_after>#[macro_use]
extern crate conrod;
extern crate xml;
extern crate piston_window;
extern crate find_folder;

use std::fs::File;
use std::io::Read;
use std::sync::mpsc;

use conrod::{Theme, Widget};
use piston_window::*;

use xml::{Parser, Element, ElementBuilder};

/// Conrod is backend agnostic. Here, we define the `piston_window` backend to use for our `Ui`.
type Backend = (piston_window::G2dTexture<'static>, piston_window::Glyphs);
type Ui = conrod::Ui<Backend>;
type UiCell<'a> = conrod::UiCell<'a, Backend>;

// mod doc;

struct InkApp {
    document: Option<ElementBuilder>,

        elem_sender: mpsc::Sender<(usize, usize, bool)>,
            elem_receiver: mpsc::Receiver<(usize, usize, bool)>,
}

impl InkApp {
    fn new() -> Self {
        let (elem_sender, elem_receiver) = mpsc::channel();
        InkApp { document: None,
            elem_sender: elem_sender,
                        elem_receiver: elem_receiver,
        }
    }

    fn setDocument(&mut self, document: ElementBuilder) {
        self.document = Some(document);
    }
}

fn main() {

    let mut file = File::open("tests/documents/testrect.svg").unwrap();

    let mut file_string = String::new();
    if let Err(err) = file.read_to_string(&mut file_string) {
        println!("Reading failed: {}", err);
        std::process::exit(1);
    };
    let mut parser = Parser::new();
    let mut eb = ElementBuilder::new();

    parser.feed_str(&file_string);
    let doc = parser.filter_map(|x| eb.handle_event(x));
    let mut app = InkApp::new();
    app.setDocument(eb);

    // Construct the window.
    let mut window: PistonWindow = WindowSettings::new("Inkrust", [720, 360])
        .opengl(piston_window::OpenGL::V3_2)
        .samples(4)
        .exit_on_esc(true)
        .build()
        .unwrap();

    // Construct our `Ui`.
    let mut ui = {
        let assets = find_folder::Search::KidsThenParents(3, 5)
            .for_folder("assets")
            .unwrap();
        let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
        let theme = Theme::default();
        let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.clone()).unwrap();
        Ui::new(glyph_cache, theme)
    };

    window.set_ups(60);

    // Poll events from the window.
    while let Some(event) = window.next() {
        ui.handle_event(event.clone());
        event.update(|_| ui.set_widgets(|mut ui| set_widgets(&mut ui, &mut app)));
        window.draw_2d(&event, |c, g| ui.draw_if_changed(c, g));
    }
}

// Declare the `WidgetId`s and instantiate the widgets.
fn set_widgets(ui: &mut UiCell, app: &mut InkApp) {
    use conrod::{Canvas, Circle, Line, Oval, PointPath, Polygon, Positionable, Rectangle};
    use std::iter::once;

    // Generate a unique const `WidgetId` for each widget.
    widget_ids!{
	        CANVAS,
	        LINE,
	        POINT_PATH,
	        RECTANGLE_FILL,
	        RECTANGLE_OUTLINE,
	        TRAPEZOID,
	        OVAL_FILL,
	        OVAL_OUTLINE,
	        CIRCLE,
	    };

    // The background canvas upon which we'll place our widgets.
    Canvas::new().pad(80.0).set(CANVAS, ui);

    Line::centred([-40.0, -40.0], [40.0, 40.0]).top_left_of(CANVAS).set(LINE, ui);

    let left = [-40.0, -40.0];
    let top = [0.0, 40.0];
    let right = [40.0, -40.0];
    let points = once(left).chain(once(top)).chain(once(right));
    PointPath::centred(points).down(80.0).set(POINT_PATH, ui);

    Rectangle::fill([80.0, 80.0]).down(80.0).set(RECTANGLE_FILL, ui);

    Rectangle::outline([80.0, 80.0]).down(80.0).set(RECTANGLE_OUTLINE, ui);

    let bl = [-40.0, -40.0];
    let tl = [-20.0, 40.0];
    let tr = [20.0, 40.0];
    let br = [40.0, -40.0];
    let points = once(bl).chain(once(tl)).chain(once(tr)).chain(once(br));
    Polygon::centred_fill(points).right_from(LINE, 80.0).set(TRAPEZOID, ui);

    Oval::fill([40.0, 80.0]).down(80.0).align_middle_x().set(OVAL_FILL, ui);

    Oval::outline([80.0, 40.0]).down(100.0).align_middle_x().set(OVAL_OUTLINE, ui);

    Circle::fill(40.0).down(100.0).align_middle_x().set(CIRCLE, ui);
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate ketos;
use ketos::*;

extern crate es;
use es::modes::ModeList;
use es::exposed::*;

use std::rc::Rc;
use std::path::Path;

fn main() {
    let global = Rc::new(ModeList::new("global"));
    let major = Rc::new(ModeList::new("major"));
    let minor = Rc::new(ModeList::new("minor"));

    let interp = Interpreter::new();

    ketos_fn! {
        interp.scope() => "new-mode" =>
        fn new_mode(list: &ModeList, name: &str, desc: &str) -> ()
    }

    ketos_fn! {
        interp.scope() => "add-key" =>
        fn add_key(list: &ModeList, name: &str, key: &str, call: &Value) -> ()
    }

    ketos_fn! {
        interp.scope() => "down-line" =>
        fn down_line(num: u32) -> ()
    }

    let res = interp.run_file(Path::new("test.ket"));
    match res {
        Ok(_) => {},
        Err(e) => {
            println!("{:?}", e);
        }
    }

    interp.call("es-main",
                vec![Value::Foreign(global.clone()),
                     Value::Foreign(major.clone()),
                     Value::Foreign(minor.clone())]).unwrap();

    global.call_key_callback(&interp, "default".into(), "j".into()).unwrap();

    //global.list();
    //major.list();
    //minor.list();
}
<commit_msg>lol welcome back<commit_after>
#[macro_use]
extern crate ketos;
use ketos::*;

extern crate es;
use es::modes::ModeList;
use es::exposed::*;

use std::rc::Rc;
use std::path::Path;

fn main() {
    let global = Rc::new(ModeList::new("global"));
    let major = Rc::new(ModeList::new("major"));
    let minor = Rc::new(ModeList::new("minor"));

    let interp = Interpreter::new();

    ketos_fn! {
        interp.scope() => "new-mode" =>
        fn new_mode(list: &ModeList, name: &str, desc: &str) -> ()
    }

    ketos_fn! {
        interp.scope() => "add-key" =>
        fn add_key(list: &ModeList, name: &str, key: &str, call: &Value) -> ()
    }

    ketos_fn! {
        interp.scope() => "down-line" =>
        fn down_line(num: u32) -> ()
    }

    let res = interp.run_file(Path::new("config.ket"));
    match res {
        Ok(_) => {},
        Err(e) => {
            println!("{:?}", e);
        }
    }

    interp.call("es-main",
                vec![Value::Foreign(global.clone()),
                     Value::Foreign(major.clone()),
                     Value::Foreign(minor.clone())]).unwrap();

    global.call_key_callback(&interp, "default".into(), "j".into()).unwrap();

    //global.list();
    //major.list();
    //minor.list();
}
<|endoftext|>


<commit_before>#![feature(core, std_misc, collections, env, path, io)]

extern crate getopts;
extern crate image;

use std::default::Default;
use std::old_io::fs::File;

mod css;
mod dom;
mod html;
mod layout;
mod style;
mod painting;
mod pdf;

fn main() {
    // Parse command-line options:
    let mut opts = getopts::Options::new();
    opts.optopt("h", "html", "HTML document", "FILENAME");
    opts.optopt("c", "css", "CSS stylesheet", "FILENAME");
    opts.optopt("o", "output", "Output file", "FILENAME");
    opts.optopt("f", "format", "Output file format", "png | pdf");

    let matches = match opts.parse(std::env::args().skip(1)) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };

    let png = match matches.opt_str("f") {
        None => true,
        Some(format) => match &*format {
            "png" => true,
            "pdf" => false,
            _ => panic!("Unknow output format: {}", format),
        }
    };

    // Read input files:
    let read_source = |&: arg_filename: Option<String>, default_filename: &str| {
        let path = match arg_filename {
            Some(ref filename) => &**filename,
            None => default_filename,
        };
        File::open(&Path::new(path)).read_to_string().unwrap()
    };
    let html = read_source(matches.opt_str("h"), "examples/test.html");
    let css  = read_source(matches.opt_str("c"), "examples/test.css");

    // Since we don't have an actual window, hard-code the "viewport" size.
    let initial_containing_block = layout::Dimensions {
        content: layout::Rect { x: 0.0, y: 0.0, width: 800.0, height: 600.0 },
        padding: Default::default(),
        border: Default::default(),
        margin: Default::default(),
    };

    // Parsing and rendering:
    let root_node = html::parse(html);
    let stylesheet = css::parse(css);
    let style_root = style::style_tree(&root_node, &stylesheet);
    let layout_root = layout::layout_tree(&style_root, initial_containing_block);

    // Create the output file:
    let default_filename = if png { "output.png" } else { "output.pdf" };
    let filename = matches.opt_str("o").unwrap_or(default_filename.to_string());
    let mut file = File::create(&Path::new(&*filename)).unwrap();

    let result_ok;
    if png {
        let canvas = painting::paint(&layout_root, initial_containing_block.content);

        // Save an image:
        let (w, h) = (canvas.width as u32, canvas.height as u32);
        let buffer: Vec<image::Rgba<u8>> = unsafe { std::mem::transmute(canvas.pixels) };
        let img = image::ImageBuffer::from_fn(w, h, Box::new(|&: x: u32, y: u32| buffer[(y * w + x) as usize]));

        result_ok = image::ImageRgba8(img).save(file, image::PNG).is_ok();
    } else {
        result_ok = pdf::render(&layout_root, initial_containing_block.content, &mut file).is_ok();
    }

    if result_ok {
        println!("Saved output as {}", filename)
    } else {
        println!("Error saving output as {}", filename)
    }
}
<commit_msg>Fix build error with latest image library<commit_after>#![feature(core, std_misc, collections, env, path, io)]

extern crate getopts;
extern crate image;

use std::default::Default;
use std::old_io::fs::File;

mod css;
mod dom;
mod html;
mod layout;
mod style;
mod painting;
mod pdf;

fn main() {
    // Parse command-line options:
    let mut opts = getopts::Options::new();
    opts.optopt("h", "html", "HTML document", "FILENAME");
    opts.optopt("c", "css", "CSS stylesheet", "FILENAME");
    opts.optopt("o", "output", "Output file", "FILENAME");
    opts.optopt("f", "format", "Output file format", "png | pdf");

    let matches = match opts.parse(std::env::args().skip(1)) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };

    let png = match matches.opt_str("f") {
        None => true,
        Some(format) => match &*format {
            "png" => true,
            "pdf" => false,
            _ => panic!("Unknow output format: {}", format),
        }
    };

    // Read input files:
    let read_source = |&: arg_filename: Option<String>, default_filename: &str| {
        let path = match arg_filename {
            Some(ref filename) => &**filename,
            None => default_filename,
        };
        File::open(&Path::new(path)).read_to_string().unwrap()
    };
    let html = read_source(matches.opt_str("h"), "examples/test.html");
    let css  = read_source(matches.opt_str("c"), "examples/test.css");

    // Since we don't have an actual window, hard-code the "viewport" size.
    let initial_containing_block = layout::Dimensions {
        content: layout::Rect { x: 0.0, y: 0.0, width: 800.0, height: 600.0 },
        padding: Default::default(),
        border: Default::default(),
        margin: Default::default(),
    };

    // Parsing and rendering:
    let root_node = html::parse(html);
    let stylesheet = css::parse(css);
    let style_root = style::style_tree(&root_node, &stylesheet);
    let layout_root = layout::layout_tree(&style_root, initial_containing_block);

    // Create the output file:
    let default_filename = if png { "output.png" } else { "output.pdf" };
    let filename = matches.opt_str("o").unwrap_or(default_filename.to_string());
    let mut file = File::create(&Path::new(&*filename)).unwrap();

    let result_ok;
    if png {
        let canvas = painting::paint(&layout_root, initial_containing_block.content);

        // Save an image:
        let (w, h) = (canvas.width as u32, canvas.height as u32);
        let buffer: Vec<image::Rgba<u8>> = unsafe { std::mem::transmute(canvas.pixels) };
        let img = image::ImageBuffer::from_fn(w, h, Box::new(|&: x: u32, y: u32| buffer[(y * w + x) as usize]));

        result_ok = image::ImageRgba8(img).save(&mut file, image::PNG).is_ok();
    } else {
        result_ok = pdf::render(&layout_root, initial_containing_block.content, &mut file).is_ok();
    }

    if result_ok {
        println!("Saved output as {}", filename)
    } else {
        println!("Error saving output as {}", filename)
    }
}
<|endoftext|>


<commit_before>#![feature(io)]

extern crate docopt;
extern crate iron;
extern crate "rustc-serialize" as rustc_serialize;

use std::old_io::net::ip::Ipv4Addr;

use docopt::Docopt;

use iron::mime::Mime;
use iron::prelude::*;
use iron::status;

static USAGE: &'static str = "
Usage: rustwarsaw [options]

Options:
    -p <port>, --port <port>  Port number [default: 3000]
    -h, --help  Show help and exit
";

#[derive(RustcDecodable)]
struct Args {
    flag_port: u16,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).decode())
        .unwrap_or_else(|e| e.exit());
    println!("Starting server on port {}", args.flag_port);
    Iron::new(|&: _: &mut Request| {
        let content_type: Mime = "text/html".parse().unwrap();
        Ok(Response::with((status::Ok, "Hello Rust Warsaw!")).set(content_type))
    }).listen((Ipv4Addr(127, 0, 0, 1), args.flag_port)).unwrap();
}
<commit_msg>Modernized main.rs<commit_after>extern crate docopt;
extern crate iron;
extern crate "rustc-serialize" as rustc_serialize;

use docopt::Docopt;

use iron::mime::Mime;
use iron::prelude::*;
use iron::status;

static USAGE: &'static str = "
Usage: rustwarsaw [options]

Options:
    -p <port>, --port <port>  Port number [default: 3000]
    -h, --help  Show help and exit
";

#[derive(RustcDecodable)]
struct Args {
    flag_port: u16,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).decode())
        .unwrap_or_else(|e| e.exit());
    println!("Starting server on port {}", args.flag_port);
    Iron::new(|_: &mut Request| {
        let content_type: Mime = "text/html".parse().unwrap();
        Ok(Response::with((status::Ok, "Hello Rust Warsaw!")).set(content_type))
    }).http(("127.0.0.1", args.flag_port)).unwrap();
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]

extern crate getopts;

use std::fs;
use std::io;
use std::io::{Read, Write};

use getopts::Options;

mod optimizer;
mod parser;
mod runner;
mod structs;

use parser::parse;
use runner::State;
use structs::OpStream;

fn main() {
    let mut opts = Options::new();
    opts.optflag("n", "dry-run", "don't actually run");
    opts.optflag("0", "no-optimize", "don't optimize");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(std::env::args().skip(1)) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut io::stderr(), "{}", f).unwrap();
            std::process::exit(2);
        }
    };
    if matches.opt_present("h") {
        print!("{}", opts.usage("Usage: brain_rust [options] FILE... "));
        return;
    }

    for filename in &matches.free[..] {
        match fs::File::open(filename)
                  .map(io::BufReader::new)
                  .and_then(|mut reader| {
                      let mut buffer = Vec::new();
                      reader.read_to_end(&mut buffer).map(|_| buffer)
                  })
                  .map_err(|e| format!("{}", e))
                  .and_then(|buffer| parse(&buffer[..])) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                if !matches.opt_present("0") {
                    opstream.optimize();
                }
                if !matches.opt_present("n") {
                    let mut state: State = Default::default();
                    state.run(opstream.get());
                }
            }
            Err(e) => {
                writeln!(&mut io::stderr(),
                         "Error while processing {}: {}",
                         filename,
                         e)
                    .unwrap();
            }
        }
    }
}
<commit_msg>refactor: cleanup main function<commit_after>#![feature(slice_patterns)]

extern crate getopts;

use std::fs;
use std::io;
use std::io::{Read, Write};

use getopts::Options;

mod optimizer;
mod parser;
mod runner;
mod structs;

use parser::parse;
use runner::State;
use structs::OpStream;

fn main() {
    let mut opts = Options::new();
    opts.optflag("n", "dry-run", "don't actually run");
    opts.optflag("0", "no-optimize", "don't optimize");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(std::env::args().skip(1)) {
        Ok(m) => m,
        Err(f) => {
            writeln!(&mut io::stderr(), "{}", f).unwrap();
            std::process::exit(2);
        }
    };
    if matches.opt_present("h") {
        print!("{}", opts.usage("Usage: brain_rust [options] FILE... "));
        return;
    }

    let dry_run = matches.opt_present("n");
    let no_optimize = matches.opt_present("0");

    for filename in &matches.free[..] {
        let buffer = match read_file(filename) {
            Ok(v) => v,
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while reading {}: {}", filename, e).unwrap();
                continue;
            }
        };
        let ops = match parse(&buffer[..]) {
            Ok(v) => v,
            Err(e) => {
                writeln!(&mut io::stderr(), "Error while parsing {}: {}", filename, e).unwrap();
                continue;
            }
        };
        let mut opstream = OpStream { ops: ops };
        if !no_optimize {
            opstream.optimize();
        }
        if !dry_run {
            let mut state: State = Default::default();
            state.run(opstream.get());
        }
    }
}

fn read_file(filename: &str) -> Result<Vec<u8>, io::Error> {
    let file = try!(fs::File::open(filename));
    let mut reader = io::BufReader::new(file);
    let mut buffer = Vec::new();
    try!(reader.read_to_end(&mut buffer));
    Ok(buffer)
}
<|endoftext|>