<commit_before>#[macro_use]
extern crate clap;

extern crate liboskar;
extern crate colored;

use colored::*;
use liboskar::prelude::*;
use clap::{App, AppSettings};
use std::env;
use std::path::PathBuf;
use std::process::Command;

#[allow(unknown_lints)]
#[allow(cyclomatic_complexity)]
fn main() {

    // command-line parser
    #[cfg(feature = "english")]
    let yaml = load_yaml!("cli/options-en.yml");
    #[cfg(feature = "francais")]
    let yaml = load_yaml!("cli/options-fr.yml");
    #[cfg(feature = "deutsch")]
    let yaml = load_yaml!("cli/options-de.yml");
    let matches = App::from_yaml(yaml)
        .version(crate_version!())
        .set_term_width(90)
        .setting(AppSettings::SubcommandRequired)
        .get_matches();

    if let Some(x) = matches.subcommand_matches("update") {

        let force = x.is_present("force");

        let s = if force {
            "curl -LSfs https://japaric.github.io/trust/install.sh | sh -s -- --git vmchale/project-init --force"
        } else {
            "curl -LSfs https://japaric.github.io/trust/install.sh | sh -s -- --git vmchale/project-init"
        };

        let script = Command::new("bash").arg("-c").arg(s).output().expect(
            "failed to execute update script.",
        );

        let script_string = String::from_utf8(script.stderr).unwrap();

        println!("{}", script_string);

    } else if let Some(command) = matches.subcommand_matches("clean") {

        // check that we aren't in the home dir
        let home_dir_str = match env::var("HOME") {
            Ok(val) => val,
            _ => "/home".to_string(),
        };

        let home_dir = PathBuf::from(home_dir_str);

        let regex = command.value_of("excludes").map(|r| check_regex(r));

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        let force = command.is_present("force");

        for dir in dirs {
            if (dir != home_dir) && !force {
                clean_project_dirs(dir, regex.clone());
            } else {
                eprintln!(
                    "{}: not cleaning directory '{}', as it is your home directory. To clean your home directory, rerun with --force.",
                    "Warning".yellow(),
                    dir.display()
                )
            }
        }
    }
    // test stuff
    else if let Some(command) = matches.subcommand_matches("parallel") {

        // set flag to print everything
        let print_all = command.is_present("all");

        // set whether to print files too
        let print_files = command.is_present("files");

        // get the number of processors to be used
        let nproc = get_threads(command.value_of("threads"));

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        let regex = command.value_of("excludes").map(|r| check_regex(r));

        for dir in dirs {

            let mut w = Walk::new(dir, nproc);
            if let Some(b) = min_bytes {
                w.set_threshold(b);
            }
            if !print_all {
                let depth = get_depth(command.value_of("depth"));
                w.set_depth(depth);
            } else if command.is_present("depth") {
                eprintln!(
                    "{}: flag --all is not compatible with --depth",
                    "Warning".yellow()
                );
            }
            if print_files {
                w.with_files();
            }

            if let Some(e) = regex.clone() {
                w.set_regex(e);
            }

            print_parallel(w);
        }

    }
    // find large files
    else if let Some(command) = matches.subcommand_matches("fat") {

        // set threshold
        let min_bytes = match threshold(command.value_of("threshold")) {
            Some(t) => t,
            _ => 31457280, // 30 MB
        };

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // don't print warnings
        //let silent = command.is_present("silent");

        // set whether to print files too
        let print_files = command.is_present("files");

        // set regex for exclusions
        let regex = command.value_of("excludes");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all(&dir, 0, depth, None, &None, false),
            };

            // filter by depth
            let mut v_filtered = v.filtered(Some(min_bytes), !print_files, depth);

            // display results
            v_filtered.display_tree(dir);
        }
    }
    // find large files
    else if let Some(command) = matches.subcommand_matches("directories") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set regex for exclusions
        let regex = command.value_of("excludes");

        // set whether to print files too
        let print_files = command.is_present("files");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all_fast(&dir, 0, depth),
            };

            // filter by depth
            let mut v_filtered = v.filtered(min_bytes, !print_files, depth);

            // display results
            v_filtered.display_tree(dir);
        }

    } else if let Some(command) = matches.subcommand_matches("files") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set regex for exclusions
        let regex = command.value_of("excludes");

        // set whether to print files too
        let print_files = true;

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all(&dir, 0, depth, None, &None, false),
            };

            // filter by depth
            let mut v_filtered = v.filtered(min_bytes, !print_files, depth);

            // display results
            v_filtered.display_tree(dir);
        }

    } else if let Some(command) = matches.subcommand_matches("artifacts") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set number to print out
        let num_int = if command.is_present("count") {
            Some(get_num(command.value_of("count")))
        } else {
            None
        };

        // decide whether to sort
        let should_sort = command.is_present("sort");

        // set whether to print files too
        let print_files = command.is_present("files");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let excludes = get_excludes(command.value_of("excludes"));
            let v = read_all(&dir, 0, depth, Some(&excludes), &None, true);

            let mut v_processed = if should_sort {
                v.sort(num_int, min_bytes, !print_files, depth)
            } else {
                v.filtered(min_bytes, !print_files, depth)
            };

            v_processed.display_tree(dir);
        }
    }
    // sort entities by size
    else if let Some(command) = matches.subcommand_matches("sort") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set number to print out
        let num_int = if command.is_present("count") {
            Some(get_num(command.value_of("count")))
        } else {
            None
        };

        // set whether to print files too
        let print_files = command.is_present("files");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // set regex for exclusions
            let regex = if let Some(n) = command.value_of("excludes") {
                Some(n)
            } else {
                None
            };

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all(&dir, 0, depth, None, &None, false),
            };

            // sort them
            let mut v_sorted = v.sort(num_int, min_bytes, !print_files, depth);

            // display sorted filenames
            v_sorted.display_tree(dir);
        }
    }
}
<commit_msg>fix update subcommand<commit_after>#[macro_use]
extern crate clap;

extern crate liboskar;
extern crate colored;

use colored::*;
use liboskar::prelude::*;
use clap::{App, AppSettings};
use std::env;
use std::path::PathBuf;
use std::process::Command;

