<commit_before>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(static_in_const)]

#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session};
use rustc::session::config::{Input, ErrorOutputType};
use std::path::PathBuf;
use std::process::Command;
use syntax::ast;

use clippy_lints::utils::cargo;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        ClippyCompilerCalls {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(&mut self,
                      matches: &getopts::Matches,
                      sopts: &config::Options,
                      cfg: &ast::CrateConfig,
                      descriptions: &rustc_errors::registry::Registry,
                      output: ErrorOutputType)
                      -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(&mut self,
                matches: &getopts::Matches,
                sopts: &config::Options,
                cfg: &ast::CrateConfig,
                odir: &Option<PathBuf>,
                ofile: &Option<PathBuf>,
                descriptions: &rustc_errors::registry::Registry)
                -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(&mut self,
                     matches: &getopts::Matches,
                     sess: &Session,
                     cfg: &ast::CrateConfig,
                     input: &Input,
                     odir: &Option<PathBuf>,
                     ofile: &Option<PathBuf>)
                     -> Compilation {
        self.default.late_callback(matches, sess, cfg, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed").span);
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry { early_lint_passes,
                                                           late_lint_passes,
                                                           lint_groups,
                                                           llvm_passes,
                                                           attributes,
                                                           mir_passes,
                                                           .. } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.mir_passes.borrow_mut().extend(mir_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

use std::path::Path;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    --features               Features to compile for the package

Other options are the same as `cargo rustc`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

The feature `cargo-clippy` is automatically defined for convenience. You can use
it to allow or deny lints from the code, eg.:

    #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
"#;

#[allow(print_stdout)]
fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
        panic!("yummy");
    }

    let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps");

    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
        format!("{}/toolchains/{}", home, toolchain)
    } else {
        option_env!("SYSROOT")
            .map(|s| s.to_owned())
            .or(Command::new("rustc")
                .arg("--print")
                .arg("sysroot")
                .output()
                .ok()
                .and_then(|out| String::from_utf8(out.stdout).ok())
                .map(|s| s.trim().to_owned()))
            .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust")
    };

    if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
        // this arm is executed on the initial call to `cargo clippy`

        if std::env::args().any(|a| a == "--help" || a == "-h") {
            show_help();
            return;
        }

        let manifest_path_arg = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path="));

        let mut metadata = cargo::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).expect("could not obtain cargo metadata");

        assert_eq!(metadata.version, 1);

        let manifest_path = manifest_path_arg.map(|arg| PathBuf::from(Path::new(&arg["--manifest-path=".len()..])));

        let current_dir = std::env::current_dir();

        let package_index = metadata.packages.iter()
            .position(|package| {
                let package_manifest_path = Path::new(&package.manifest_path);
                if let Some(ref manifest_path) = manifest_path {
                    package_manifest_path == manifest_path
                } else {
                    let current_dir = current_dir.as_ref().expect("could not read current directory");
                    let package_manifest_directory = package_manifest_path.parent().expect("could not find parent directory of package manifest");
                    package_manifest_directory == current_dir
                }
            })
            .expect("could not find matching package");
        let package = metadata.packages.remove(package_index);
        for target in package.targets {
            let args = std::env::args().skip(2);
            if let Some(first) = target.kind.get(0) {
                if target.kind.len() > 1 || first.ends_with("lib") {
                    if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root) {
                        std::process::exit(code);
                    }
                } else if ["bin", "example", "test", "bench"].contains(&&**first) {
                    if let Err(code) = process(vec![format!("--{}", first), target.name].into_iter().chain(args), &dep_path, &sys_root) {
                        std::process::exit(code);
                    }
                }
            } else {
                panic!("badly formatted cargo metadata: target::kind is an empty array");
            }
        }
    } else {
        // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC` env var set to itself

        // this conditional check for the --sysroot flag is there so users can call `cargo-clippy` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
            env::args().collect()
        } else {
            env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect()
        };

        // this check ensures that dependencies are built but not linted and the final crate is
        // linted but not built
        args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);

        let mut ccc = ClippyCompilerCalls::new(env::args().any(|s| s == "-Zno-trans"));
        let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);

        if let Err(err_count) = result {
            if err_count > 0 {
                std::process::exit(1);
            }
        }
    }
}

fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32>
    where P: AsRef<Path>,
          I: Iterator<Item = String>
{

    let mut args = vec!["rustc".to_owned()];

    let mut found_dashes = false;
    for arg in old_args {
        found_dashes |= arg == "--";
        args.push(arg);
    }
    if !found_dashes {
        args.push("--".to_owned());
    }
    args.push("-L".to_owned());
    args.push(dep_path.as_ref().to_string_lossy().into_owned());
    args.push(String::from("--sysroot"));
    args.push(sysroot.to_owned());
    args.push("-Zno-trans".to_owned());
    args.push("--cfg".to_owned());
    args.push(r#"feature="cargo-clippy""#.to_owned());

    let path = std::env::current_exe().expect("current executable path invalid");
    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC", path)
        .spawn().expect("could not run cargo")
        .wait().expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<commit_msg>fixed callback changes from rustc 1.14.0-nightly (7c69b0d5a 2016-11-01)<commit_after>// error-pattern:yummy
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(static_in_const)]

#![allow(unknown_lints, missing_docs_in_private_items)]

extern crate clippy_lints;
extern crate getopts;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin;
extern crate syntax;

use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session};
use rustc::session::config::{Input, ErrorOutputType};
use std::path::PathBuf;
use std::process::Command;
use syntax::ast;

use clippy_lints::utils::cargo;

struct ClippyCompilerCalls {
    default: RustcDefaultCalls,
    run_lints: bool,
}

impl ClippyCompilerCalls {
    fn new(run_lints: bool) -> Self {
        ClippyCompilerCalls {
            default: RustcDefaultCalls,
            run_lints: run_lints,
        }
    }
}

impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
    fn early_callback(&mut self,
                      matches: &getopts::Matches,
                      sopts: &config::Options,
                      cfg: &ast::CrateConfig,
                      descriptions: &rustc_errors::registry::Registry,
                      output: ErrorOutputType)
                      -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(&mut self,
                matches: &getopts::Matches,
                sopts: &config::Options,
                cfg: &ast::CrateConfig,
                odir: &Option<PathBuf>,
                ofile: &Option<PathBuf>,
                descriptions: &rustc_errors::registry::Registry)
                -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(&mut self,
                     matches: &getopts::Matches,
                     sess: &Session,
                     input: &Input,
                     odir: &Option<PathBuf>,
                     ofile: &Option<PathBuf>)
                     -> Compilation {
        self.default.late_callback(matches, sess, input, odir, ofile)
    }
    fn build_controller(&mut self, sess: &Session, matches: &getopts::Matches) -> driver::CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);

        if self.run_lints {
            let old = std::mem::replace(&mut control.after_parse.callback, box |_| {});
            control.after_parse.callback = Box::new(move |state| {
                {
                    let mut registry = rustc_plugin::registry::Registry::new(state.session, state.krate.as_ref().expect("at this compilation stage the krate must be parsed").span);
                    registry.args_hidden = Some(Vec::new());
                    clippy_lints::register_plugins(&mut registry);

                    let rustc_plugin::registry::Registry { early_lint_passes,
                                                           late_lint_passes,
                                                           lint_groups,
                                                           llvm_passes,
                                                           attributes,
                                                           mir_passes,
                                                           .. } = registry;
                    let sess = &state.session;
                    let mut ls = sess.lint_store.borrow_mut();
                    for pass in early_lint_passes {
                        ls.register_early_pass(Some(sess), true, pass);
                    }
                    for pass in late_lint_passes {
                        ls.register_late_pass(Some(sess), true, pass);
                    }

                    for (name, to) in lint_groups {
                        ls.register_group(Some(sess), true, name, to);
                    }

                    sess.plugin_llvm_passes.borrow_mut().extend(llvm_passes);
                    sess.mir_passes.borrow_mut().extend(mir_passes);
                    sess.plugin_attributes.borrow_mut().extend(attributes);
                }
                old(state);
            });
        }

        control
    }
}

use std::path::Path;

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    --features               Features to compile for the package

Other options are the same as `cargo rustc`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