#[allow(unknown_lints)]
#[allow(cyclomatic_complexity)]
fn main() {

    // command-line parser
    #[cfg(feature = "english")]
    let yaml = load_yaml!("cli/options-en.yml");
    #[cfg(feature = "francais")]
    let yaml = load_yaml!("cli/options-fr.yml");
    #[cfg(feature = "deutsch")]
    let yaml = load_yaml!("cli/options-de.yml");
    let matches = App::from_yaml(yaml)
        .version(crate_version!())
        .set_term_width(90)
        .setting(AppSettings::SubcommandRequired)
        .get_matches();

    if let Some(x) = matches.subcommand_matches("update") {

        let force = x.is_present("force");

        println!("current version: {}", crate_version!());

        let s = if force {
            "curl -LSfs https://japaric.github.io/trust/install.sh | sh -s -- --git vmchale/tin-summer --force"
        } else {
            "curl -LSfs https://japaric.github.io/trust/install.sh | sh -s -- --git vmchale/tin-summer"
        };

        let script = Command::new("bash").arg("-c").arg(s).output().expect(
            "failed to execute update script.",
        );

        let script_string = String::from_utf8(script.stderr).unwrap();

        println!("{}", script_string);

    } else if let Some(command) = matches.subcommand_matches("clean") {

        // check that we aren't in the home dir
        let home_dir_str = match env::var("HOME") {
            Ok(val) => val,
            _ => "/home".to_string(),
        };

        let home_dir = PathBuf::from(home_dir_str);

        let regex = command.value_of("excludes").map(|r| check_regex(r));

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        let force = command.is_present("force");

        for dir in dirs {
            if (dir != home_dir) && !force {
                clean_project_dirs(dir, regex.clone());
            } else {
                eprintln!(
                    "{}: not cleaning directory '{}', as it is your home directory. To clean your home directory, rerun with --force.",
                    "Warning".yellow(),
                    dir.display()
                )
            }
        }
    }
    // test stuff
    else if let Some(command) = matches.subcommand_matches("parallel") {

        // set flag to print everything
        let print_all = command.is_present("all");

        // set whether to print files too
        let print_files = command.is_present("files");

        // get the number of processors to be used
        let nproc = get_threads(command.value_of("threads"));

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        let regex = command.value_of("excludes").map(|r| check_regex(r));

        for dir in dirs {

            let mut w = Walk::new(dir, nproc);
            if let Some(b) = min_bytes {
                w.set_threshold(b);
            }
            if !print_all {
                let depth = get_depth(command.value_of("depth"));
                w.set_depth(depth);
            } else if command.is_present("depth") {
                eprintln!(
                    "{}: flag --all is not compatible with --depth",
                    "Warning".yellow()
                );
            }
            if print_files {
                w.with_files();
            }

            if let Some(e) = regex.clone() {
                w.set_regex(e);
            }

            print_parallel(w);
        }

    }
    // find large files
    else if let Some(command) = matches.subcommand_matches("fat") {

        // set threshold
        let min_bytes = match threshold(command.value_of("threshold")) {
            Some(t) => t,
            _ => 31457280, // 30 MB
        };

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // don't print warnings
        //let silent = command.is_present("silent");

        // set whether to print files too
        let print_files = command.is_present("files");

        // set regex for exclusions
        let regex = command.value_of("excludes");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all(&dir, 0, depth, None, &None, false),
            };

            // filter by depth
            let mut v_filtered = v.filtered(Some(min_bytes), !print_files, depth);

            // display results
            v_filtered.display_tree(dir);
        }
    }
    // find large files
    else if let Some(command) = matches.subcommand_matches("directories") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set regex for exclusions
        let regex = command.value_of("excludes");

        // set whether to print files too
        let print_files = command.is_present("files");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all_fast(&dir, 0, depth),
            };

            // filter by depth
            let mut v_filtered = v.filtered(min_bytes, !print_files, depth);

            // display results
            v_filtered.display_tree(dir);
        }

    } else if let Some(command) = matches.subcommand_matches("files") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set regex for exclusions
        let regex = command.value_of("excludes");

        // set whether to print files too
        let print_files = true;

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all(&dir, 0, depth, None, &None, false),
            };

            // filter by depth
            let mut v_filtered = v.filtered(min_bytes, !print_files, depth);

            // display results
            v_filtered.display_tree(dir);
        }

    } else if let Some(command) = matches.subcommand_matches("artifacts") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set number to print out
        let num_int = if command.is_present("count") {
            Some(get_num(command.value_of("count")))
        } else {
            None
        };

        // decide whether to sort
        let should_sort = command.is_present("sort");

        // set whether to print files too
        let print_files = command.is_present("files");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // get relevant filenames &c.
            let excludes = get_excludes(command.value_of("excludes"));
            let v = read_all(&dir, 0, depth, Some(&excludes), &None, true);

            let mut v_processed = if should_sort {
                v.sort(num_int, min_bytes, !print_files, depth)
            } else {
                v.filtered(min_bytes, !print_files, depth)
            };

            v_processed.display_tree(dir);
        }
    }
    // sort entities by size
    else if let Some(command) = matches.subcommand_matches("sort") {

        // set threshold
        let min_bytes = threshold(command.value_of("threshold"));

        // set depth
        let depth = if !command.is_present("all") {
            Some(get_depth(command.value_of("depth")))
        } else if command.is_present("depth") {
            eprintln!(
                "{}: flag --all is not compatible with --depth",
                "Warning".yellow()
            );
            None
        } else {
            None
        };

        // set number to print out
        let num_int = if command.is_present("count") {
            Some(get_num(command.value_of("count")))
        } else {
            None
        };

        // set whether to print files too
        let print_files = command.is_present("files");

        // set path to dirs
        let dirs = get_dirs(command.values_of("dir"));

        for dir in dirs {

            // set regex for exclusions
            let regex = if let Some(n) = command.value_of("excludes") {
                Some(n)
            } else {
                None
            };

            // get relevant filenames &c.
            let v = match regex {
                Some(r) => read_all(&dir, 0, depth, Some(&check_regex(r)), &None, false),
                _ => read_all(&dir, 0, depth, None, &None, false),
            };

            // sort them
            let mut v_sorted = v.sort(num_int, min_bytes, !print_files, depth);

            // display sorted filenames
            v_sorted.display_tree(dir);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(phase)]

extern crate html5ever;

extern crate string_cache;
#[phase(plugin)] extern crate string_cache_macros;

use std::io;
use std::default::Default;
use std::string::String;

use html5ever::sink::common::{Document, Doctype, Text, Comment, Element};
use html5ever::sink::rcdom::{RcDom, Handle};
use html5ever::{parse, one_input};

// This is not proper HTML serialization, of course.

fn walk(indent: uint, handle: Handle) {
    let node = handle.borrow();
    // FIXME: don't allocate
    print!("{:s}", String::from_char(indent, ' '));
    match node.node {
        Document
            => println!("#Document"),

        Doctype(ref name, ref public, ref system)
            => println!("<!DOCTYPE {:s} \"{:s}\" \"{:s}\">", *name, *public, *system),

        Text(ref text)
            => println!("#text: {:s}", text.escape_default()),

        Comment(ref text)
            => println!("<!-- {:s} -->", text.escape_default()),

        Element(ref name, ref attrs) => {
            assert!(name.ns == ns!(""));
            print!("<{:s}", name.local.as_slice());
            for attr in attrs.iter() {
                assert!(attr.name.ns == ns!(""));
                print!(" {:s}=\"{:s}\"", attr.name.local.as_slice(), attr.value);
            }
            println!(">");
        }
    }

    for child in node.children.iter() {
        walk(indent+4, child.clone());
    }
}

fn main() {
    let input = io::stdin().read_to_string().unwrap();
    let dom: RcDom = parse(one_input(input), Default::default());
    walk(0, dom.document);

    if !dom.errors.is_empty() {
        println!("\nParse errors:");
        for err in dom.errors.into_iter() {
            println!("    {}", err);
        }
    }
}
<commit_msg>Fix print-rcdom<commit_after>// Copyright 2014 The html5ever Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(phase)]

extern crate html5ever;

extern crate string_cache;
#[phase(plugin)] extern crate string_cache_macros;

use std::io;
use std::default::Default;
use std::string::String;

use html5ever::sink::common::{Document, Doctype, Text, Comment, Element};
use html5ever::sink::rcdom::{RcDom, Handle};
use html5ever::{parse, one_input};

// This is not proper HTML serialization, of course.

fn walk(indent: uint, handle: Handle) {
    let node = handle.borrow();
    // FIXME: don't allocate
    print!("{:s}", String::from_char(indent, ' '));
    match node.node {
        Document
            => println!("#Document"),

        Doctype(ref name, ref public, ref system)
            => println!("<!DOCTYPE {:s} \"{:s}\" \"{:s}\">", *name, *public, *system),

        Text(ref text)
            => println!("#text: {:s}", text.escape_default()),

        Comment(ref text)
            => println!("<!-- {:s} -->", text.escape_default()),

        Element(ref name, ref attrs) => {
            assert!(name.ns == ns!(html));
            print!("<{:s}", name.local.as_slice());
            for attr in attrs.iter() {
                assert!(attr.name.ns == ns!(""));
                print!(" {:s}=\"{:s}\"", attr.name.local.as_slice(), attr.value);
            }
            println!(">");
        }
    }

    for child in node.children.iter() {
        walk(indent+4, child.clone());
    }
}

fn main() {
    let input = io::stdin().read_to_string().unwrap();
    let dom: RcDom = parse(one_input(input), Default::default());
    walk(0, dom.document);

    if !dom.errors.is_empty() {
        println!("\nParse errors:");
        for err in dom.errors.into_iter() {
            println!("    {}", err);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate toml;
use std::env::args;
use std::fs::{File,metadata,copy};
use std::io::prelude::*;
use std::process::Command;
use rustc_serialize::json::Json;

fn main() {
	if !check_built(".so") {
		println!("Need to build!");
		println!("{}",cargo("build"));
	}
	bundle();
}

fn manifest() -> String {
	let package_name = toml_lookup("package.name").replace("-","_");
	return format!(
"Manifest-Version: 1.0
Bundle-SymbolicName: {}
Bundle-Name: {}
Bundle-Version: {}
Bundle-Activator: lib{}.so
Private-Library: lib{}.so
", package_name,package_name,toml_lookup("package.version"),package_name,package_name);
}

fn bundle() {
	let tmpdir : String = String::from_utf8_lossy(&Command::new("mktemp").arg("-dt").arg("rust-celix.XXXXXXXXXXXXXX").output().unwrap().stdout).into_owned().trim_right().to_string() + "/";
	copy(get_lib_name("target/release/lib",".so"),get_lib_name((tmpdir.as_str().clone().to_string()+"lib").as_str().clone(),".so"));
	let _ = Command::new("mkdir").arg("-p").arg(tmpdir.as_str().clone().to_string()+"META-INF").output().unwrap().stdout;
	File::create(tmpdir.as_str().clone().to_string()+"META-INF/MANIFEST.MF").unwrap().write_all(manifest().as_bytes()).unwrap();
	println!("{}", String::from_utf8_lossy(&Command::new("ls").current_dir(tmpdir.as_str().clone()).output().unwrap().stdout));
	println!("{}", String::from_utf8_lossy(&Command::new("zip").current_dir(tmpdir.as_str().clone()).arg(get_lib_name("",".zip")).arg(get_lib_name("lib",".so")).arg("META-INF/MANIFEST.MF").output().unwrap().stdout));
	copy(get_lib_name(tmpdir.as_str().clone(),".zip"),("deploy/bundles/".to_string()+toml_lookup("package.name").replace("-","_").as_str()).to_string()+".zip");
	let _ = Command::new("rm").arg("-rf").arg(tmpdir).output().unwrap().stdout;
}

fn check_built(ext: &str) -> bool {
	metadata(get_lib_name("target/release/lib",ext)).is_ok()
}

fn get_cargo_toml_path() -> String {
	let output = cargo("locate-project");
	let json =
		match Json::from_str(&*output) {
			Ok(j) => j,
			Err(_) => panic!("Couldn't parse the output of `cargo locate-project`")
		};
	json["root"].as_string().unwrap().to_string()
}

fn cargo(command: &str) -> String {
	if command == "build" {
		let output = Command::new("cargo")
							 .arg("build")
							 .arg("--release")
							 .output()
							 .unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	} else {
		let output = Command::new("cargo")
							 .arg(command)
							 .output()
							 .unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	}
}

fn get_lib_name(pre: &str, ext: &str) -> String {
	let base_name = toml_lookup("package.name").replace("-","_");
	((pre.to_string() + base_name.as_str()) + ext).to_string()
}

fn toml_lookup(name: &str) -> String {
	let toml_path = get_cargo_toml_path();
	let mut toml_file = match File::open(toml_path) {
			Ok(f) => f,
			Err(_) => panic!("Couldn't open Cargo.toml")
		};

	let mut contents = String::new();
	toml_file.read_to_string(&mut contents).unwrap();

	let mut parser = toml::Parser::new(&*contents);
	let toml_table = toml::Value::Table(parser.parse().unwrap());

	toml_table.lookup(name).expect("Couldn't find the index!").as_str().unwrap().to_string()
}
<commit_msg>tab fixes<commit_after>extern crate rustc_serialize;
extern crate toml;
use std::env::args;
use std::fs::{File,metadata,copy};
use std::io::prelude::*;
use std::process::Command;
use rustc_serialize::json::Json;

fn main() {
	if !check_built(".so") {
		println!("Need to build!");
		println!("{}",cargo("build"));
	}
	bundle();
}

fn manifest() -> String {
	let package_name = toml_lookup("package.name").replace("-","_");
	return format!(
"Manifest-Version: 1.0
Bundle-SymbolicName: {}
Bundle-Name: {}
Bundle-Version: {}
Bundle-Activator: lib{}.so
Private-Library: lib{}.so
", package_name,package_name,toml_lookup("package.version"),package_name,package_name);
}

fn bundle() {
	let tmpdir : String = String::from_utf8_lossy(&Command::new("mktemp").arg("-dt").arg("rust-celix.XXXXXXXXXXXXXX").output().unwrap().stdout).into_owned().trim_right().to_string() + "/";
	copy(get_lib_name("target/release/lib",".so"),get_lib_name((tmpdir.as_str().clone().to_string()+"lib").as_str().clone(),".so"));
	let _ = Command::new("mkdir").arg("-p").arg(tmpdir.as_str().clone().to_string()+"META-INF").output().unwrap().stdout;
	File::create(tmpdir.as_str().clone().to_string()+"META-INF/MANIFEST.MF").unwrap().write_all(manifest().as_bytes()).unwrap();
	println!("{}", String::from_utf8_lossy(&Command::new("ls").current_dir(tmpdir.as_str().clone()).output().unwrap().stdout));
	println!("{}", String::from_utf8_lossy(&Command::new("zip").current_dir(tmpdir.as_str().clone()).arg(get_lib_name("",".zip")).arg(get_lib_name("lib",".so")).arg("META-INF/MANIFEST.MF").output().unwrap().stdout));
	copy(get_lib_name(tmpdir.as_str().clone(),".zip"),("deploy/bundles/".to_string()+toml_lookup("package.name").replace("-","_").as_str()).to_string()+".zip");
	let _ = Command::new("rm").arg("-rf").arg(tmpdir).output().unwrap().stdout;
}

fn check_built(ext: &str) -> bool {
	metadata(get_lib_name("target/release/lib",ext)).is_ok()
}

fn get_cargo_toml_path() -> String {
	let output = cargo("locate-project");
	let json =
		match Json::from_str(&*output) {
			Ok(j) => j,
			Err(_) => panic!("Couldn't parse the output of `cargo locate-project`")
		};
	json["root"].as_string().unwrap().to_string()
}

fn cargo(command: &str) -> String {
	if command == "build" {
		let output = Command::new("cargo").arg("build").arg("--release").output().unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	} else {
		let output = Command::new("cargo").arg(command).output().unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	}
}

fn get_lib_name(pre: &str, ext: &str) -> String {
	let base_name = toml_lookup("package.name").replace("-","_");
	((pre.to_string() + base_name.as_str()) + ext).to_string()
}

fn toml_lookup(name: &str) -> String {
	let toml_path = get_cargo_toml_path();
	let mut toml_file = match File::open(toml_path) {
			Ok(f) => f,
			Err(_) => panic!("Couldn't open Cargo.toml")
		};

	let mut contents = String::new();
	toml_file.read_to_string(&mut contents).unwrap();

	let mut parser = toml::Parser::new(&*contents);
	let toml_table = toml::Value::Table(parser.parse().unwrap());

	toml_table.lookup(name).expect("Couldn't find the index!").as_str().unwrap().to_string()
}
<|endoftext|>


<commit_before>//
//    Copyright (C) 2015  Rory McCann
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate num;
extern crate regex;

use std::env;
use std::fmt;
use num::integer::{div_rem, Integer};
use regex::Regex;

struct Duration<T> {
    weeks: T,
    days: T,
    hours: T,
    minutes: T,
    seconds: T,
}

impl<T:Integer> Duration<T> {
    fn new() -> Duration<T> {
        Duration{ weeks: T::zero(), days: T::zero(), hours: T::zero(), minutes: T::zero(), seconds: T::zero() }
    }

    fn set_weeks<'a>(&'a mut self, weeks: T) -> &'a mut Duration<T> {
        self.weeks = weeks;
        self
    }
    fn set_days<'a>(&'a mut self, days: T) -> &'a mut Duration<T> {
        self.days = days;
        self
    }
    fn set_hours<'a>(&'a mut self, hours: T) -> &'a mut Duration<T> {
        self.hours = hours;
        self
    }
    fn set_minutes<'a>(&'a mut self, minutes: T) -> &'a mut Duration<T> {
        self.minutes = minutes;
        self
    }
    fn set_seconds<'a>(&'a mut self, seconds: T) -> &'a mut Duration<T> {
        self.seconds = seconds;
        self
    }

}