The feature `cargo-clippy` is automatically defined for convenience. You can use
it to allow or deny lints from the code, eg.:

    #[cfg_attr(feature = "cargo-clippy", allow(needless_lifetimes))]
"#;

#[allow(print_stdout)]
fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

pub fn main() {
    use std::env;

    if env::var("CLIPPY_DOGFOOD").map(|_| true).unwrap_or(false) {
        panic!("yummy");
    }

    let dep_path = env::current_dir().expect("current dir is not readable").join("target").join("debug").join("deps");

    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sys_root = if let (Some(home), Some(toolchain)) = (home, toolchain) {
        format!("{}/toolchains/{}", home, toolchain)
    } else {
        option_env!("SYSROOT")
            .map(|s| s.to_owned())
            .or(Command::new("rustc")
                .arg("--print")
                .arg("sysroot")
                .output()
                .ok()
                .and_then(|out| String::from_utf8(out.stdout).ok())
                .map(|s| s.trim().to_owned()))
            .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust")
    };

    if let Some("clippy") = std::env::args().nth(1).as_ref().map(AsRef::as_ref) {
        // this arm is executed on the initial call to `cargo clippy`

        if std::env::args().any(|a| a == "--help" || a == "-h") {
            show_help();
            return;
        }

        let manifest_path_arg = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path="));

        let mut metadata = cargo::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).expect("could not obtain cargo metadata");

        assert_eq!(metadata.version, 1);

        let manifest_path = manifest_path_arg.map(|arg| PathBuf::from(Path::new(&arg["--manifest-path=".len()..])));

        let current_dir = std::env::current_dir();

        let package_index = metadata.packages.iter()
            .position(|package| {
                let package_manifest_path = Path::new(&package.manifest_path);
                if let Some(ref manifest_path) = manifest_path {
                    package_manifest_path == manifest_path
                } else {
                    let current_dir = current_dir.as_ref().expect("could not read current directory");
                    let package_manifest_directory = package_manifest_path.parent().expect("could not find parent directory of package manifest");
                    package_manifest_directory == current_dir
                }
            })
            .expect("could not find matching package");
        let package = metadata.packages.remove(package_index);
        for target in package.targets {
            let args = std::env::args().skip(2);
            if let Some(first) = target.kind.get(0) {
                if target.kind.len() > 1 || first.ends_with("lib") {
                    if let Err(code) = process(std::iter::once("--lib".to_owned()).chain(args), &dep_path, &sys_root) {
                        std::process::exit(code);
                    }
                } else if ["bin", "example", "test", "bench"].contains(&&**first) {
                    if let Err(code) = process(vec![format!("--{}", first), target.name].into_iter().chain(args), &dep_path, &sys_root) {
                        std::process::exit(code);
                    }
                }
            } else {
                panic!("badly formatted cargo metadata: target::kind is an empty array");
            }
        }
    } else {
        // this arm is executed when cargo-clippy runs `cargo rustc` with the `RUSTC` env var set to itself

        // this conditional check for the --sysroot flag is there so users can call `cargo-clippy` directly
        // without having to pass --sysroot or anything
        let mut args: Vec<String> = if env::args().any(|s| s == "--sysroot") {
            env::args().collect()
        } else {
            env::args().chain(Some("--sysroot".to_owned())).chain(Some(sys_root)).collect()
        };

        // this check ensures that dependencies are built but not linted and the final crate is
        // linted but not built
        args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);

        let mut ccc = ClippyCompilerCalls::new(env::args().any(|s| s == "-Zno-trans"));
        let (result, _) = rustc_driver::run_compiler(&args, &mut ccc, None, None);

        if let Err(err_count) = result {
            if err_count > 0 {
                std::process::exit(1);
            }
        }
    }
}