impl fmt::Display for Duration<u64> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut writing = false;
        if self.weeks != 0 {
            try!(write!(f, "{}wk", self.weeks));
            writing = true;
        }
        if self.days != 0 || writing {
            try!(write!(f, "{}dy", self.days));
            writing = true;
        }
        if self.hours != 0 || writing {
            try!(write!(f, "{}hr", self.hours));
            writing = true;
        }
        if self.minutes != 0 || writing {
            if writing {
                try!(write!(f, "{:02}m", self.minutes));
            } else {
                try!(write!(f, "{}m", self.minutes));
            }
            writing = true;
        }
        if self.seconds != 0 || writing {
            if writing {
                try!(write!(f, "{:02}s", self.seconds));
            } else {
                try!(write!(f, "{}s", self.seconds));
            }
            //writing = true;
        }
        Ok(())
    }
}

fn sec2duration(seconds: u64) -> Duration<u64> {
    let (minutes, seconds) = div_rem(seconds, 60);
    let (hours, minutes) = div_rem(minutes, 60);
    let (days, hours) = div_rem(hours, 24);
    let (weeks, days) = div_rem(days, 7);

    Duration{ weeks: weeks, days: days, hours: hours, minutes: minutes, seconds: seconds }
}

// Converts a textual input to
fn input2sec(input:String) -> Result<u64, String> {
    // TODO replace with regex! macro so the is guaranteed to be OK

    if let Some(cap) = Regex::new(r"^\s*(?P<sec>[0-9]+)\s*(s|sec|seconds?)?\s*$").unwrap().captures(&input) {
        // Just numbers, interpret as seconds
        let sec: u64 = try!(try!(cap.name("sec").ok_or("0")).parse().or(Err("Invalid seconds")));
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+)\s*(m|min|minutes?)\s*((?P<sec>[0-9]+)\s*(s|sec|seconds?)?)?\s*$").unwrap().captures(&input) {
        // XmYs
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+):(?P<sec>[0-9][0-9])\s*$").unwrap().captures(&input) {
        // 0:00
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ms|msec|milliseconds?)\s*$").unwrap().captures(&input) {
        // Milliseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid milliseconds")));
        let sec = ms / 1_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(μs|μsec|microsec|microseconds?)\s*$").unwrap().captures(&input) {
        // Microseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ns|nsec|nanosec|nanoseconds?)\s*$").unwrap().captures(&input) {
        // Nanoseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000_000;
        Ok(sec)
    } else {
        Err("Invalid input".to_string())
    }

}

fn prettytime(input: Vec<String>) -> Result<String, String> {
    if input.len() < 1 { return Err("No input".to_string()); }

    let input = input.join(" ");
    let seconds: u64 = try!(input2sec(input));

    let duration = sec2duration(seconds);

    Ok(format!("{}", duration))
}

fn main() {
    let args: Vec<_> = env::args().skip(1).collect();
    match prettytime(args) {
        Ok(s) => { println!("{}", s); },
        Err(s) => { println!("{}", s); }
    }
}

#[test]
fn test_print_duration() {
    assert_eq!("", format!("{}", Duration::new()));
    assert_eq!("1s", format!("{}", Duration::new().set_seconds(1)));
    assert_eq!("1m00s", format!("{}", Duration::new().set_minutes(1)));
    assert_eq!("1m03s", format!("{}", Duration::new().set_minutes(1).set_seconds(3)));
    assert_eq!("1hr00m00s", format!("{}", Duration::new().set_hours(1)));
    assert_eq!("1dy0hr00m00s", format!("{}", Duration::new().set_days(1)));
    assert_eq!("1wk0dy0hr00m00s", format!("{}", Duration::new().set_weeks(1)));
}