fn process<P, I>(old_args: I, dep_path: P, sysroot: &str) -> Result<(), i32>
    where P: AsRef<Path>,
          I: Iterator<Item = String>
{

    let mut args = vec!["rustc".to_owned()];

    let mut found_dashes = false;
    for arg in old_args {
        found_dashes |= arg == "--";
        args.push(arg);
    }
    if !found_dashes {
        args.push("--".to_owned());
    }
    args.push("-L".to_owned());
    args.push(dep_path.as_ref().to_string_lossy().into_owned());
    args.push(String::from("--sysroot"));
    args.push(sysroot.to_owned());
    args.push("-Zno-trans".to_owned());
    args.push("--cfg".to_owned());
    args.push(r#"feature="cargo-clippy""#.to_owned());

    let path = std::env::current_exe().expect("current executable path invalid");
    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC", path)
        .spawn().expect("could not run cargo")
        .wait().expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}
<|endoftext|>


<commit_before>extern crate osmio;
extern crate image;
extern crate gif;

use std::fs;
use osmio::OSMReader;
use osmio::pbf::PBFReader;
use std::env::args;
use std::io::BufReader;
use std::collections::{HashMap, HashSet};

use gif::SetParameter;

type Frames = Vec<(u32, Vec<u32>)>;

fn read_file(filename: &str, height: u32, sec_per_frame: u32) -> Frames {
    let file = BufReader::new(fs::File::open(&filename).unwrap());
    let mut node_reader = PBFReader::new(file);
    let node_reader = node_reader.nodes();

    println!("Parsing {}", filename);

    let mut results: HashMap<u32, HashSet<u32>> = HashMap::new();

    // 1st April 2005, midnight GMT. We presume no OSM editing before then.
    let osm_epoch = 1109635200;

    let width = height * 2;

    // FIXME use a btreemap?

    let mut first_frame_no = std::u32::MAX;
    let mut last_frame_no = 0;

    let mut num_nodes = 0;
    for node in node_reader {
        if let (Some(lat), Some(lon)) = (node.lat, node.lon) {
            let timestamp = node.timestamp.to_epoch_number() as u64;
            if timestamp < osm_epoch {
                panic!("timestamp before epoch. Change code. {}", timestamp);
            }
            let offset = (timestamp - osm_epoch) as u32;
            // TODO double check that this rounds down
            let frame_no = offset / sec_per_frame;

            if frame_no < first_frame_no {
                first_frame_no = frame_no;
            }
            if frame_no > last_frame_no {
                last_frame_no = frame_no;
            }

            let pixel_idx = latlon_to_pixel_index(lat, lon, width, height);
            results.entry(frame_no).or_insert(HashSet::new()).insert(pixel_idx);

            num_nodes += 1;
            if num_nodes % 10_000_000 == 0 {
                println!("Done {} nodes", num_nodes);
            }
        }
    }
    let num_frames = last_frame_no - first_frame_no + 1;
    println!("There are {} frames, which is {} sec", num_frames, num_frames as f32/30.);

    let mut sorted_results = Vec::with_capacity((last_frame_no-first_frame_no+1) as usize);

    for frame_no in 0..num_frames {
        match results.remove(&(frame_no+first_frame_no)) {
            None => { sorted_results.push((frame_no, Vec::with_capacity(0))) },
            Some(pixels) => {
                let pixels = pixels.into_iter().collect();
                sorted_results.push((frame_no, pixels));
            }
        }
    }

    sorted_results
}

#[inline(always)]
fn age_to_colour(curr_value: u32, frame_no: u32) -> [u8; 3] {
    if curr_value == 0 {
        // This means the pixel has never been used
        [0, 0, 0]
    } else {
        let age = frame_no - curr_value;
        if age > 255 {
            [0, 0, 0]
        } else {
            [(255 - age) as u8, 0, 0]
        }

    }
}

fn latlon_to_pixel_index(lat: f32, lon: f32, width: u32, height: u32) -> u32 {
    // update the image
    let x = (((lon + 90.)/180.)*(width as f32)) as u32;
    let y = (((lat + 180.)/360.)*(height as f32)) as u32;

    //println!("lat = {} lon = {} x = {} y = {} y*width+x = {}", lat, lon, x, y, y*width+x);
    let i = y * width + x;

    i
}

fn create_equirectangular_map(frames: Frames, output_image_filename: &str, height: u32) {
    let mut output_file = fs::File::create(output_image_filename).expect("Can't create image");

    let width = height * 2;
    // FIXME change width/height to u16?
    let mut encoder = gif::Encoder::new(&mut output_file, width as u16, height as u16, &[]).expect("Couldn't create encoder");
    encoder.set(gif::Repeat::Infinite).expect("Couldn't get inf repeat");

    // 0 means never done.
    let mut image = vec![0u32; (width*height) as usize];

    for (frame_no, pixels) in frames.into_iter() {
        for i in pixels {
            image[i as usize] = frame_no;
        }

        // Write out a new frame
        let img = image::ImageBuffer::from_fn(width, height, |x, y| {
            //println!("x = {} y = {} width = {} height = {} x*width+y = {}", x, y, width, height, x*width+y);
            let curr_value = image[(y*width+x) as usize];
            image::Rgb(age_to_colour(curr_value, frame_no))
        });

        //let mut f = fs::File::create(format!("{}-frame{:08}.png", output_image_filename, frame_no)).expect("Couldn't create frame");
        //image::ImageRgb8(img.clone()).save(&mut f, image::PNG).expect("Couldn't save image");
        //frame_no += 1;

        let mut frame = gif::Frame::from_rgb(width as u16, height as u16, &img.into_vec());
        // 30 fps, and delay is in units of 10ms.
        frame.delay = 100 / 30;

        encoder.write_frame(&frame).expect("Couldn't write frame");

        println!("Wrote frame {}", frame_no);
        //println!("Wrote frame for timestamp {} ({})", iso, timestamp);

    }

}

fn main() {
    let input_filename = args().nth(1).expect("Missing inputfilename");
    let output_image = args().nth(2).expect("Missing output image");
    let height: u32 = args().nth(3).expect("need to provide a height").parse().expect("Not an integer");
    let frames_per_sec: u32 = args().nth(4).expect("need to provide a speed").parse().expect("Not an integer");

    let frames = read_file(&input_filename, height, frames_per_sec);

    println!("Creating image {}", output_image);

    create_equirectangular_map(frames, &output_image, height);

    println!("\nFinished");
}
<commit_msg>stuff<commit_after>extern crate osmio;
extern crate image;
extern crate gif;

use std::fs;
use osmio::OSMReader;
use osmio::pbf::PBFReader;
use std::env::args;
use std::io::BufReader;
use std::collections::{HashMap, HashSet};

use gif::SetParameter;

type Frames = Vec<(u32, Vec<u32>)>;

fn read_file(filename: &str, height: u32, sec_per_frame: u32, bbox: &[f32; 4]) -> Frames {
    let file = BufReader::new(fs::File::open(&filename).unwrap());
    let mut node_reader = PBFReader::new(file);
    let node_reader = node_reader.nodes();

    println!("Parsing {}", filename);

    let mut results: HashMap<u32, HashSet<u32>> = HashMap::new();

    let left = bbox[0]; let bottom = bbox[1]; let right = bbox[2]; let top = bbox[3];
    let bbox_width = right - left;
    let bbox_height = top - bottom;
    let width = ((bbox_width / bbox_height) * (height as f32)) as u32;

    // 1st April 2005, midnight GMT. We presume no OSM editing before then.
    let osm_epoch = 1109635200;

    // FIXME use a btreemap?

    let mut first_frame_no = std::u32::MAX;
    let mut last_frame_no = 0;

    let mut num_nodes = 0;
    for node in node_reader {
        if let (Some(lat), Some(lon)) = (node.lat, node.lon) {
            if lat > top || lat < bottom || lon > right || lon < left {
                continue;
            }

            let timestamp = node.timestamp.to_epoch_number() as u64;
            if timestamp < osm_epoch {
                panic!("timestamp before epoch. Change code. {}", timestamp);
            }
            let offset = (timestamp - osm_epoch) as u32;
            // TODO double check that this rounds down
            let frame_no = offset / sec_per_frame;

            if frame_no < first_frame_no {
                first_frame_no = frame_no;
            }
            if frame_no > last_frame_no {
                last_frame_no = frame_no;
            }

            let pixel_idx = latlon_to_pixel_index(lat, lon, width, height, &bbox);
            results.entry(frame_no).or_insert(HashSet::new()).insert(pixel_idx);

            num_nodes += 1;
            if num_nodes % 10_000_000 == 0 {
                println!("Done {} nodes", num_nodes);
            }
        }
    }
    let num_frames = last_frame_no - first_frame_no + 1;
    println!("There are {} frames, which is {} sec", num_frames, num_frames as f32/30.);

    let mut sorted_results = Vec::with_capacity((last_frame_no-first_frame_no+1) as usize);

    for frame_no in 0..num_frames {
        match results.remove(&(frame_no+first_frame_no)) {
            None => { sorted_results.push((frame_no, Vec::with_capacity(0))) },
            Some(pixels) => {
                let pixels = pixels.into_iter().collect();
                sorted_results.push((frame_no, pixels));
            }
        }
    }

    sorted_results
}

#[inline(always)]
fn age_to_colour(age: &Option<u32>) -> [u8; 4] {
    match *age {
        None => [0, 0, 0, 0xff],
        Some(age) => {
            let age = age * 3;
            if age > 255 {
                [0, 0, 0, 0xff]
            } else {
                [(255 - age) as u8, 0, 0, 0xff]
            }
        }
    }
}

fn latlon_to_pixel_index(lat: f32, lon: f32, width: u32, height: u32, bbox: &[f32; 4]) -> u32 {
    let left = bbox[0]; let bottom = bbox[1]; let right = bbox[2]; let top = bbox[3];
    assert!(top > bottom);
    let bbox_width = right - left;
    let bbox_height = top - bottom;
    let lat = top - lat;
    let lon = lon - left;

    let x = ((lon/bbox_width)*(width as f32)) as u32;
    let y = ((lat/bbox_height)*(height as f32)) as u32;

    //println!("lat = {} lon = {} x = {} y = {} y*width+x = {}", lat, lon, x, y, y*width+x);
    let i = y * width + x;

    i
}

fn create_equirectangular_map(frames: Frames, output_image_filename: &str, height: u32, bbox: &[f32; 4]) {
    let mut output_file = fs::File::create(output_image_filename).expect("Can't create image");

    let left = bbox[0]; let bottom = bbox[1]; let right = bbox[2]; let top = bbox[3];
    let bbox_width = right - left;
    let bbox_height = top - bottom;
    let width = ((bbox_width / bbox_height) * (height as f32)) as u32;

    // FIXME change width/height to u16?
    let mut encoder = gif::Encoder::new(&mut output_file, width as u16, height as u16, &[]).expect("Couldn't create encoder");
    encoder.set(gif::Repeat::Infinite).expect("Couldn't get inf repeat");

    let mut image = vec![None; (width*height) as usize];

    for (frame_no, pixels) in frames.into_iter() {
        for i in pixels {
            image[i as usize] = Some(frame_no);
        }

        let mut pixels = Vec::with_capacity(image.len() * 4);
        for p in image.iter().cloned() {
            pixels.extend(age_to_colour(&p.clone()).iter());
        }

        let mut frame = gif::Frame::from_rgba(width as u16, height as u16, pixels.as_mut_slice());
        // 30 fps, and delay is in units of 10ms.
        frame.delay = 100 / 30;

        encoder.write_frame(&frame).expect("Couldn't write frame");

        println!("Wrote frame {}", frame_no);

    }

}

fn main() {
    let input_filename = args().nth(1).expect("Missing inputfilename");
    let output_image = args().nth(2).expect("Missing output image");
    let height: u32 = args().nth(3).expect("need to provide a height").parse().expect("Not an integer");
    let frames_per_sec: u32 = args().nth(4).expect("need to provide a speed").parse().expect("Not an integer");

    let bbox = [-13.1, 49.28, -3.26, 56.69];

    let frames = read_file(&input_filename, height, frames_per_sec, &bbox);

    println!("Creating image {}", output_image);

    create_equirectangular_map(frames, &output_image, height, &bbox);

    println!("\nFinished");
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate libc;
extern crate nix;
extern crate pty;
extern crate rmp_serialize as msgpack;
extern crate rustc_serialize;
extern crate termios;

mod libc_ext;
mod pty_spawn;
mod winsize;
mod message;
mod broadcast;
mod server;
mod watch;

use docopt::Docopt;

static USAGE: &'static str ="
Usage:
  hokaido <command>
  hokaido <command> [--host=<host>] [--port=<port>] [--channel=<channel>]
  hokaido (-h | --help)
  hokaido (-v | --version)

Options:
  -h --help            Show this screen.
  -v --version         Show the version of hokaido.
  --host=<host>        Server name     [default: localhost].
  --port=<port>        Port number     [default: 4747].
  --channel=<channel>  channelnel name [default: default].
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_command:  Option<String>,
    flag_host:    String,
    flag_port:    i32,
    flag_channel: String,
    flag_version: bool
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit() );

    match args.arg_command {
        Some(command_name) => {
            match command_name.as_ref() {
                "broadcast" => broadcast::execute(args.flag_host, args.flag_port, args.flag_channel),
                "server"    => server::execute(args.flag_host, args.flag_port),
                "watch"     => watch::execute(args.flag_host, args.flag_port, args.flag_channel),
                _           => unreachable!()
            }
        },
        _ => {
            if args.flag_version {
                println!("{}", env!("CARGO_PKG_VERSION"));
            } else {
                unreachable!();
            }
        }
    }
}
<commit_msg>Default port is 4423, not 4747 :beer:<commit_after>extern crate docopt;
extern crate libc;
extern crate nix;
extern crate pty;
extern crate rmp_serialize as msgpack;
extern crate rustc_serialize;
extern crate termios;