#[test]
fn test_parse_input() {
    // simple seconds
    assert_eq!(input2sec("10".to_string()), Ok(10));
    assert_eq!(input2sec("10s".to_string()), Ok(10));
    assert_eq!(input2sec("10 s".to_string()), Ok(10));
    assert_eq!(input2sec("10 sec".to_string()), Ok(10));
    assert_eq!(input2sec("10 foos".to_string()), Err("Invalid input".to_string()));

    // minutes
    assert_eq!(input2sec("2m".to_string()), Ok(120));
    assert_eq!(input2sec("2m 20".to_string()), Ok(140));
    assert_eq!(input2sec("2m 20s".to_string()), Ok(140));
    assert_eq!(input2sec("2m20s".to_string()), Ok(140));
    assert_eq!(input2sec("   2 m   20  s   ".to_string()), Ok(140));
    assert_eq!(input2sec("2:20".to_string()), Ok(140));
    assert_eq!(input2sec("02:20".to_string()), Ok(140));
    assert_eq!(input2sec("100:00".to_string()), Ok(6000));

    // milliseconds
    assert_eq!(input2sec("2000ms".to_string()), Ok(2));
    assert_eq!(input2sec("2ms".to_string()), Ok(0));
    assert_eq!(input2sec("2000 milliseconds".to_string()), Ok(2));
    assert_eq!(input2sec("1500ms".to_string()), Ok(1));
    assert_eq!(input2sec("1100ms".to_string()), Ok(1));
    assert_eq!(input2sec("1999ms".to_string()), Ok(1));

    // microseconds
    assert_eq!(input2sec("2000000microsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000μsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000 μs".to_string()), Ok(2));

    // nanoseconds
    assert_eq!(input2sec("2000000000ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nanosec".to_string()), Ok(2));
}

<commit_msg>fractional seconds<commit_after>//
//    Copyright (C) 2015  Rory McCann
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU Affero General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU Affero General Public License for more details.
//
//    You should have received a copy of the GNU Affero General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

extern crate num;
extern crate regex;

use std::env;
use std::fmt;
use num::integer::{div_rem, Integer};
use regex::Regex;

struct Duration<T> {
    weeks: T,
    days: T,
    hours: T,
    minutes: T,
    seconds: T,
}

impl<T:Integer> Duration<T> {
    fn new() -> Duration<T> {
        Duration{ weeks: T::zero(), days: T::zero(), hours: T::zero(), minutes: T::zero(), seconds: T::zero() }
    }

    fn set_weeks<'a>(&'a mut self, weeks: T) -> &'a mut Duration<T> {
        self.weeks = weeks;
        self
    }
    fn set_days<'a>(&'a mut self, days: T) -> &'a mut Duration<T> {
        self.days = days;
        self
    }
    fn set_hours<'a>(&'a mut self, hours: T) -> &'a mut Duration<T> {
        self.hours = hours;
        self
    }
    fn set_minutes<'a>(&'a mut self, minutes: T) -> &'a mut Duration<T> {
        self.minutes = minutes;
        self
    }
    fn set_seconds<'a>(&'a mut self, seconds: T) -> &'a mut Duration<T> {
        self.seconds = seconds;
        self
    }

}

impl fmt::Display for Duration<u64> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut writing = false;
        if self.weeks != 0 {
            try!(write!(f, "{}wk", self.weeks));
            writing = true;
        }
        if self.days != 0 || writing {
            try!(write!(f, "{}dy", self.days));
            writing = true;
        }
        if self.hours != 0 || writing {
            try!(write!(f, "{}hr", self.hours));
            writing = true;
        }
        if self.minutes != 0 || writing {
            if writing {
                try!(write!(f, "{:02}m", self.minutes));
            } else {
                try!(write!(f, "{}m", self.minutes));
            }
            writing = true;
        }
        if self.seconds != 0 || writing {
            if writing {
                try!(write!(f, "{:02}s", self.seconds));
            } else {
                try!(write!(f, "{}s", self.seconds));
            }
            //writing = true;
        }
        Ok(())
    }
}

fn sec2duration(seconds: u64) -> Duration<u64> {
    let (minutes, seconds) = div_rem(seconds, 60);
    let (hours, minutes) = div_rem(minutes, 60);
    let (days, hours) = div_rem(hours, 24);
    let (weeks, days) = div_rem(days, 7);

    Duration{ weeks: weeks, days: days, hours: hours, minutes: minutes, seconds: seconds }
}

// Converts a textual input to
fn input2sec(input:String) -> Result<u64, String> {
    // TODO replace with regex! macro so the is guaranteed to be OK

    if let Some(cap) = Regex::new(r"^\s*(?P<sec>[0-9]+)(\.[0-9]+)?\s*(s|sec|seconds?)?\s*$").unwrap().captures(&input) {
        // Just numbers, interpret as seconds. Truncate the sub-seconds
        let sec: u64 = try!(try!(cap.name("sec").ok_or("0")).parse().or(Err("Invalid seconds")));
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+)\s*(m|min|minutes?)\s*((?P<sec>[0-9]+)\s*(s|sec|seconds?)?)?\s*$").unwrap().captures(&input) {
        // XmYs
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<min>[0-9]+):(?P<sec>[0-9][0-9])\s*$").unwrap().captures(&input) {
        // 0:00
        let sec: u64 = try!(cap.name("sec").unwrap_or(&"0").parse::<u64>().or(Err("Invalid seconds")));
        let min: u64 = try!(cap.name("min").unwrap_or(&"0").parse::<u64>().or(Err("Invalid minutes")));
        Ok(min*60 + sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ms|msec|milliseconds?)\s*$").unwrap().captures(&input) {
        // Milliseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid milliseconds")));
        let sec = ms / 1_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(μs|μsec|microsec|microseconds?)\s*$").unwrap().captures(&input) {
        // Microseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000;
        Ok(sec)
    } else if let Some(cap) = Regex::new(r"^\s*(?P<ms>[0-9]+)\s*(ns|nsec|nanosec|nanoseconds?)\s*$").unwrap().captures(&input) {
        // Nanoseconds
        let ms: u64 = try!(try!(cap.name("ms").ok_or("0")).parse().or(Err("Invalid microseconds")));
        let sec = ms / 1_000_000_000;
        Ok(sec)
    } else {
        Err("Invalid input".to_string())
    }

}

fn prettytime(input: Vec<String>) -> Result<String, String> {
    if input.len() < 1 { return Err("No input".to_string()); }

    let input = input.join(" ");
    let seconds: u64 = try!(input2sec(input));

    let duration = sec2duration(seconds);

    Ok(format!("{}", duration))
}

fn main() {
    let args: Vec<_> = env::args().skip(1).collect();
    match prettytime(args) {
        Ok(s) => { println!("{}", s); },
        Err(s) => { println!("{}", s); }
    }
}

#[test]
fn test_print_duration() {
    assert_eq!("", format!("{}", Duration::new()));
    assert_eq!("1s", format!("{}", Duration::new().set_seconds(1)));
    assert_eq!("1m00s", format!("{}", Duration::new().set_minutes(1)));
    assert_eq!("1m03s", format!("{}", Duration::new().set_minutes(1).set_seconds(3)));
    assert_eq!("1hr00m00s", format!("{}", Duration::new().set_hours(1)));
    assert_eq!("1dy0hr00m00s", format!("{}", Duration::new().set_days(1)));
    assert_eq!("1wk0dy0hr00m00s", format!("{}", Duration::new().set_weeks(1)));
}