mod libc_ext;
mod pty_spawn;
mod winsize;
mod message;
mod broadcast;
mod server;
mod watch;

use docopt::Docopt;

static USAGE: &'static str ="
Usage:
  hokaido <command>
  hokaido <command> [--host=<host>] [--port=<port>] [--channel=<channel>]
  hokaido (-h | --help)
  hokaido (-v | --version)

Options:
  -h --help            Show this screen.
  -v --version         Show the version of hokaido.
  --host=<host>        Server name     [default: localhost].
  --port=<port>        Port number     [default: 4423].
  --channel=<channel>  channelnel name [default: default].
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_command:  Option<String>,
    flag_host:    String,
    flag_port:    i32,
    flag_channel: String,
    flag_version: bool
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit() );

    match args.arg_command {
        Some(command_name) => {
            match command_name.as_ref() {
                "broadcast" => broadcast::execute(args.flag_host, args.flag_port, args.flag_channel),
                "server"    => server::execute(args.flag_host, args.flag_port),
                "watch"     => watch::execute(args.flag_host, args.flag_port, args.flag_channel),
                _           => unreachable!()
            }
        },
        _ => {
            if args.flag_version {
                println!("{}", env!("CARGO_PKG_VERSION"));
            } else {
                unreachable!();
            }
        }
    }
}
<|endoftext|>


<commit_before>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

#![doc(html_logo_url = "https://raw.githubusercontent.com/Luz/hexdino/master/logo.png")]

use std::io::prelude::*;
use std::fs::OpenOptions;
use std::io::SeekFrom;
use std::path::Path;
use std::error::Error;
use std::env;

mod draw;
mod find;
use draw::draw;
use find::FindSubset;

extern crate ncurses;
use ncurses::*;

// extern crate getopts;
// use getopts::Options;

#[derive(PartialEq, Copy, Clone)]
pub enum Mode {
    Command,
    Replace,
    TypeCommand,
    Insert,
    TypeSearch,
    SearchIt,
}

fn main() {
    let mut buf = vec![];
    let mut cursorpos: usize = 0;
    // 0 is left nibble, 1 is right nibble, 2 is ascii
    let mut cursorstate: usize = 0;
    // 0 = display data from first line of file
    let mut screenoffset: usize = 0;
    const SPALTEN: usize = 16;
    let mut command = String::new();

    // start ncursesw
    initscr();
    let screenheight: usize = getmaxy(stdscr) as usize;
    // ctrl+z and fg works with this
    cbreak();
    noecho();
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);

    printw("Welcome to Hexdino.\nPlease find the any-key on your keyboard and press it.\n");

    let args: Vec<_> = env::args().collect();
    // let program = args[0].clone();
    // let mut opts = Options::new();
    // opts.optopt("f", "", "set file name", "NAME");
    // opts.optflag("h", "help", "print this help menu");
    //
    // let matches = match opts.parse(&args[1..]) {
    // Ok(m) => { m }
    // Err(f) => { panic!(f.to_string()) }
    // };
    // if matches.opt_present("h") {
    // let brief = format!("Usage: {} FILE [options]", program);
    // print!("{}", opts.usage(&brief));
    // return;
    // }
    // let path = if !matches.free.is_empty() {
    // matches.free[0].clone()
    // } else {
    // let brief = format!("Usage: {} FILE [options]", program);
    // print!("{}", opts.usage(&brief));
    // return;
    // };

    let path = if args.len() > 1 {
        printw(&format!("Opening file {}", args[1]));
        args[1].clone()
    } else {
        printw(&format!("No file specified. Trying to open foo.txt"));
        "foo.txt".into()
    };

    let path = Path::new(&path);
    let display = path.display();

    getch();
    clear();

    if !has_colors() {
        endwin();
        println!("Your terminal does not support color!\n");
        return;
    }

    // TODO in this order: 1)disp files 2) hjkl movement 3) edit file by 'r' 4) save file 5) edit file by 'x, i' 6) search by '/'

    let mut file = match OpenOptions::new().read(true).write(true).create(true).open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    file.read_to_end(&mut buf).ok().expect("File could not be read.");

    let mut mode = Mode::Command;

    draw(&buf,
         cursorpos,
         SPALTEN,
         mode,
         &command,
         cursorstate,
         screenoffset);

    let mut key;
    //    key = getch() as u8;
    //    printw(&format!("{:?}", key));

    let mut quitnow = 0;
    while quitnow == 0 {
        key = getch() as u8;
        if mode == Mode::Command {
            match key as char {
                'h' => {
                    if cursorstate == 2 {
                        // ascii mode
                        if cursorpos > 0 {
                            // not at start
                            cursorpos -= 1; // go left
                        }
                    } else if cursorstate == 1 {
                        // hex mode, right nibble
                        cursorstate = 0; // left nibble
                    } else if cursorstate == 0 {
                        // hex mode, left nibble
                        if cursorpos > 0 {
                            // not at start
                            cursorstate = 1; // right nibble
                            cursorpos -= 1; // go left
                        }
                    }
                }
                'j' => {
                    if cursorpos + SPALTEN < buf.len() {
                        // not at end
                        cursorpos += SPALTEN; // go down
                    } else {
                        // when at end
                        if buf.len() != 0 {
                            // Suppress underflow
                            cursorpos = buf.len() - 1; // go to end
                        }
                    }
                }
                'k' => {
                    if cursorpos >= SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                'l' => {
                    if cursorstate == 2 {
                        // ascii mode
                        if cursorpos < buf.len() - 1 {
                            // not at end
                            cursorpos += 1; // go right
                        }
                    } else if cursorstate == 0 {
                        // hex mode, left nibble
                        cursorstate = 1; // right nibble
                    } else if cursorstate == 1 {
                        // hex mode, right nibble
                        if cursorpos < buf.len() - 1 {
                            // not at end
                            cursorstate = 0; // left nibble
                            cursorpos += 1; // go right
                        }
                    }
                }
                '0' => {
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    if cursorstate == 1 {
                        // hex mode, right nibble
                        cursorstate = 0; // left nibble
                    }
                }
                '$' => {
                    if cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1) < buf.len() {
                        // check if no overflow
                        cursorpos = cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1); // jump to end of line
                    } else {
                        cursorpos = buf.len() - 1 // jump to end of line
                    }
                    if cursorstate == 0 {
                        // hex mode, left nibble
                        cursorstate = 1; // right nibble
                    }
                }
                'r' => {
                    mode = Mode::Replace;
                }
                'x' => {
                    if buf.len() > 0 {
                        // remove the current char
                        buf.remove(cursorpos);
                        if cursorpos >= buf.len() {
                            cursorpos = buf.len() - 1;
                        }
                    }
                }
                'i' => {
                    mode = Mode::Insert;
                }
                ':' => {
                    command.clear(); // delete old command
                    mode = Mode::TypeCommand;
                }
                'J' => {
                    if cursorstate == 2 {
                        // ascii mode
                        cursorstate = 0; // hex mode, left nibble
                    } else {
                        cursorstate = 2; // jump to ascii
                    }
                }
                '?' => {
                    // TODO
                    command.push_str("No helpfile yet");
                }
                '/' => {
                    // TODO
                    command.clear();
                    mode = Mode::TypeSearch;
                }
                _ => (),
            }

            // Always move screen when cursor leaves screen
            if cursorpos > (screenheight + screenoffset - 1) * SPALTEN - 1 {
                screenoffset += 1; // move screen
            }
            if cursorpos < screenoffset * SPALTEN {
                screenoffset -= 1; // move screen
            }

        } else if mode == Mode::Replace && cursorstate == 2 {
            // r was pressed so replace next char in ascii mode
            match key {
                c @ 32...126 => buf[cursorpos] = c,
                _ => (),
            }
            mode = Mode::Command;
        } else if mode == Mode::Replace {
            let mask = if cursorstate == 0 { 0x0F } else { 0xF0 };
            let shift = if cursorstate == 0 { 4 } else { 0 };
            // Change the selected nibble
            if let Some(c) = (key as char).to_digit(16) {
                buf[cursorpos] = buf[cursorpos] & mask | (c as u8) << shift;
            }
            mode = Mode::Command;
        } else if mode == Mode::TypeCommand {
            match key {
                c @ 32...126 => {
                    command.push(c as char);
                }
                27 => {
                    command.clear();
                    mode = Mode::Command;
                }
                10 => {
                    // Enter pressed, compute command!
                    if (command == "w".to_string()) || (command == "wq".to_string()) {
                        file.seek(SeekFrom::Start(0))
                            .ok()
                            .expect("Filepointer could not be set to 0");
                        file.write_all(&mut buf).ok().expect("File could not be written.");
                        if command == "wq".to_string() {
                            quitnow = 1;
                        }
                        command.clear();
                        mode = Mode::Command;
                    } else if command == "q".to_string() {
                        quitnow = 1;
                    } else {
                        command.clear();
                        command.push_str("Bad_command!");
                        mode = Mode::Command;
                    }
                }
                _ => (),
            }
        } else if mode == Mode::Insert {
            if cursorstate == 0 {
                // Left nibble
                match key {
                    c @ 65... 70 => // A-F
                        {buf.insert(cursorpos, (c-55)<<4 ); cursorstate = 1;},
                    c @ 97...102 => // a-f
                        {buf.insert(cursorpos, (c-87)<<4 ); cursorstate = 1;},
                    c @ 48... 57 => // 0-9
                        {buf.insert(cursorpos, (c-48)<<4 ); cursorstate = 1;},
                    27 => {mode = Mode::Command;},
                    _ => ()
                }
            } else if cursorstate == 1 {
                // Right nibble
                match key {
                    c @ 65...70 => // A-F
                        { buf[cursorpos] = buf[cursorpos]&0xF0 | (c-55); cursorstate = 0; cursorpos+=1; },
                    c @ 97...102 => // a-f
                        { buf[cursorpos] = buf[cursorpos]&0xF0 | (c-87); cursorstate = 0; cursorpos+=1; },
                    c @ 48...57 => // 0-9
                        { buf[cursorpos] = buf[cursorpos]&0xF0 | (c-48); cursorstate = 0; cursorpos+=1; },
                    27 => {mode = Mode::Command;},
                    _ => ()
                }
            } else if cursorstate == 2 {
                // Ascii
                match key {
                    c @ 32...126 => {
                        buf.insert(cursorpos, c);
                        cursorpos += 1;
                    }
                    27 => {
                        mode = Mode::Command;
                    }
                    _ => (),
                }
            }
        } else if mode == Mode::TypeSearch {
            //            if cursorstate == 2 { // Ascii search
            match key {
                c @ 32...126 => {
                    command.push(c as char);
                }
                27 => {
                    command.clear();
                    mode = Mode::Command;
                }
                10 => {
                    // Enter pressed, compute command!
                    mode = Mode::SearchIt;
                }
                _ => (),
            }
            //            }

            if mode == Mode::SearchIt {
                let search = command.as_bytes();
                cursorpos = buf.find_subset(&search).unwrap_or(cursorpos);
                mode = Mode::Command;
                // command.push_str("Bad_command!");
            }
        }
        draw(&buf,
             cursorpos,
             SPALTEN,
             mode,
             &command,
             cursorstate,
             screenoffset);
    }

    refresh();
    endwin();
}
<commit_msg>Add stub for hex search<commit_after>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

#![doc(html_logo_url = "https://raw.githubusercontent.com/Luz/hexdino/master/logo.png")]

use std::io::prelude::*;
use std::fs::OpenOptions;
use std::io::SeekFrom;
use std::path::Path;
use std::error::Error;
use std::env;

mod draw;
mod find;
use draw::draw;
use find::FindSubset;

extern crate ncurses;
use ncurses::*;

// extern crate getopts;
// use getopts::Options;

#[derive(PartialEq, Copy, Clone)]
pub enum Mode {
    Command,
    Replace,
    TypeCommand,
    Insert,
    TypeSearch,
    SearchIt,
    SearchItHex,
}

fn main() {
    let mut buf = vec![];
    let mut cursorpos: usize = 0;
    // 0 is left nibble, 1 is right nibble, 2 is ascii
    let mut cursorstate: usize = 0;
    // 0 = display data from first line of file
    let mut screenoffset: usize = 0;
    const SPALTEN: usize = 16;
    let mut command = String::new();

    // start ncursesw
    initscr();
    let screenheight: usize = getmaxy(stdscr) as usize;
    // ctrl+z and fg works with this
    cbreak();
    noecho();
    start_color();
    init_pair(1, COLOR_GREEN, COLOR_BLACK);

    printw("Welcome to Hexdino.\nPlease find the any-key on your keyboard and press it.\n");

    let args: Vec<_> = env::args().collect();
    // let program = args[0].clone();
    // let mut opts = Options::new();
    // opts.optopt("f", "", "set file name", "NAME");
    // opts.optflag("h", "help", "print this help menu");
    //
    // let matches = match opts.parse(&args[1..]) {
    // Ok(m) => { m }
    // Err(f) => { panic!(f.to_string()) }
    // };
    // if matches.opt_present("h") {
    // let brief = format!("Usage: {} FILE [options]", program);
    // print!("{}", opts.usage(&brief));
    // return;
    // }
    // let path = if !matches.free.is_empty() {
    // matches.free[0].clone()
    // } else {
    // let brief = format!("Usage: {} FILE [options]", program);
    // print!("{}", opts.usage(&brief));
    // return;
    // };

    let path = if args.len() > 1 {
        printw(&format!("Opening file {}", args[1]));
        args[1].clone()
    } else {
        printw(&format!("No file specified. Trying to open foo.txt"));
        "foo.txt".into()
    };

    let path = Path::new(&path);
    let display = path.display();

    getch();
    clear();

    if !has_colors() {
        endwin();
        println!("Your terminal does not support color!\n");
        return;
    }

    // TODO in this order: 1)disp files 2) hjkl movement 3) edit file by 'r' 4) save file 5) edit file by 'x, i' 6) search by '/'

    let mut file = match OpenOptions::new().read(true).write(true).create(true).open(&path) {
        Err(why) => panic!("couldn't open {}: {}", display, Error::description(&why)),
        Ok(file) => file,
    };

    file.read_to_end(&mut buf).ok().expect("File could not be read.");

    let mut mode = Mode::Command;

    draw(&buf,
         cursorpos,
         SPALTEN,
         mode,
         &command,
         cursorstate,
         screenoffset);

    let mut key;
    //    key = getch() as u8;
    //    printw(&format!("{:?}", key));

    let mut quitnow = 0;
    while quitnow == 0 {
        key = getch() as u8;
        if mode == Mode::Command {
            match key as char {
                'h' => {
                    if cursorstate == 2 {
                        // ascii mode
                        if cursorpos > 0 {
                            // not at start
                            cursorpos -= 1; // go left
                        }
                    } else if cursorstate == 1 {
                        // hex mode, right nibble
                        cursorstate = 0; // left nibble
                    } else if cursorstate == 0 {
                        // hex mode, left nibble
                        if cursorpos > 0 {
                            // not at start
                            cursorstate = 1; // right nibble
                            cursorpos -= 1; // go left
                        }
                    }
                }
                'j' => {
                    if cursorpos + SPALTEN < buf.len() {
                        // not at end
                        cursorpos += SPALTEN; // go down
                    } else {
                        // when at end
                        if buf.len() != 0 {
                            // Suppress underflow
                            cursorpos = buf.len() - 1; // go to end
                        }
                    }
                }
                'k' => {
                    if cursorpos >= SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                'l' => {
                    if cursorstate == 2 {
                        // ascii mode
                        if cursorpos < buf.len() - 1 {
                            // not at end
                            cursorpos += 1; // go right
                        }
                    } else if cursorstate == 0 {
                        // hex mode, left nibble
                        cursorstate = 1; // right nibble
                    } else if cursorstate == 1 {
                        // hex mode, right nibble
                        if cursorpos < buf.len() - 1 {
                            // not at end
                            cursorstate = 0; // left nibble
                            cursorpos += 1; // go right
                        }
                    }
                }
                '0' => {
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    if cursorstate == 1 {
                        // hex mode, right nibble
                        cursorstate = 0; // left nibble
                    }
                }
                '$' => {
                    if cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1) < buf.len() {
                        // check if no overflow
                        cursorpos = cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1); // jump to end of line
                    } else {
                        cursorpos = buf.len() - 1 // jump to end of line
                    }
                    if cursorstate == 0 {
                        // hex mode, left nibble
                        cursorstate = 1; // right nibble
                    }
                }
                'r' => {
                    mode = Mode::Replace;
                }
                'x' => {
                    if buf.len() > 0 {
                        // remove the current char
                        buf.remove(cursorpos);
                        if cursorpos >= buf.len() {
                            cursorpos = buf.len() - 1;
                        }
                    }
                }
                'i' => {
                    mode = Mode::Insert;
                }
                ':' => {
                    command.clear(); // delete old command
                    mode = Mode::TypeCommand;
                }
                'J' => {
                    if cursorstate == 2 {
                        // ascii mode
                        cursorstate = 0; // hex mode, left nibble
                    } else {
                        cursorstate = 2; // jump to ascii
                    }
                }
                '?' => {
                    // TODO
                    command.push_str("No helpfile yet");
                }
                '/' => {
                    // TODO
                    command.clear();
                    mode = Mode::TypeSearch;
                }
                _ => (),
            }

            // Always move screen when cursor leaves screen
            if cursorpos > (screenheight + screenoffset - 1) * SPALTEN - 1 {
                screenoffset += 1; // move screen
            }
            if cursorpos < screenoffset * SPALTEN {
                screenoffset -= 1; // move screen
            }

        } else if mode == Mode::Replace && cursorstate == 2 {
            // r was pressed so replace next char in ascii mode
            match key {
                c @ 32...126 => buf[cursorpos] = c,
                _ => (),
            }
            mode = Mode::Command;
        } else if mode == Mode::Replace {
            let mask = if cursorstate == 0 { 0x0F } else { 0xF0 };
            let shift = if cursorstate == 0 { 4 } else { 0 };
            // Change the selected nibble
            if let Some(c) = (key as char).to_digit(16) {
                buf[cursorpos] = buf[cursorpos] & mask | (c as u8) << shift;
            }
            mode = Mode::Command;
        } else if mode == Mode::TypeCommand {
            match key {
                c @ 32...126 => {
                    command.push(c as char);
                }
                27 => {
                    command.clear();
                    mode = Mode::Command;
                }
                10 => {
                    // Enter pressed, compute command!
                    if (command == "w".to_string()) || (command == "wq".to_string()) {
                        file.seek(SeekFrom::Start(0))
                            .ok()
                            .expect("Filepointer could not be set to 0");
                        file.write_all(&mut buf).ok().expect("File could not be written.");
                        if command == "wq".to_string() {
                            quitnow = 1;
                        }
                        command.clear();
                        mode = Mode::Command;
                    } else if command == "q".to_string() {
                        quitnow = 1;
                    } else {
                        command.clear();
                        command.push_str("Bad_command!");
                        mode = Mode::Command;
                    }
                }
                _ => (),
            }
        } else if mode == Mode::Insert {
            if cursorstate == 0 {
                // Left nibble
                match key {
                    c @ 65... 70 => // A-F
                        {buf.insert(cursorpos, (c-55)<<4 ); cursorstate = 1;},
                    c @ 97...102 => // a-f
                        {buf.insert(cursorpos, (c-87)<<4 ); cursorstate = 1;},
                    c @ 48... 57 => // 0-9
                        {buf.insert(cursorpos, (c-48)<<4 ); cursorstate = 1;},
                    27 => {mode = Mode::Command;},
                    _ => ()
                }
            } else if cursorstate == 1 {
                // Right nibble
                match key {
                    c @ 65...70 => // A-F
                        { buf[cursorpos] = buf[cursorpos]&0xF0 | (c-55); cursorstate = 0; cursorpos+=1; },
                    c @ 97...102 => // a-f
                        { buf[cursorpos] = buf[cursorpos]&0xF0 | (c-87); cursorstate = 0; cursorpos+=1; },
                    c @ 48...57 => // 0-9
                        { buf[cursorpos] = buf[cursorpos]&0xF0 | (c-48); cursorstate = 0; cursorpos+=1; },
                    27 => {mode = Mode::Command;},
                    _ => ()
                }
            } else if cursorstate == 2 {
                // Ascii
                match key {
                    c @ 32...126 => {
                        buf.insert(cursorpos, c);
                        cursorpos += 1;
                    }
                    27 => {
                        mode = Mode::Command;
                    }
                    _ => (),
                }
            }
        } else if mode == Mode::TypeSearch {
            //            if cursorstate == 2 { // Ascii search
            match key {
                c @ 32...126 => {
                    command.push(c as char);
                }
                27 => {
                    command.clear();
                    mode = Mode::Command;
                }
                10 => {
                    // Enter pressed, compute command!
                    if cursorstate == 2 {
                        mode = Mode::SearchIt;
                    } else {
                        mode = Mode::SearchItHex;
                    }
                }
                _ => (),
            }
            //            }

            if mode == Mode::SearchIt {
                let search = command.as_bytes();
                cursorpos = buf.find_subset(&search).unwrap_or(cursorpos);
                mode = Mode::Command;
                // command.push_str("Bad_command!");
            }
            if mode == Mode::SearchItHex {
                // TODO
                mode = Mode::Command;
                command.push_str("Hex search not yet implemented!");
            }
        }
        draw(&buf,
             cursorpos,
             SPALTEN,
             mode,
             &command,
             cursorstate,
             screenoffset);
    }

    refresh();
    endwin();
}
<|endoftext|>