#[test]
fn test_parse_input() {
    // simple seconds
    assert_eq!(input2sec("10".to_string()), Ok(10));
    assert_eq!(input2sec("10s".to_string()), Ok(10));
    assert_eq!(input2sec("10 s".to_string()), Ok(10));
    assert_eq!(input2sec("10 sec".to_string()), Ok(10));
    assert_eq!(input2sec("10 foos".to_string()), Err("Invalid input".to_string()));

    // seconds with precision
    assert_eq!(input2sec("10.5".to_string()), Ok(10));
    assert_eq!(input2sec("10.5s".to_string()), Ok(10));
    assert_eq!(input2sec("10.2 s".to_string()), Ok(10));
    assert_eq!(input2sec("10.1 sec".to_string()), Ok(10));

    // minutes
    assert_eq!(input2sec("2m".to_string()), Ok(120));
    assert_eq!(input2sec("2m 20".to_string()), Ok(140));
    assert_eq!(input2sec("2m 20s".to_string()), Ok(140));
    assert_eq!(input2sec("2m20s".to_string()), Ok(140));
    assert_eq!(input2sec("   2 m   20  s   ".to_string()), Ok(140));
    assert_eq!(input2sec("2:20".to_string()), Ok(140));
    assert_eq!(input2sec("02:20".to_string()), Ok(140));
    assert_eq!(input2sec("100:00".to_string()), Ok(6000));

    // milliseconds
    assert_eq!(input2sec("2000ms".to_string()), Ok(2));
    assert_eq!(input2sec("2ms".to_string()), Ok(0));
    assert_eq!(input2sec("2000 milliseconds".to_string()), Ok(2));
    assert_eq!(input2sec("1500ms".to_string()), Ok(1));
    assert_eq!(input2sec("1100ms".to_string()), Ok(1));
    assert_eq!(input2sec("1999ms".to_string()), Ok(1));

    // microseconds
    assert_eq!(input2sec("2000000microsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000μsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000 μs".to_string()), Ok(2));

    // nanoseconds
    assert_eq!(input2sec("2000000000ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 ns".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nsec".to_string()), Ok(2));
    assert_eq!(input2sec("2000000000 nanosec".to_string()), Ok(2));
}

<|endoftext|>


<commit_before>extern crate rudit;
extern crate termion;

use std::io::{Write, stdout};
use termion::raw::IntoRawMode;
use termion::event::Key;
use termion::input::TermRead;
use termion::cursor::Goto;
use rudit::gapbuffer::GapBuffer;

fn main() {
    let mut buffer = GapBuffer::new(30);
    let mut stdout = stdout().into_raw_mode().unwrap();
    let mut index = 0;
    let mut cx: u16 = 3;
    let mut cy: u16 = 1;
    // buffer.insert(0, 'a');
    // buffer.insert(1, 'b');
    // buffer.insert(2, '\n');
    // buffer.insert(3, 'c');
    // index = 3;
    // cy = 2;
    write!(stdout,
           "{}{}",
           termion::clear::All,
           termion::cursor::Goto(cx, cy))
            .unwrap();
    stdout.flush().unwrap();
    'main: loop {

        write!(stdout, "{}", termion::clear::CurrentLine).unwrap();

        draw_lines(&mut stdout, &buffer.buffer);
        draw_cursor(&mut stdout, cx, cy);

        stdout.flush().unwrap();

        for c in std::io::stdin().keys() {
            match c.unwrap() {
                Key::Char('\n') => {
                    buffer.insert(index, '\n');
                    cx = 3;
                    cy += 1;
                    index += 1;
                }
                Key::Char(c) => {
                    buffer.insert(index, c);
                    index += 1;
                    cx += 1;
                }
                Key::Up => {
                    let mut new_line_pos = index;
                    let mut count_previous_line = 0;
                    for i in (0..index).rev() {
                        new_line_pos -= 1;
                        if i == 0 || buffer.buffer[i] == '\n' {
                            break;
                        }
                    }
                    if new_line_pos == 0 {
                        count_previous_line = 1;
                    }
                    for i in (0..new_line_pos).rev() {
                        count_previous_line += 1;
                        if i == 0 || buffer.buffer[i] == '\n' {
                            count_previous_line += 1;
                            break;
                        }
                    }
                    index = (cy as usize) - 1 +
                            std::cmp::min((cx as usize) - 3, count_previous_line - 1);
                    index -= 1;
                    if cx - 3 > count_previous_line as u16 {
                        cx -= count_previous_line as u16 + 3;

                    }
                    cy -= 1;
                }
                Key::Left => {
                    if cx > 3 {
                        cx -= 1;
                        index -= 1;
                    }
                }
                Key::Right => {
                    if buffer.buffer[index] != '\0' ||
                       buffer.buffer[buffer.buffer.len() - index + buffer.gap_start - 1] != '\0' {
                        cx += 1;
                        index += 1;
                    }
                }
                Key::Esc => break,
                _ => (),
            }
            continue 'main;
        }
        write!(stdout, "{}", termion::clear::All).unwrap();
        stdout.flush().unwrap();
        break;
    }
}

fn draw_lines(stdout: &mut termion::raw::RawTerminal<std::io::Stdout>, buffer: &Vec<char>) {
    let s: String = buffer.iter().collect();
    for (index, i) in s.split('\n').enumerate() {
        write!(stdout,
               "{}{}{}{}",
               Goto(0, (index + 1) as u16),
               index + 1,
               Goto(3, (index + 1) as u16),
               i)
                .unwrap();
    }
}

fn draw_cursor(stdout: &mut termion::raw::RawTerminal<std::io::Stdout>, cx: u16, cy: u16) {
    write!(stdout, "{}", termion::cursor::Goto(cx, cy)).unwrap();
}
<commit_msg>down cursor finally working<commit_after>extern crate rudit;
extern crate termion;

use std::io::{Write, stdout};
use termion::raw::IntoRawMode;
use termion::event::Key;
use termion::input::TermRead;
use termion::cursor::Goto;
use rudit::gapbuffer::GapBuffer;

fn main() {
    let mut buffer = GapBuffer::new(30);
    let mut stdout = stdout().into_raw_mode().unwrap();
    let mut index = 0;
    let mut cx: u16 = 3;
    let mut cy: u16 = 1;
    // buffer.insert(0, 'a');
    // buffer.insert(1, 'b');
    // buffer.insert(2, '\n');
    // buffer.insert(3, 'c');
    // index = 3;
    // cy = 2;
    write!(stdout,
           "{}{}",
           termion::clear::All,
           termion::cursor::Goto(cx, cy))
        .unwrap();
    stdout.flush().unwrap();
    'main: loop {

        write!(stdout, "{}", termion::clear::All).unwrap();

        draw_lines(&mut stdout, &buffer.buffer);
        draw_cursor(&mut stdout, cx, cy);

        stdout.flush().unwrap();

        for c in std::io::stdin().keys() {
            match c.unwrap() {
                Key::Char('\n') => {
                    buffer.insert(index, '\n');
                    cx = 3;
                    cy += 1;
                    index += 1;
                }
                Key::Char(c) => {
                    buffer.insert(index, c);
                    index += 1;
                    cx += 1;
                }
                Key::Up => {
                    let mut new_line_pos = 0;
                    for i in (0..index).rev() {
                        if buffer.buffer[i] == '\n' {
                            new_line_pos = i;
                            break;
                        }
                    }
                    let mut prev_line = new_line_pos;
                    for i in (0..new_line_pos).rev() {
                        if buffer.buffer[i] == '\n' {
                            break;
                        }
                        prev_line -= 1;
                    }
                    let mut count_previous_line = 0;
                    if new_line_pos == 0 {
                        new_line_pos += 1;
                        count_previous_line = 1;
                    } else {
                        count_previous_line += 1;
                    }
                    for i in (0..new_line_pos).rev() {
                        count_previous_line += 1;
                        if buffer.buffer[i] == '\n' {
                            count_previous_line -= 1;
                            break;
                        }

                    }

                    index = prev_line + std::cmp::min((cx as usize - 3), count_previous_line - 1);
                    if cx - 3 >= count_previous_line as u16 {
                        cx = count_previous_line as u16 + 2;
                    }
                    // println!("");
                    // println!("size {} prevline {}", count_previous_line, prev_line);
                    cy -= 1;
                }
                Key::Left => {
                    if cx > 3 {
                        cx -= 1;
                        index -= 1;
                    }
                }
                Key::Right => {
                    if buffer.buffer[index] != '\0' ||
                       buffer.buffer[buffer.buffer.len() - index + buffer.gap_start - 1] != '\0' {
                        cx += 1;
                        index += 1;
                    }
                }
                Key::Esc => break,
                _ => (),
            }
            continue 'main;
        }
        write!(stdout, "{}", termion::clear::All).unwrap();
        stdout.flush().unwrap();
        break;
    }
}

fn draw_lines(stdout: &mut termion::raw::RawTerminal<std::io::Stdout>, buffer: &Vec<char>) {
    let s: String = buffer.iter().collect();
    for (index, i) in s.split('\n').enumerate() {
        write!(stdout,
               "{}{}{}{}",
               Goto(0, (index + 1) as u16),
               index + 1,
               Goto(3, (index + 1) as u16),
               i)
            .unwrap();
    }
}

fn draw_cursor(stdout: &mut termion::raw::RawTerminal<std::io::Stdout>, cx: u16, cy: u16) {
    write!(stdout, "{}", termion::cursor::Goto(cx, cy)).unwrap();
}
<|endoftext|>


<commit_before>/* Command Line Argument Parser */
#[macro_use]
extern crate clap;
use clap::AppSettings::SubcommandRequiredElseHelp;

/* For serialization/deserialization of the timesheet */
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

/* For parsing time strings */
#[macro_use]
extern crate nom;

/* For time handling */
extern crate chrono;

/* To open link to report in browser */
extern crate url_open;
extern crate url;

/* For process termination */
use std::{process, env};

use util::*;

use timesheet::timesheet::Timesheet;

mod util;
mod timesheet;
mod config;