<commit_before>extern crate itertools;
extern crate num;
extern crate permutohedron;

use std::env;

mod euler1;
mod euler2;
mod euler3;
mod euler4;
mod euler5;
mod euler6;
mod euler7;
mod euler8;
mod euler9;
mod euler10;
mod euler12;
mod euler14;
mod euler15;
mod euler20;
mod euler22;
mod euler30;
mod euler35;
mod euler36;
mod euler37;
mod euler41;
mod euler42;
mod euler43;
mod euler45;
mod euler46;
mod euler48;
mod euler49;
mod euler50;
mod euler52;
mod euler74;
mod euler79;
mod euler92;
mod euler92b;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    if args.len() < 2 {
        println!("Provide a number as parameter");
    } else {
        match args[1].as_ref() {
            "1" => euler1::main(),
            "2" => euler2::main(),
            "3" => euler3::main(),
            "4" => euler4::main(),
            "5" => euler5::main(),
            "6" => euler6::main(),
            "7" => euler7::main(),
            "8" => euler8::main(),
            "9" => euler9::main(),
            "10" => euler10::main(),
            "12" => euler12::main(),
            "14" => euler14::main(),
            "15" => euler15::main(),
            "20" => euler20::main(),
            "35" => euler35::main(),
            "36" => euler36::main(),
            "37" => euler37::main(),
            "41" => euler41::main(),
            "42" => euler42::main(),
            "43" => euler43::main(),
            "45" => euler45::main(),
            "46" => euler46::main(),
            "48" => euler48::main(),
            "49" => euler49::main(),
            "50" => euler50::main(),
            "22" => euler22::main(),
            "52" => euler52::main(),
            "74" => euler74::main(),
            "79" => euler79::main(),
            "92" => euler92::main(),
            "92b" => euler92b::main(),
            _ => println!("Hasn't solved yet"),
        }
    }
}
<commit_msg>forgot to commit this line for problem 30 solution<commit_after>extern crate itertools;
extern crate num;
extern crate permutohedron;

use std::env;

mod euler1;
mod euler2;
mod euler3;
mod euler4;
mod euler5;
mod euler6;
mod euler7;
mod euler8;
mod euler9;
mod euler10;
mod euler12;
mod euler14;
mod euler15;
mod euler20;
mod euler22;
mod euler30;
mod euler35;
mod euler36;
mod euler37;
mod euler41;
mod euler42;
mod euler43;
mod euler45;
mod euler46;
mod euler48;
mod euler49;
mod euler50;
mod euler52;
mod euler74;
mod euler79;
mod euler92;
mod euler92b;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    if args.len() < 2 {
        println!("Provide a number as parameter");
    } else {
        match args[1].as_ref() {
            "1" => euler1::main(),
            "2" => euler2::main(),
            "3" => euler3::main(),
            "4" => euler4::main(),
            "5" => euler5::main(),
            "6" => euler6::main(),
            "7" => euler7::main(),
            "8" => euler8::main(),
            "9" => euler9::main(),
            "10" => euler10::main(),
            "12" => euler12::main(),
            "14" => euler14::main(),
            "15" => euler15::main(),
            "20" => euler20::main(),
            "30" => euler30::main(),
            "35" => euler35::main(),
            "36" => euler36::main(),
            "37" => euler37::main(),
            "41" => euler41::main(),
            "42" => euler42::main(),
            "43" => euler43::main(),
            "45" => euler45::main(),
            "46" => euler46::main(),
            "48" => euler48::main(),
            "49" => euler49::main(),
            "50" => euler50::main(),
            "22" => euler22::main(),
            "52" => euler52::main(),
            "74" => euler74::main(),
            "79" => euler79::main(),
            "92" => euler92::main(),
            "92b" => euler92b::main(),
            _ => println!("Hasn't solved yet"),
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::time::{Duration, Instant};
use std::thread;

#[macro_use]
extern crate glium;

pub mod gb_proc;
pub mod gpu;
pub mod controller;
mod debugger;

use self::debugger::Debugger;

use self::gb_proc::handler_holder::GBHandlerHolder;
use self::gb_proc::cartridge::Cartridge;
use self::gb_proc::cpu::Cpu;
use self::gpu::renderer::Renderer;
use self::controller::{Event, Controller};

#[cfg(test)]
mod tests;

pub fn main() {
    let mut f = File::open("rom.gb").unwrap();
    let cartridge = Cartridge::from_file(&mut f);

    let mut controller = Controller::new();;

    let handler = GBHandlerHolder::new(Box::new(cartridge));
    let mut cpu = Cpu::new(Box::new(handler));

    cpu.set_debug(false);

    let mut last_update = Instant::now();

    let mut debugger = Debugger::new();
    let mut natural_speed = true;
    // Refresh 59.7 times a sec
    let target = Duration::new(0, (1e9/59.7) as u32);
    loop {
        debugger.check_breakpoints(&mut cpu);

        cpu.next_instruction();

        if cpu.handler_holder.should_refresh() {
            match controller.check_events(&mut cpu) {
                Event::Quit => break,
                Event::Break => {
                    debugger.breakpoint(&mut cpu);
                },
                Event::ToggleSpeed => { natural_speed = !natural_speed },
                Event::Continue => {},
            }

            let screen = cpu.handler_holder.get_screen_buffer();
            controller.refresh(screen);

            let diff = Instant::now() - last_update;

            if target > diff && natural_speed {
                thread::sleep(target - diff);
            }

            last_update = Instant::now();
        }

        debugger.next_instruction(&mut cpu);
    }
}
<commit_msg>Increase target speed to 63fps.<commit_after>use std::fs::File;
use std::time::{Duration, Instant};
use std::thread;

#[macro_use]
extern crate glium;

pub mod gb_proc;
pub mod gpu;
pub mod controller;
mod debugger;

use self::debugger::Debugger;

use self::gb_proc::handler_holder::GBHandlerHolder;
use self::gb_proc::cartridge::Cartridge;
use self::gb_proc::cpu::Cpu;
use self::gpu::renderer::Renderer;
use self::controller::{Event, Controller};

#[cfg(test)]
mod tests;

pub fn main() {
    let mut f = File::open("rom.gb").unwrap();
    let cartridge = Cartridge::from_file(&mut f);

    let mut controller = Controller::new();;

    let handler = GBHandlerHolder::new(Box::new(cartridge));
    let mut cpu = Cpu::new(Box::new(handler));

    cpu.set_debug(false);

    let mut last_update = Instant::now();

    let mut debugger = Debugger::new();
    let mut natural_speed = true;
    // This target seems to match the actual Game Boy in terms of speed
    let target = Duration::new(0, (1e9/63.0) as u32);
    loop {
        debugger.check_breakpoints(&mut cpu);

        cpu.next_instruction();

        if cpu.handler_holder.should_refresh() {
            match controller.check_events(&mut cpu) {
                Event::Quit => break,
                Event::Break => {
                    debugger.breakpoint(&mut cpu);
                },
                Event::ToggleSpeed => { natural_speed = !natural_speed },
                Event::Continue => {},
            }

            let screen = cpu.handler_holder.get_screen_buffer();
            controller.refresh(screen);

            let diff = Instant::now() - last_update;

            if target > diff && natural_speed {
                thread::sleep(target - diff);
            }

            last_update = Instant::now();
        }

        debugger.next_instruction(&mut cpu);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate notify;

mod gitignore;
mod notification_filter;
mod runner;

use std::sync::mpsc::{channel, Receiver, RecvError};
use std::{env, thread, time};
use std::path::Path;

use clap::{App, Arg, ArgMatches};
use notify::{Event, RecommendedWatcher, Watcher};

use notification_filter::NotificationFilter;
use runner::Runner;

fn get_args<'a>() -> ArgMatches<'a> {
    App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("path")
            .help("Path to watch")
            .short("w")
            .long("watch")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true)
            .default_value("."))
        .arg(Arg::with_name("command")
            .help("Command to execute")
            .multiple(true)
            .required(true))
        .arg(Arg::with_name("extensions")
             .help("Comma-separated list of file extensions to watch (js,css,html)")
             .short("e")
             .long("exts")
             .takes_value(true))
        .arg(Arg::with_name("clear")
            .help("Clear screen before executing command")
            .short("c")
            .long("clear"))
        .arg(Arg::with_name("restart")
             .help("Restart the process if it's still running")
             .short("r")
             .long("restart"))
        .arg(Arg::with_name("debug")
             .help("Print debugging messages to stderr")
             .short("d")
             .long("debug"))
        .arg(Arg::with_name("filter")
             .help("Ignore all modifications except those matching the pattern")
             .short("f")
             .long("filter")
             .number_of_values(1)
             .multiple(true)
             .takes_value(true)
             .value_name("pattern"))
        .arg(Arg::with_name("ignore")
             .help("Ignore modifications to paths matching the pattern")
             .short("i")
             .long("ignore")
             .number_of_values(1)
             .multiple(true)
             .takes_value(true)
             .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
             .help("Skip auto-loading of .gitignore files for filtering")
             .long("no-vcs-ignore"))
        .arg(Arg::with_name("run-initially")
             .help("Run command initially, before first file change")
             .long("run-initially"))
        .get_matches()
}

fn init_logger(debug: bool) {
    let mut log_builder = env_logger::LogBuilder::new();
    let level = if debug {
        log::LogLevelFilter::Debug
    } else {
		log::LogLevelFilter::Warn
    };

    log_builder
        .format(|r| format!("*** {}", r.args()))
        .filter(None, level);
    log_builder.init().expect("unable to initialize logger");
}

fn main() {
    let args = get_args();

    init_logger(args.is_present("debug"));

    let cwd = env::current_dir()
        .expect("unable to get cwd")
        .canonicalize()
        .expect("unable to canonicalize cwd");

    let mut gitignore_file = None;
    if !args.is_present("no-vcs-ignore") {
        let gitignore_path = cwd.join(".gitignore");
        if gitignore_path.exists() {
            debug!("Found .gitignore file: {:?}", gitignore_path);

            gitignore_file = gitignore::parse(&gitignore_path).ok();
        }
    }

    let mut filter = NotificationFilter::new(&cwd, gitignore_file).expect("unable to create notification filter");

    // Add default ignore list
    let dotted_dirs = Path::new(".*").join("*");
    let default_filters = vec!["*/.DS_Store", "*.pyc", "*.swp", dotted_dirs.to_str().unwrap()];
    for p in default_filters {
        filter.add_ignore(p).expect("bad default filter");
    }

    if let Some(extensions) = args.values_of("extensions") {
        for ext in extensions {
            filter.add_extension(ext).expect("bad extension");
        }
    }

    if let Some(filters) = args.values_of("filter") {
        for p in filters {
            filter.add_filter(p).expect("bad filter");
        }
    }

    if let Some(ignores) = args.values_of("ignore") {
        for i in ignores {
            filter.add_ignore(i).expect("bad ignore pattern");
        }
    }

    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("unable to create watcher");

    let paths = args.values_of("path").unwrap();
    for path in paths {
        match Path::new(path).canonicalize() {
            Ok(canonicalized)   => watcher.watch(canonicalized).expect("unable to watch path"),
            Err(_)              => {
                println!("invalid path: {}", path);
                return;
            }
        }
    }

    let cmd_parts: Vec<&str> = args.values_of("command").unwrap().collect();
    let cmd = cmd_parts.join(" ");
    let mut runner = Runner::new(args.is_present("restart"), args.is_present("clear"));

    if args.is_present("run-initially") {
        runner.run_command(&cmd);
    }

    loop {
        let e = wait(&rx, &filter).expect("error when waiting for filesystem changes");

        debug!("{:?}: {:?}", e.op, e.path);

        runner.run_command(&cmd);
    }
}

fn wait(rx: &Receiver<Event>, filter: &NotificationFilter) -> Result<Event, RecvError> {
    loop {
        // Block on initial notification
        let e = try!(rx.recv());
        if let Some(ref path) = e.path {
            if filter.is_excluded(path) {
                continue;
            }
        }

        // Accumulate subsequent events
        thread::sleep(time::Duration::from_millis(250));

        // Drain rx buffer and drop them
        while let Ok(_) = rx.try_recv() {
			// nothing to do here
        }

        return Ok(e);
    }
}
<commit_msg>Search for .gitignore files in parent dirs; closes #10<commit_after>#[macro_use]
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate notify;

mod gitignore;
mod notification_filter;
mod runner;

use std::sync::mpsc::{channel, Receiver, RecvError};
use std::{env, thread, time};
use std::path::{Path, PathBuf};

use clap::{App, Arg, ArgMatches};
use notify::{Event, RecommendedWatcher, Watcher};

use notification_filter::NotificationFilter;
use runner::Runner;

// Starting at the specified path, search for gitignore files,
// stopping at the first one found.
fn find_gitignore_file(path: &Path) -> Option<PathBuf> {
    let mut gitignore_path = path.join(".gitignore");
    if gitignore_path.exists() {
        return Some(gitignore_path);
    }

    let p = path.to_owned();

    while let Some(p) = p.parent() {
        gitignore_path = p.join(".gitignore");
        if gitignore_path.exists() {
            return Some(gitignore_path);
        }
    }

    None
}

fn get_args<'a>() -> ArgMatches<'a> {
    App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("path")
            .help("Path to watch")
            .short("w")
            .long("watch")
            .number_of_values(1)
            .multiple(true)
            .takes_value(true)
            .default_value("."))
        .arg(Arg::with_name("command")
            .help("Command to execute")
            .multiple(true)
            .required(true))
        .arg(Arg::with_name("extensions")
             .help("Comma-separated list of file extensions to watch (js,css,html)")
             .short("e")
             .long("exts")
             .takes_value(true))
        .arg(Arg::with_name("clear")
            .help("Clear screen before executing command")
            .short("c")
            .long("clear"))
        .arg(Arg::with_name("restart")
             .help("Restart the process if it's still running")
             .short("r")
             .long("restart"))
        .arg(Arg::with_name("debug")
             .help("Print debugging messages to stderr")
             .short("d")
             .long("debug"))
        .arg(Arg::with_name("filter")
             .help("Ignore all modifications except those matching the pattern")
             .short("f")
             .long("filter")
             .number_of_values(1)
             .multiple(true)
             .takes_value(true)
             .value_name("pattern"))
        .arg(Arg::with_name("ignore")
             .help("Ignore modifications to paths matching the pattern")
             .short("i")
             .long("ignore")
             .number_of_values(1)
             .multiple(true)
             .takes_value(true)
             .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
             .help("Skip auto-loading of .gitignore files for filtering")
             .long("no-vcs-ignore"))
        .arg(Arg::with_name("run-initially")
             .help("Run command initially, before first file change")
             .long("run-initially"))
        .get_matches()
}

fn init_logger(debug: bool) {
    let mut log_builder = env_logger::LogBuilder::new();
    let level = if debug {
        log::LogLevelFilter::Debug
    } else {
		log::LogLevelFilter::Warn
    };

    log_builder
        .format(|r| format!("*** {}", r.args()))
        .filter(None, level);
    log_builder.init().expect("unable to initialize logger");
}

fn main() {
    let args = get_args();

    init_logger(args.is_present("debug"));

    let cwd = env::current_dir()
        .expect("unable to get cwd")
        .canonicalize()
        .expect("unable to canonicalize cwd");

    let mut gitignore_file = None;
    if !args.is_present("no-vcs-ignore") {
        if let Some(gitignore_path) = find_gitignore_file(&cwd) {
            debug!("Found .gitignore file: {:?}", gitignore_path);

            gitignore_file = gitignore::parse(&gitignore_path).ok();
        }
    }

    let mut filter = NotificationFilter::new(&cwd, gitignore_file).expect("unable to create notification filter");

    // Add default ignore list
    let dotted_dirs = Path::new(".*").join("*");
    let default_filters = vec!["*/.DS_Store", "*.pyc", "*.swp", dotted_dirs.to_str().unwrap()];
    for p in default_filters {
        filter.add_ignore(p).expect("bad default filter");
    }

    if let Some(extensions) = args.values_of("extensions") {
        for ext in extensions {
            filter.add_extension(ext).expect("bad extension");
        }
    }

    if let Some(filters) = args.values_of("filter") {
        for p in filters {
            filter.add_filter(p).expect("bad filter");
        }
    }

    if let Some(ignores) = args.values_of("ignore") {
        for i in ignores {
            filter.add_ignore(i).expect("bad ignore pattern");
        }
    }

    let (tx, rx) = channel();
    let mut watcher: RecommendedWatcher = Watcher::new(tx).expect("unable to create watcher");

    let paths = args.values_of("path").unwrap();
    for path in paths {
        match Path::new(path).canonicalize() {
            Ok(canonicalized)   => watcher.watch(canonicalized).expect("unable to watch path"),
            Err(_)              => {
                println!("invalid path: {}", path);
                return;
            }
        }
    }

    let cmd_parts: Vec<&str> = args.values_of("command").unwrap().collect();
    let cmd = cmd_parts.join(" ");
    let mut runner = Runner::new(args.is_present("restart"), args.is_present("clear"));

    if args.is_present("run-initially") {
        runner.run_command(&cmd);
    }

    loop {
        let e = wait(&rx, &filter).expect("error when waiting for filesystem changes");

        debug!("{:?}: {:?}", e.op, e.path);

        runner.run_command(&cmd);
    }
}

fn wait(rx: &Receiver<Event>, filter: &NotificationFilter) -> Result<Event, RecvError> {
    loop {
        // Block on initial notification
        let e = try!(rx.recv());
        if let Some(ref path) = e.path {
            if filter.is_excluded(path) {
                continue;
            }
        }

        // Accumulate subsequent events
        thread::sleep(time::Duration::from_millis(250));

        // Drain rx buffer and drop them
        while let Ok(_) = rx.try_recv() {
			// nothing to do here
        }

        return Ok(e);
    }
}
<|endoftext|>