fn main() {
    /* Handle command line arguments with clap */
    let arguments = clap_app!(trk =>
        (setting: SubcommandRequiredElseHelp)
        (version: "0.1")
        (author: "Rafael B. <mediumendian@gmail.com>")
        (about: "Create timesheets from git history and meta info")
            /* (@arg CONFIG: -c --config +takes_value "[UNUSED] Sets a custom config file") */
            /* (@arg debug: -d ... "[UNUSED] Sets the level of debugging information") */

            (@subcommand init =>
                (about: "Initialise trk in this directory and give name (should match git user name)")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
                (@arg name: "Optional: user name. Default is git user name if set, empty otherwise.")
            )
            (@subcommand begin =>
                (about: "Begin session")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
                (@arg ago: "Optional: begin in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand end =>
                (about: "End session")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
                (@arg ago: "Optional: end in the past, specify how long ago.
                    Time must be after the last event though.")
                )
            (@subcommand pause =>
                (about: "Pause current session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg note_text: "Optional: Pause note")
                (@arg ago: "Optional: pause in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand resume =>
                (about: "Resume currently paused session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg ago: "Optional: resume in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand note =>
                (about: "Add a note about current work or pause")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg note_text: +required "Note text")
                (@arg ago: "Optional: Add a note in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand commit =>
                (about: "Add a commit to the event list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg hash: +required "Commit hash id")
            )
            (@subcommand branch =>
                (about: "Add a branch to the session's branch list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg name: +required "branch name")
            )
            (@subcommand set_show_commits =>
                    (about: "Show information about git commits/branches in the report")
                    (version: "0.1")
                    (author: "mediumendian@gmail.com")
                    (@arg on_off: +required "on or off")
            )
            (@subcommand set_repo_url =>
                    (about: "Set git repo url to use for turning commit hashes to links")
                    (version: "0.1")
                    (author: "mediumendian@gmail.com")
                    (@arg url: +required "url to repository")
            )
            (@subcommand status =>
                (about: "Prints the current WIP for session or sheet")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg sheet_or_session: +required "session or sheet")
            )
            (@subcommand report =>
                (about:
"Generate html report for current session or entire sheet and save it to {timesheet|session}.html")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg sheet_or_session: +required "session or sheet")
                (@arg ago: "How long the record should go back")
            )
            (@subcommand clear =>
                (about: "Temporary: clears all sessions and updates all timestamps")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
            )
       )
            .get_matches();

    /* Set current dir to the next upper directory containing a .trk directory */
    let mut p = env::current_dir().unwrap();
    loop {
        p.push(".trk");
        if p.exists() {
            p.pop();
            env::set_current_dir(&p).is_ok();
            break;
        } else {
            p.pop();
            if !p.pop() {
                println!("Fatal: not a .trk directory (or subdirectory of one).");
                process::exit(0);
            }
        }
    }

    /* Gets a value for config if supplied by user, or defaults to "default.conf" */
    /* let config = matches.value_of("config").unwrap_or("default.conf");
    println!("[UNUSED] Value for config: {}", config); */

    let sheet = Timesheet::load_from_file();

    /* Special case for init because t_sheet can and should be None before initialisation */
    if let Some(command) = arguments.subcommand_matches("init") {
        match sheet {
            Some(..) => println!("Already initialised."),
            None => {
                match Timesheet::init(command.value_of("name")) {
                    Some(..) => println!("Init successful."),
                    None => println!("Could not initialize."),
                }
            }
        }
        return;
    }

    /* Special case for clear because t_sheet can be None when clearing (corrupt file) */
    if let Some(command) = arguments.subcommand_matches("clear") {
        match sheet {
            Some(..) => {
                println!("Clearing timesheet.");
                Timesheet::clear();
            }
            None => {
                match Timesheet::init(command.value_of("name")) {
                    Some(..) => println!("Reinitialised timesheet."),
                    None => println!("Could not initialize."),
                }
            }
        }
        return;
    }

    /* Ignore commit or branch on uninitialised trk,
     * which occur when post-commit/post-checkout hooks run
     */
    if arguments.subcommand_matches("commit").is_some() ||
       arguments.subcommand_matches("branch").is_some() {
        match sheet {
            Some(..) => {}
            None => process::exit(0),
        }
    }

    /* Unwrap the timesheet and continue only if timesheet file exists */
    let mut sheet = match sheet {
        Some(file) => file,
        None => {
            println!("No timesheet file! You might have to init first.");
            return;
        }
    };

    match arguments.subcommand() {
        ("begin", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            sheet.new_session(timestamp);
        }
        ("end", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            sheet.end_session(timestamp);
        }
        ("pause", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            let note_text = arg.value_of("note_text");
            match note_text {
                Some(note_text) => sheet.pause(timestamp, Some(note_text.to_string())),
                None => sheet.pause(timestamp, None),
            }
        }

        ("resume", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            sheet.resume(timestamp);
        }
        ("note", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            let note_text = arg.value_of("note_text").unwrap();
            sheet.note(timestamp, note_text.to_string());
        }
        ("commit", Some(arg)) => {
            let commit_hash = arg.value_of("hash").unwrap();
            sheet.add_commit(commit_hash.to_string());
        }
        ("branch", Some(arg)) => {
            let branch_name = arg.value_of("name").unwrap();
            sheet.add_branch(branch_name.to_string());
        }
        ("status", Some(arg)) => {
            match arg.value_of("sheet_or_session") {
                Some("session") => println!("{}", sheet.last_session_status()),
                Some("sheet") => println!("{}", sheet.timesheet_status()),
                Some(text) => {
                    println!("What do you mean by {}? Should be either 'sheet' or 'session'.",
                             text)
                }
                _ => unreachable!(),
            }
        }
        ("report", Some(arg)) => {
            match arg.value_of("sheet_or_session") {
                Some("session") => sheet.report_last_session(),
                Some("sheet") => {
                    let timestamp: Option<u64> =
                        parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                        .map(|ago| get_seconds() - ago);
                    sheet.report_sheet(timestamp);
                }
                Some(text) => {
                    println!("What do you mean by {}? Should be either 'sheet' or 'session'.",
                             text)
                }
                _ => unreachable!(),
            }
        }
        ("set_show_commits", Some(arg)) => {
            match arg.value_of("on_off") {
                Some("on") => sheet.show_commits(true),
                Some("off") => sheet.show_commits(false),
                Some(text) => {
                    println!("What do you mean by {}? Should be either 'on' or 'off'.",
                             text)
                }
                _ => unreachable!(),
            }
        }
        ("set_repo_url", Some(arg)) => {
            match arg.value_of("url") {
                Some(repo_url) => sheet.set_repo_url(repo_url.to_string()),
                None => println!("Could not parse argument of trk set repo_url."),
            }
        }
        _ => unreachable!(),
    }
    sheet.write_files();
}
<commit_msg>bump version number<commit_after>/* Command Line Argument Parser */
#[macro_use]
extern crate clap;
use clap::AppSettings::SubcommandRequiredElseHelp;

/* For serialization/deserialization of the timesheet */
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

/* For parsing time strings */
#[macro_use]
extern crate nom;

/* For time handling */
extern crate chrono;

/* To open link to report in browser */
extern crate url_open;
extern crate url;

/* For process termination */
use std::{process, env};

use util::*;

use timesheet::timesheet::Timesheet;

mod util;
mod timesheet;
mod config;

fn main() {
    /* Handle command line arguments with clap */
    let arguments = clap_app!(trk =>
        (setting: SubcommandRequiredElseHelp)
        (version: "0.9")
        (author: "Rafael B. <mediumendian@gmail.com>")
        (about: "Create timesheets from git history and meta info")
            /* (@arg CONFIG: -c --config +takes_value "[UNUSED] Sets a custom config file") */
            /* (@arg debug: -d ... "[UNUSED] Sets the level of debugging information") */

            (@subcommand init =>
                (about: "Initialise trk in this directory and give name (should match git user name)")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
                (@arg name: "Optional: user name. Default is git user name if set, empty otherwise.")
            )
            (@subcommand begin =>
                (about: "Begin session")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
                (@arg ago: "Optional: begin in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand end =>
                (about: "End session")
                (version: "0.1")
                (author:  "Rafael B. <mediumendian@gmail.com>")
                (@arg ago: "Optional: end in the past, specify how long ago.
                    Time must be after the last event though.")
                )
            (@subcommand pause =>
                (about: "Pause current session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg note_text: "Optional: Pause note")
                (@arg ago: "Optional: pause in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand resume =>
                (about: "Resume currently paused session")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg ago: "Optional: resume in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand note =>
                (about: "Add a note about current work or pause")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg note_text: +required "Note text")
                (@arg ago: "Optional: Add a note in the past, specify how long ago.
                    Time must be after the last event though.")
            )
            (@subcommand commit =>
                (about: "Add a commit to the event list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg hash: +required "Commit hash id")
            )
            (@subcommand branch =>
                (about: "Add a branch to the session's branch list")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg name: +required "branch name")
            )
            (@subcommand set_show_commits =>
                    (about: "Show information about git commits/branches in the report")
                    (version: "0.1")
                    (author: "mediumendian@gmail.com")
                    (@arg on_off: +required "on or off")
            )
            (@subcommand set_repo_url =>
                    (about: "Set git repo url to use for turning commit hashes to links")
                    (version: "0.1")
                    (author: "mediumendian@gmail.com")
                    (@arg url: +required "url to repository")
            )
            (@subcommand status =>
                (about: "Prints the current WIP for session or sheet")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg sheet_or_session: +required "session or sheet")
            )
            (@subcommand report =>
                (about:
"Generate html report for current session or entire sheet and save it to {timesheet|session}.html")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
                (@arg sheet_or_session: +required "session or sheet")
                (@arg ago: "How long the record should go back")
            )
            (@subcommand clear =>
                (about: "Temporary: clears all sessions and updates all timestamps")
                (version: "0.1")
                (author: "mediumendian@gmail.com")
            )
       )
            .get_matches();

    /* Set current dir to the next upper directory containing a .trk directory */
    let mut p = env::current_dir().unwrap();
    loop {
        p.push(".trk");
        if p.exists() {
            p.pop();
            env::set_current_dir(&p).is_ok();
            break;
        } else {
            p.pop();
            if !p.pop() {
                println!("Fatal: not a .trk directory (or subdirectory of one).");
                process::exit(0);
            }
        }
    }

    /* Gets a value for config if supplied by user, or defaults to "default.conf" */
    /* let config = matches.value_of("config").unwrap_or("default.conf");
    println!("[UNUSED] Value for config: {}", config); */

    let sheet = Timesheet::load_from_file();

    /* Special case for init because t_sheet can and should be None before initialisation */
    if let Some(command) = arguments.subcommand_matches("init") {
        match sheet {
            Some(..) => println!("Already initialised."),
            None => {
                match Timesheet::init(command.value_of("name")) {
                    Some(..) => println!("Init successful."),
                    None => println!("Could not initialize."),
                }
            }
        }
        return;
    }

    /* Special case for clear because t_sheet can be None when clearing (corrupt file) */
    if let Some(command) = arguments.subcommand_matches("clear") {
        match sheet {
            Some(..) => {
                println!("Clearing timesheet.");
                Timesheet::clear();
            }
            None => {
                match Timesheet::init(command.value_of("name")) {
                    Some(..) => println!("Reinitialised timesheet."),
                    None => println!("Could not initialize."),
                }
            }
        }
        return;
    }

    /* Ignore commit or branch on uninitialised trk,
     * which occur when post-commit/post-checkout hooks run
     */
    if arguments.subcommand_matches("commit").is_some() ||
       arguments.subcommand_matches("branch").is_some() {
        match sheet {
            Some(..) => {}
            None => process::exit(0),
        }
    }

    /* Unwrap the timesheet and continue only if timesheet file exists */
    let mut sheet = match sheet {
        Some(file) => file,
        None => {
            println!("No timesheet file! You might have to init first.");
            return;
        }
    };

    match arguments.subcommand() {
        ("begin", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            sheet.new_session(timestamp);
        }
        ("end", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            sheet.end_session(timestamp);
        }
        ("pause", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            let note_text = arg.value_of("note_text");
            match note_text {
                Some(note_text) => sheet.pause(timestamp, Some(note_text.to_string())),
                None => sheet.pause(timestamp, None),
            }
        }

        ("resume", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            sheet.resume(timestamp);
        }
        ("note", Some(arg)) => {
            let timestamp: Option<u64> = parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                .map(|ago| get_seconds() - ago);
            let note_text = arg.value_of("note_text").unwrap();
            sheet.note(timestamp, note_text.to_string());
        }
        ("commit", Some(arg)) => {
            let commit_hash = arg.value_of("hash").unwrap();
            sheet.add_commit(commit_hash.to_string());
        }
        ("branch", Some(arg)) => {
            let branch_name = arg.value_of("name").unwrap();
            sheet.add_branch(branch_name.to_string());
        }
        ("status", Some(arg)) => {
            match arg.value_of("sheet_or_session") {
                Some("session") => println!("{}", sheet.last_session_status()),
                Some("sheet") => println!("{}", sheet.timesheet_status()),
                Some(text) => {
                    println!("What do you mean by {}? Should be either 'sheet' or 'session'.",
                             text)
                }
                _ => unreachable!(),
            }
        }
        ("report", Some(arg)) => {
            match arg.value_of("sheet_or_session") {
                Some("session") => sheet.report_last_session(),
                Some("sheet") => {
                    let timestamp: Option<u64> =
                        parse_hhmm_to_seconds(arg.value_of("ago").unwrap_or(""))
                        .map(|ago| get_seconds() - ago);
                    sheet.report_sheet(timestamp);
                }
                Some(text) => {
                    println!("What do you mean by {}? Should be either 'sheet' or 'session'.",
                             text)
                }
                _ => unreachable!(),
            }
        }
        ("set_show_commits", Some(arg)) => {
            match arg.value_of("on_off") {
                Some("on") => sheet.show_commits(true),
                Some("off") => sheet.show_commits(false),
                Some(text) => {
                    println!("What do you mean by {}? Should be either 'on' or 'off'.",
                             text)
                }
                _ => unreachable!(),
            }
        }
        ("set_repo_url", Some(arg)) => {
            match arg.value_of("url") {
                Some(repo_url) => sheet.set_repo_url(repo_url.to_string()),
                None => println!("Could not parse argument of trk set repo_url."),
            }
        }
        _ => unreachable!(),
    }
    sheet.write_files();
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests;

mod game;
mod ai;
mod tree_expand_ai;
mod ui;
mod game_view;
mod constants;
mod helpers;
mod thread_synchronisation;

// Command line argument parser
extern crate clap;
use clap::{App, Arg, SubCommand};

// UI dependencies
extern crate kiss3d;
extern crate glfw;
extern crate nalgebra as na;

extern crate rand;

use ai::StatelessAI;
use constants::LINES; //, PARALLELOGRAMS, PLUSSES};
use std::rc::Rc;

fn main() {
    let matches = parse_command_line_input();

    fn batch(arguments: &clap::ArgMatches) -> Result<(), String> {
        let ai1_params = arguments.values_of("ai1").map(ai_parser).unwrap()?;
        let ai2_params = arguments.values_of("ai2").map(ai_parser).unwrap()?;
        let count: usize = arguments
            .value_of("count")
            .unwrap()
            .parse::<usize>()
            .unwrap();

        let structure = Rc::new(game::Structure::new(&LINES));

        let mut ai1 = ai::AIBox::new(structure.clone(), ai1_params);
        let mut ai2 = ai::AIBox::new(structure.clone(), ai2_params);

        for i in 1..count+1 {
            println!("Match {} results in {:?}",
                     i,
                     ai::run_match(&structure, &mut ai1, &mut ai2).victory_state);
        }
        Ok(())
    }

    if let Some(batch_matches) = matches.subcommand_matches("batch") {

        batch(batch_matches).unwrap();

        return;
    }

    let ai_parameter_result = matches
        .values_of("opponent")
        .map(ai_parser)
        .unwrap_or(Ok(ai::Constructor::MonteCarlo { endurance: 1000 }));

    let ai_parameter = match ai_parameter_result {
        Ok(param) => param,
        Err(error) => {
            println!("Faulty AI specified: {}", error);
            return;
        }
    };

    let structure = Rc::new(game::Structure::new(&LINES));
    let player_2_ai = ai::AIBox::new(structure.clone(), ai_parameter);

    interactive(structure, player_2_ai);
}

fn parse_command_line_input<'clap>() -> clap::ArgMatches<'clap> {
    let validate_integer = |s: String| match s.parse::<u32>() {
        Ok(_) => Ok(()),
        Err(_) => Err("Needs to be an integer.".to_owned()),
    };

    let batch_run = SubCommand::with_name("batch")
        .about("Executes many AI matches at once.")
        .arg(Arg::with_name("count")
                 .short("n")
                 .long("count")
                 .help("How many matches should be played")
                 .takes_value(true)
                 .default_value("1")
                 .validator(validate_integer))
        .arg(Arg::with_name("ai1")
                 .short("p")
                 .required(true)
                 .help("Specify first AI.")
                 .min_values(1))
        .arg(Arg::with_name("ai2")
                 .short("q")
                 .required(true)
                 .help("Specify second AI.")
                 .min_values(1));

    let opponent = Arg::with_name("opponent")
        .short("p")
        .long("player")
        .help("Specify which AI you want to play against.")
        .min_values(1);

    App::new("Sogo - Play four in a row.")
        .version("0.0.1")
        .author("Rolf Sievers <rolf.sievers@posteo.de>")
        .about("UI and AIs for Sogo.")
        .subcommand(batch_run)
        .arg(opponent)
        .get_matches()
}

fn ai_parser(mut values: clap::Values) -> Result<ai::Constructor, String> {
    let ai_name: &str = values.next().unwrap();
    match ai_name {
        "random" => Ok(ai::Constructor::Random),
        "mc" => {
            let endurance = values
                .next()
                .unwrap_or("10000")
                .parse::<usize>()
                .map_err(|_| "The endurance needs to be a number.")?;
            Ok(ai::Constructor::MonteCarlo { endurance })
        }
        "tree" => {
            let depth = values
                .next()
                .unwrap_or("2")
                .parse::<u8>()
                .map_err(|_| "The depth needs to be a number.")?;
            Ok(ai::Constructor::Tree { depth })
        }
        _ => Err("AI not recognized.")?,
    }
}

fn interactive(structure: Rc<game::Structure>, mut p2: ai::AIBox) {
    let ui_connector = ui::UiConnector::new();

    // let mut p2 = ai::tree::TreeJudgementAI::new(structure.clone(), 2);
    // let mut p2 = ai::mc::MonteCarloAI::new(structure.clone(), 10000);
    // let mut p2 = ai::random::RandomSogoAI::new();

    // Run a game, this should look synchronous.
    let mut state = game::State::new();

    loop {
        user_turn(&ui_connector, &mut state, &structure);

        // Check for victory.
        if !state.victory_state.active() {
            println!("The Human has won the game.");
            ui_connector.wait_for_halt();
            break;
        }

        ai_turn(&ui_connector, &mut p2, &mut state, &structure);

        // Check for victory.
        if !state.victory_state.active() {
            println!("The AI has won the game.");
            ui_connector.wait_for_halt();
            break;
        }
    }
}

fn user_turn(ui_connector: &ui::UiConnector,
             state: &mut game::State,
             structure: &game::Structure) {
    // Wait for the player to make the first action
    let action = ui_connector.wait_for_action().unwrap();

    let color = state.current_color;
    state.execute(&structure, action);
    ui_connector.confirmed_action(action, color).unwrap();
}

fn ai_turn<A: StatelessAI>(ui_connector: &ui::UiConnector,
                           ai: &mut A,
                           state: &mut game::State,
                           structure: &game::Structure) {
    // Let the AI take one action
    let action = ai.action(&state);

    let color = state.current_color;
    state.execute(&structure, action);
    ui_connector.confirmed_action(action, color).unwrap();
}
<commit_msg>Remove reference to old draft I never commited.<commit_after>#[cfg(test)]
mod tests;

mod game;
mod ai;
mod ui;
mod game_view;
mod constants;
mod helpers;
mod thread_synchronisation;

// Command line argument parser
extern crate clap;
use clap::{App, Arg, SubCommand};

// UI dependencies
extern crate kiss3d;
extern crate glfw;
extern crate nalgebra as na;

extern crate rand;

use ai::StatelessAI;
use constants::LINES; //, PARALLELOGRAMS, PLUSSES};
use std::rc::Rc;

fn main() {
    let matches = parse_command_line_input();

    fn batch(arguments: &clap::ArgMatches) -> Result<(), String> {
        let ai1_params = arguments.values_of("ai1").map(ai_parser).unwrap()?;
        let ai2_params = arguments.values_of("ai2").map(ai_parser).unwrap()?;
        let count: usize = arguments
            .value_of("count")
            .unwrap()
            .parse::<usize>()
            .unwrap();

        let structure = Rc::new(game::Structure::new(&LINES));

        let mut ai1 = ai::AIBox::new(structure.clone(), ai1_params);
        let mut ai2 = ai::AIBox::new(structure.clone(), ai2_params);

        for i in 1..count+1 {
            println!("Match {} results in {:?}",
                     i,
                     ai::run_match(&structure, &mut ai1, &mut ai2).victory_state);
        }
        Ok(())
    }

    if let Some(batch_matches) = matches.subcommand_matches("batch") {

        batch(batch_matches).unwrap();

        return;
    }

    let ai_parameter_result = matches
        .values_of("opponent")
        .map(ai_parser)
        .unwrap_or(Ok(ai::Constructor::MonteCarlo { endurance: 1000 }));

    let ai_parameter = match ai_parameter_result {
        Ok(param) => param,
        Err(error) => {
            println!("Faulty AI specified: {}", error);
            return;
        }
    };

    let structure = Rc::new(game::Structure::new(&LINES));
    let player_2_ai = ai::AIBox::new(structure.clone(), ai_parameter);

    interactive(structure, player_2_ai);
}

fn parse_command_line_input<'clap>() -> clap::ArgMatches<'clap> {
    let validate_integer = |s: String| match s.parse::<u32>() {
        Ok(_) => Ok(()),
        Err(_) => Err("Needs to be an integer.".to_owned()),
    };

    let batch_run = SubCommand::with_name("batch")
        .about("Executes many AI matches at once.")
        .arg(Arg::with_name("count")
                 .short("n")
                 .long("count")
                 .help("How many matches should be played")
                 .takes_value(true)
                 .default_value("1")
                 .validator(validate_integer))
        .arg(Arg::with_name("ai1")
                 .short("p")
                 .required(true)
                 .help("Specify first AI.")
                 .min_values(1))
        .arg(Arg::with_name("ai2")
                 .short("q")
                 .required(true)
                 .help("Specify second AI.")
                 .min_values(1));

    let opponent = Arg::with_name("opponent")
        .short("p")
        .long("player")
        .help("Specify which AI you want to play against.")
        .min_values(1);

    App::new("Sogo - Play four in a row.")
        .version("0.0.1")
        .author("Rolf Sievers <rolf.sievers@posteo.de>")
        .about("UI and AIs for Sogo.")
        .subcommand(batch_run)
        .arg(opponent)
        .get_matches()
}

fn ai_parser(mut values: clap::Values) -> Result<ai::Constructor, String> {
    let ai_name: &str = values.next().unwrap();
    match ai_name {
        "random" => Ok(ai::Constructor::Random),
        "mc" => {
            let endurance = values
                .next()
                .unwrap_or("10000")
                .parse::<usize>()
                .map_err(|_| "The endurance needs to be a number.")?;
            Ok(ai::Constructor::MonteCarlo { endurance })
        }
        "tree" => {
            let depth = values
                .next()
                .unwrap_or("2")
                .parse::<u8>()
                .map_err(|_| "The depth needs to be a number.")?;
            Ok(ai::Constructor::Tree { depth })
        }
        _ => Err("AI not recognized.")?,
    }
}

fn interactive(structure: Rc<game::Structure>, mut p2: ai::AIBox) {
    let ui_connector = ui::UiConnector::new();

    // let mut p2 = ai::tree::TreeJudgementAI::new(structure.clone(), 2);
    // let mut p2 = ai::mc::MonteCarloAI::new(structure.clone(), 10000);
    // let mut p2 = ai::random::RandomSogoAI::new();

    // Run a game, this should look synchronous.
    let mut state = game::State::new();

    loop {
        user_turn(&ui_connector, &mut state, &structure);

        // Check for victory.
        if !state.victory_state.active() {
            println!("The Human has won the game.");
            ui_connector.wait_for_halt();
            break;
        }

        ai_turn(&ui_connector, &mut p2, &mut state, &structure);

        // Check for victory.
        if !state.victory_state.active() {
            println!("The AI has won the game.");
            ui_connector.wait_for_halt();
            break;
        }
    }
}

fn user_turn(ui_connector: &ui::UiConnector,
             state: &mut game::State,
             structure: &game::Structure) {
    // Wait for the player to make the first action
    let action = ui_connector.wait_for_action().unwrap();

    let color = state.current_color;
    state.execute(&structure, action);
    ui_connector.confirmed_action(action, color).unwrap();
}

fn ai_turn<A: StatelessAI>(ui_connector: &ui::UiConnector,
                           ai: &mut A,
                           state: &mut game::State,
                           structure: &game::Structure) {
    // Let the AI take one action
    let action = ai.action(&state);

    let color = state.current_color;
    state.execute(&structure, action);
    ui_connector.confirmed_action(action, color).unwrap();
}
<|endoftext|>


<commit_before>#![feature(tuple_indexing)]
#![feature(macro_rules)]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

use memory::Memory;
use memory::GameboyMemory;
use cpu::Cpu;
use std::io::stdio::stdin;

mod memory;
mod ops;
mod extensions;
mod cpu;

fn main() {
    let mut memory = box GameboyMemory::new(0x10000);
    let mut cpu = Cpu::new(memory);

    let mut count: uint = 0;
    let mut handle = stdin();
    loop {
        debug!("cycle: {}", count);
        /*
        if count % 10 == 0 {
            let val = handle.read_char();
        }
       */
        let clock_cycle = cpu.tick();
        count += 1;
    }

}
<commit_msg>Remove feature gate<commit_after>#![feature(macro_rules)]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

use memory::Memory;
use memory::GameboyMemory;
use cpu::Cpu;
use std::io::stdio::stdin;

mod memory;
mod ops;
mod extensions;
mod cpu;

fn main() {
    let mut memory = box GameboyMemory::new(0x10000);
    let mut cpu = Cpu::new(memory);

    let mut count: uint = 0;
    let mut handle = stdin();
    loop {
        debug!("cycle: {}", count);
        /*
        if count % 10 == 0 {
            let val = handle.read_char();
        }
       */
        let clock_cycle = cpu.tick();
        count += 1;
    }

}
<|endoftext|>


<commit_before>use std::fmt;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
enum Atom {
  Number(f64),
    Symbol(String)
}

enum ParseAtomError {
    IncorrectSymbolName
}

impl fmt::Display for Atom {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      &Atom::Number(n) => {
        write!(f, "{}", n)
      },
      &Atom::Symbol(ref name) => {
        write!(f, "'{}'", name)
      }
    }
  }
}

impl FromStr for Atom {
  type Err = ParseAtomError;

  fn from_str(s: &str) -> Result<Atom, ParseAtomError> {
    match s.parse::<f64>() {
      Ok(f) => {
        Ok(Atom::Number(f))
      },
      Err(..) => {
        match s.chars().next() {
          Some(c) => {
            if c.is_numeric() {
              Err(ParseAtomError::IncorrectSymbolName)
            } else {
              Ok(Atom::Symbol(s.to_string()))
            }
          },
          None => {
            Err(ParseAtomError::IncorrectSymbolName)
          }
        }
      }
    }
  }
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
}

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

  #[test]
  fn parse_integer() {
    assert_eq!(Atom::Number(64f64), "64".parse::<Atom>().ok().unwrap())
  }

  #[test]
  fn parse_float() {
    assert_eq!(Atom::Number(64.5), "64.5".parse::<Atom>().ok().unwrap())
  }

  #[test]
  fn parse_symbol() {
    assert_eq!(Atom::Symbol("name".to_string()), "name".parse::<Atom>().ok().unwrap())
  }
}
<commit_msg>Fix indentations<commit_after>use std::fmt;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
enum Atom {
    Number(f64),
    Symbol(String)
}

enum ParseAtomError {
    IncorrectSymbolName
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Atom::Number(n) => {
                write!(f, "{}", n)
            },
            Atom::Symbol(ref name) => {
                write!(f, "'{}", name)
            }
        }
    }
}

impl FromStr for Atom {
    type Err = ParseAtomError;

    fn from_str(s: &str) -> Result<Atom, ParseAtomError> {
        match s.parse::<f64>() {
            Ok(f) => {
                Ok(Atom::Number(f))
            },
            Err(..) => {
                match s.chars().next() {
                    Some(c) => {
                        if c.is_numeric() {
                            Err(ParseAtomError::IncorrectSymbolName)
                        } else {
                            Ok(Atom::Symbol(s.to_string()))
                        }
                    },
                    None => {
                        Err(ParseAtomError::IncorrectSymbolName)
                    }
                }
            }
        }
    }
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
}

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

    #[test]
    fn parse_integer() {
        assert_eq!(Atom::Number(64f64), "64".parse::<Atom>().ok().unwrap())
    }

    #[test]
    fn parse_float() {
        assert_eq!(Atom::Number(64.5), "64.5".parse::<Atom>().ok().unwrap())
    }

    #[test]
    fn parse_symbol() {
        assert_eq!(Atom::Symbol("name".to_string()), "name".parse::<Atom>().ok().unwrap())
    }
}
<|endoftext|>