<commit_before>extern crate loc;

extern crate clap;
extern crate deque;
extern crate itertools;
extern crate num_cpus;
extern crate walkdir;
extern crate regex;

use clap::{Arg, App, AppSettings};
use walkdir::WalkDir;

use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::thread;

use deque::{Stealer, Stolen};
use regex::Regex;

use loc as c;

enum Work {
    File(String),
    Quit,
}

struct Worker {
    chan: Stealer<Work>,
}

#[derive(Clone)]
struct FileCount {
    path: String,
    lang: c::Lang,
    count: c::Count,
}

// TODO(cgag): name this (lang, path, count) tuple concept and make it a struct
impl Worker {
    fn run(self) -> Vec<FileCount> {
        let mut v: Vec<FileCount> = vec![];
        loop {
            match self.chan.steal() {
                // What causes these?
                Stolen::Empty | Stolen::Abort => continue,
                Stolen::Data(Work::Quit) => break,
                Stolen::Data(Work::File(path)) => {
                    let lang = c::lang_from_ext(&path);
                    if lang != c::Lang::Unrecognized {
                        let count = c::count(&path);
                        v.push(FileCount {
                            lang: lang,
                            path: String::from(path),
                            count: count,
                        });
                    }
                }
            };
        }
        v
    }
}

fn main() {

    let matches = App::new("count")
        .global_settings(&[AppSettings::ColoredHelp])
        .version("0.1")
        .author("Curtis Gagliardi <curtis@curtis.io>")
        .about("counts things quickly hopefully")
        // TODO(cgag): actually implement filtering
        .arg(Arg::with_name("exclude")
            .required(false)
            .long("exclude")
            .value_name("REGEX")
            .takes_value(true)
            .help("comma separated list of files/directories to ignore"))
        .arg(Arg::with_name("files")
             .required(false)
             .long("files")
             .takes_value(false)
             .help("Show stats for individual files"))
        .arg(Arg::with_name("sort")
            .required(false)
            .long("sort")
            .value_name("COLUMN")
            .takes_value(true)
            .help("Column to sort by"))
        .arg(Arg::with_name("target")
            .required(true)
            .help("File or directory to count"))
        .get_matches();

    let filepaths = matches.values_of("target").unwrap();
    let sort = matches.value_of("sort").unwrap_or("language");
    let by_file = matches.is_present("files");
    let exclude_regex = match matches.value_of("exclude") {
        Some(rx_str) => {
            match Regex::new(rx_str) {
                Ok(r) => Some(r),
                Err(e) => {
                    println!("e: {}", e);
                    std::process::exit(1);
                }
            }
        }
        None => None,
    };

    let threads = num_cpus::get();
    let mut workers = vec![];
    let (workq, stealer) = deque::new();
    for _ in 0..threads {
        let worker = Worker { chan: stealer.clone() };
        workers.push(thread::spawn(|| worker.run()));
    }

    for filepath in filepaths {
        if exclude_regex.is_some() {
            let ref r = &exclude_regex.clone().unwrap();
            for entry in WalkDir::new(filepath).into_iter().filter_map(|e| e.ok()) {
                if entry.file_type().is_file() {
                    let path = entry.path().to_str().unwrap();
                    if !r.is_match(path) {
                        workq.push(Work::File(String::from(path)));
                    }
                }
            }
        } else {
            for entry in WalkDir::new(filepath).into_iter().filter_map(|e| e.ok()) {
                if entry.file_type().is_file() {
                    let path = entry.path().to_str().unwrap();
                    workq.push(Work::File(String::from(path)));
                }
            }
        }
    }

    for _ in 0..workers.len() {
        workq.push(Work::Quit);
    }

    let mut counts: Vec<FileCount> = Vec::new();
    for worker in workers {
        counts.extend(worker.join().unwrap().iter().cloned())
    }

    let mut lang_counts_by_file: HashMap<c::Lang, Vec<(String, c::Count)>> = HashMap::new();
    for FileCount { lang, path, count } in counts {
        match lang_counts_by_file.entry(lang) {
            Entry::Occupied(mut lang_counts_by_file) => {
                lang_counts_by_file.get_mut().push((path, count))
            }
            Entry::Vacant(lang_counts_by_file) => {
                lang_counts_by_file.insert(vec![(path, count)]);
            }
        };
    }

    // TODO(cgag): string repeat function?
    let linesep = "---------------------------------------------------------------------------------";

    if by_file {
        // TODO(cgag): Need sorting for by_file as well.

        println!("{}", linesep);
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 "Language",
                 "Files",
                 "Lines",
                 "Blank",
                 "Comment",
                 "Code");
        println!("{}", linesep);

        for (lang, count_vec) in lang_counts_by_file {
            let mut total = c::Count::default();
            for &(_, ref count) in &count_vec {
                total.merge(count);
            }
            println!("{}", linesep);
            println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                     lang,
                     count_vec.len(),
                     total.lines,
                     total.blank,
                     total.comment,
                     total.code);
            println!("{}", lang);
            println!("{}", linesep);
            for (path, count) in count_vec {
                // TODO(cgag): grab last-n-chars fn from hostblock
                let mut path_tail = String::from(path);
                if path_tail.len() > 25 {
                    path_tail = path_tail.chars().skip(path_tail.len() - 25).collect::<String>();
                }
                println!("|{0: <25} {1: >12} {2: >12} {3: >12} {4: >12}",
                         path_tail,
                         count.lines,
                         count.blank,
                         count.comment,
                         count.code);
            }
        }
    } else {
        let mut lang_totals: HashMap<&c::Lang, c::LangTotal> = HashMap::new();
        for (lang, count_vec) in &lang_counts_by_file {
            let mut lang_total: c::Count = Default::default();
            for &(_, ref count) in count_vec {
                lang_total.merge(count);
            }
            lang_totals.insert(lang,
                               c::LangTotal {
                                   files: count_vec.len() as u32,
                                   count: lang_total,
                               });
        }

        let mut totals_by_lang = lang_totals.iter().collect::<Vec<(&&c::Lang, &c::LangTotal)>>();
        match sort {
            "language" => totals_by_lang.sort_by(|&(l1, _), &(l2, _)| l1.to_s().cmp(&l2.to_s())),
            "files" => totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.files.cmp(&c1.files)),
            "code" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.code.cmp(&c1.count.code))
            }
            "comment" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.comment.cmp(&c1.count.comment))
            }
            "blank" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.blank.cmp(&c1.count.blank))
            }
            "lines" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.lines.cmp(&c1.count.lines))
            }
            _ => {
                println!("invalid sort option {}, sorting by language", sort);
                totals_by_lang.sort_by(|&(l1, _), &(l2, _)| l1.to_s().cmp(&l2.to_s()))
            }
        }

        let mut totals = c::LangTotal {
            files: 0,
            count: c::Count::default(),
        };
        for &(_, total) in &totals_by_lang {
            totals.files += total.files;
            totals.count.code += total.count.code;
            totals.count.blank += total.count.blank;
            totals.count.comment += total.count.comment;
            totals.count.lines += total.count.lines;
        }

        println!("{}", linesep);
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 "Language",
                 "Files",
                 "Lines",
                 "Blank",
                 "Comment",
                 "Code");
        println!("{}", linesep);

        for &(lang, total) in &totals_by_lang {
            println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                     lang,
                     total.files,
                     total.count.lines,
                     total.count.blank,
                     total.count.comment,
                     total.count.code);
        }

        println!("{}", linesep);
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 "Total",
                 totals.files,
                 totals.count.lines,
                 totals.count.blank,
                 totals.count.comment,
                 totals.count.code);
        println!("{}", linesep);
    }
}
<commit_msg>improve regex error messaging<commit_after>extern crate loc;

extern crate clap;
extern crate deque;
extern crate itertools;
extern crate num_cpus;
extern crate walkdir;
extern crate regex;

use clap::{Arg, App, AppSettings};
use walkdir::WalkDir;

use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::thread;

use deque::{Stealer, Stolen};
use regex::Regex;

use loc as c;

enum Work {
    File(String),
    Quit,
}

struct Worker {
    chan: Stealer<Work>,
}

#[derive(Clone)]
struct FileCount {
    path: String,
    lang: c::Lang,
    count: c::Count,
}

// TODO(cgag): name this (lang, path, count) tuple concept and make it a struct
impl Worker {
    fn run(self) -> Vec<FileCount> {
        let mut v: Vec<FileCount> = vec![];
        loop {
            match self.chan.steal() {
                // What causes these?
                Stolen::Empty | Stolen::Abort => continue,
                Stolen::Data(Work::Quit) => break,
                Stolen::Data(Work::File(path)) => {
                    let lang = c::lang_from_ext(&path);
                    if lang != c::Lang::Unrecognized {
                        let count = c::count(&path);
                        v.push(FileCount {
                            lang: lang,
                            path: String::from(path),
                            count: count,
                        });
                    }
                }
            };
        }
        v
    }
}

fn main() {

    let matches = App::new("count")
        .global_settings(&[AppSettings::ColoredHelp])
        .version("0.1")
        .author("Curtis Gagliardi <curtis@curtis.io>")
        .about("counts things quickly hopefully")
        // TODO(cgag): actually implement filtering
        .arg(Arg::with_name("exclude")
            .required(false)
            .long("exclude")
            .value_name("REGEX")
            .takes_value(true)
            .help("comma separated list of files/directories to ignore"))
        .arg(Arg::with_name("files")
             .required(false)
             .long("files")
             .takes_value(false)
             .help("Show stats for individual files"))
        .arg(Arg::with_name("sort")
            .required(false)
            .long("sort")
            .value_name("COLUMN")
            .takes_value(true)
            .help("Column to sort by"))
        .arg(Arg::with_name("target")
            .required(true)
            .help("File or directory to count"))
        .get_matches();

    let filepaths = matches.values_of("target").unwrap();
    let sort = matches.value_of("sort").unwrap_or("language");
    let by_file = matches.is_present("files");
    let exclude_regex = match matches.value_of("exclude") {
        Some(rx_str) => {
            match Regex::new(rx_str) {
                Ok(r) => Some(r),
                Err(e) => {
                    println!("Error processing regex: {}", e);
                    std::process::exit(1);
                }
            }
        }
        None => None,
    };

    let threads = num_cpus::get();
    let mut workers = vec![];
    let (workq, stealer) = deque::new();
    for _ in 0..threads {
        let worker = Worker { chan: stealer.clone() };
        workers.push(thread::spawn(|| worker.run()));
    }

    for filepath in filepaths {
        if exclude_regex.is_some() {
            let ref r = &exclude_regex.clone().unwrap();
            for entry in WalkDir::new(filepath).into_iter().filter_map(|e| e.ok()) {
                if entry.file_type().is_file() {
                    let path = entry.path().to_str().unwrap();
                    if !r.is_match(path) {
                        workq.push(Work::File(String::from(path)));
                    }
                }
            }
        } else {
            for entry in WalkDir::new(filepath).into_iter().filter_map(|e| e.ok()) {
                if entry.file_type().is_file() {
                    let path = entry.path().to_str().unwrap();
                    workq.push(Work::File(String::from(path)));
                }
            }
        }
    }

    for _ in 0..workers.len() {
        workq.push(Work::Quit);
    }

    let mut counts: Vec<FileCount> = Vec::new();
    for worker in workers {
        counts.extend(worker.join().unwrap().iter().cloned())
    }

    let mut lang_counts_by_file: HashMap<c::Lang, Vec<(String, c::Count)>> = HashMap::new();
    for FileCount { lang, path, count } in counts {
        match lang_counts_by_file.entry(lang) {
            Entry::Occupied(mut lang_counts_by_file) => {
                lang_counts_by_file.get_mut().push((path, count))
            }
            Entry::Vacant(lang_counts_by_file) => {
                lang_counts_by_file.insert(vec![(path, count)]);
            }
        };
    }

    // TODO(cgag): string repeat function?
    let linesep = "---------------------------------------------------------------------------------";

    if by_file {
        // TODO(cgag): Need sorting for by_file as well.
        //
        println!("{}", linesep);
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 "Language",
                 "Files",
                 "Lines",
                 "Blank",
                 "Comment",
                 "Code");
        println!("{}", linesep);

        for (lang, count_vec) in lang_counts_by_file {
            let mut total = c::Count::default();
            for &(_, ref count) in &count_vec {
                total.merge(count);
            }
            println!("{}", linesep);
            println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                     lang,
                     count_vec.len(),
                     total.lines,
                     total.blank,
                     total.comment,
                     total.code);
            println!("{}", lang);
            println!("{}", linesep);
            for (path, count) in count_vec {
                // TODO(cgag): grab last-n-chars fn from hostblock
                let mut path_tail = String::from(path);
                if path_tail.len() > 25 {
                    path_tail = path_tail.chars().skip(path_tail.len() - 25).collect::<String>();
                }
                println!("|{0: <25} {1: >12} {2: >12} {3: >12} {4: >12}",
                         path_tail,
                         count.lines,
                         count.blank,
                         count.comment,
                         count.code);
            }
        }
    } else {
        let mut lang_totals: HashMap<&c::Lang, c::LangTotal> = HashMap::new();
        for (lang, count_vec) in &lang_counts_by_file {
            let mut lang_total: c::Count = Default::default();
            for &(_, ref count) in count_vec {
                lang_total.merge(count);
            }
            lang_totals.insert(lang,
                               c::LangTotal {
                                   files: count_vec.len() as u32,
                                   count: lang_total,
                               });
        }

        let mut totals_by_lang = lang_totals.iter().collect::<Vec<(&&c::Lang, &c::LangTotal)>>();
        match sort {
            "language" => totals_by_lang.sort_by(|&(l1, _), &(l2, _)| l1.to_s().cmp(&l2.to_s())),
            "files" => totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.files.cmp(&c1.files)),
            "code" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.code.cmp(&c1.count.code))
            }
            "comment" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.comment.cmp(&c1.count.comment))
            }
            "blank" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.blank.cmp(&c1.count.blank))
            }
            "lines" => {
                totals_by_lang.sort_by(|&(_, c1), &(_, c2)| c2.count.lines.cmp(&c1.count.lines))
            }
            _ => {
                println!("invalid sort option {}, sorting by language", sort);
                totals_by_lang.sort_by(|&(l1, _), &(l2, _)| l1.to_s().cmp(&l2.to_s()))
            }
        }

        let mut totals = c::LangTotal {
            files: 0,
            count: c::Count::default(),
        };
        for &(_, total) in &totals_by_lang {
            totals.files += total.files;
            totals.count.code += total.count.code;
            totals.count.blank += total.count.blank;
            totals.count.comment += total.count.comment;
            totals.count.lines += total.count.lines;
        }

        println!("{}", linesep);
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 "Language",
                 "Files",
                 "Lines",
                 "Blank",
                 "Comment",
                 "Code");
        println!("{}", linesep);

        for &(lang, total) in &totals_by_lang {
            println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                     lang,
                     total.files,
                     total.count.lines,
                     total.count.blank,
                     total.count.comment,
                     total.count.code);
        }

        println!("{}", linesep);
        println!(" {0: <18} {1: >8} {2: >12} {3: >12} {4: >12} {5: >12}",
                 "Total",
                 totals.files,
                 totals.count.lines,
                 totals.count.blank,
                 totals.count.comment,
                 totals.count.code);
        println!("{}", linesep);
    }
}
<|endoftext|>


<commit_before>// TODO: write a description.
//! Ferrum is a ...

#![deny(non_camel_case_types)]
#![feature(plugin)]

extern crate getopts;
#[macro_use] extern crate log;
extern crate mustache;
#[plugin] extern crate peg_syntax_ext;

use std::os;

use getopts::{getopts, optopt, optflag, short_usage, usage};

mod error;
mod ferrum;
mod parser;
mod document;
mod template;
mod util;

fn main() {
    // Setup the possible opts.
    let opts = &[
        optopt("s", "source", "set source directory", "NAME"),
        optopt("d", "destination", "set destination directory", "NAME"),
        optflag("h", "help", "print this help menu")
    ];

    let instructions = "Usage: ferrum [command]";

    // Get the arguments and program name.
    let args: Vec<String> = os::args();
    let program = args[0].clone();

    // Match the opts.
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { panic!(f) }
    };

    // Check if the help opt is present.
    if matches.opt_present("h") {
        println!("{}", usage(&*program, opts));
        return;
    }

    // Retrieve the command.
    let command = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        println!("{}", short_usage(instructions, opts));
        return;
    };

    match &*command {
        "build" => ferrum::build(matches),
        _ => {
            println!("{}", short_usage(instructions, opts));
            return;
        }
    }
}
<commit_msg>Add feature gates<commit_after>#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(path)]

// TODO: write a description.
//! Ferrum is a ...

#![deny(non_camel_case_types)]
#![feature(plugin)]

extern crate getopts;
#[macro_use] extern crate log;
extern crate mustache;
#[plugin] extern crate peg_syntax_ext;

use std::os;

use getopts::{getopts, optopt, optflag, short_usage, usage};

mod error;
mod ferrum;
mod parser;
mod document;
mod template;
mod util;

fn main() {
    // Setup the possible opts.
    let opts = &[
        optopt("s", "source", "set source directory", "NAME"),
        optopt("d", "destination", "set destination directory", "NAME"),
        optflag("h", "help", "print this help menu")
    ];

    let instructions = "Usage: ferrum [command]";

    // Get the arguments and program name.
    let args: Vec<String> = os::args();
    let program = args[0].clone();

    // Match the opts.
    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { panic!(f) }
    };

    // Check if the help opt is present.
    if matches.opt_present("h") {
        println!("{}", usage(&*program, opts));
        return;
    }

    // Retrieve the command.
    let command = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        println!("{}", short_usage(instructions, opts));
        return;
    };

    match &*command {
        "build" => ferrum::build(matches),
        _ => {
            println!("{}", short_usage(instructions, opts));
            return;
        }
    }
}
<|endoftext|>


<commit_before>/// A genetic algorithm in Rust
/// Copyright (C) 2015  Andrew Schwartzmeyer

#[macro_use]
extern crate clap;
extern crate rand;
extern crate time;

use clap::App;

mod algorithm;
mod individual;
mod problem;

arg_enum!{
    #[derive(Debug, PartialEq, Eq, Copy, Clone)]
    pub enum Problem {
        Ackley,
        Schwefel
    }
}

/// Setup and run algorithm to search for solution
fn main() {
    let matches = App::new("rust-genetic-algorithm")
        .version(&crate_version!()[..])
        .author("Andrew Schwartzmeyer <andrew@schwartzmeyer.com")
        .about("A genetic algorithm in Rust for Schwefel's function.")
        .args_from_usage(
            "[problem]... 'The problem to solve'
             -d --dimension [30] 'Sets the dimension of the hypercube'
             -p --population [256] 'Sets the size of the population'
             -i --iterations [5000] 'Sets maximum number of generations'
             [verbose]... -v 'Print fitness (1) and solution (2) every 10th generation'")
        .get_matches();
    let problems = value_t!(matches.values_of("problem"), Problem)
        .unwrap_or(vec![Problem::Schwefel, Problem::Ackley]);
    let dimension = value_t!(matches.value_of("d"), usize).unwrap_or(30);
    let population = value_t!(matches.value_of("p"), usize).unwrap_or(256);
    let iterations = value_t!(matches.value_of("i"), usize).unwrap_or(5000);
    let verbosity = matches.occurrences_of("verbose") as usize;

    for problem in problems {
        algorithm::search(problem, 0.05_f64, dimension, population, iterations, verbosity)
    }
}
<commit_msg>Specify convergence tolerance with CLI<commit_after>/// A genetic algorithm in Rust
/// Copyright (C) 2015  Andrew Schwartzmeyer

#[macro_use]
extern crate clap;
extern crate rand;
extern crate time;

use clap::App;

mod algorithm;
mod individual;
mod problem;

arg_enum!{
    #[derive(Debug, PartialEq, Eq, Copy, Clone)]
    pub enum Problem {
        Ackley,
        Schwefel
    }
}

/// Setup and run algorithm to search for solution
fn main() {
    let matches = App::new("rust-genetic-algorithm")
        .version(&crate_version!()[..])
        .author("Andrew Schwartzmeyer <andrew@schwartzmeyer.com")
        .about("A genetic algorithm in Rust for Schwefel's function.")
        .args_from_usage(
            "[problem]... 'The problem to solve'
             -t --tolerance [0.05] 'Sets the convergence tolerance'
             -d --dimension [30] 'Sets the dimension of the hypercube'
             -p --population [256] 'Sets the size of the population'
             -i --iterations [5000] 'Sets maximum number of generations'
             [verbose]... -v 'Print fitness (1) and solution (2) every 10th generation'")
        .get_matches();
    let problems = value_t!(matches.values_of("problem"), Problem)
        .unwrap_or(vec![Problem::Schwefel, Problem::Ackley]);
    let tolerance = value_t!(matches.value_of("t"), f64).unwrap_or(0.05_f64);
    let dimension = value_t!(matches.value_of("d"), usize).unwrap_or(30);
    let population = value_t!(matches.value_of("p"), usize).unwrap_or(256);
    let iterations = value_t!(matches.value_of("i"), usize).unwrap_or(5000);
    let verbosity = matches.occurrences_of("verbose") as usize;

    for problem in problems {
        algorithm::search(problem, tolerance, dimension, population, iterations, verbosity)
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
mod ast;
#[macro_use]
extern crate nom;
extern crate regex;
// TOML
// TODO: toml
// TODO: expression

// Newline
named!(newline<&str, &str>, alt!(tag_s!("\n") | tag_s!("\r\n")));

named!(newlines<&str, Vec<&str> >, many1!(newline));

// Whitespace
fn is_space(chr: char) -> bool {
    chr as u32 == 0x20 || chr as u32 == 0x09
}

named!(ws<&str, &str>, take_while_s!(is_space));

// Comment
fn not_eol(chr: char) -> bool {
  chr as u32 == 0x09 || (chr as u32 >= 0x20 && chr as u32 <=0x10FFF)
}

named!(comment<&str, ast::Comment>,
       chain!(
              tag_s!("#") ~
 comment_txt: take_while_s!(not_eol),
              || {ast::Comment{text: comment_txt}}
             )
      );

// Key-Value pairs
fn is_keychar(chr: char) -> bool {
  let uchr = chr as u32;
  uchr >= 0x41 && uchr <= 0x5A || // A-Z
  uchr >= 0x61 && uchr <= 0x7A || // A-Z
  uchr >= 0x30 && uchr <= 0x39 || // 0-9
  uchr == 0x2D || uchr == 0x5f // "-", "_"
}

// named!(basic_unescaped<&str, &str>, re_match!(r" |!|[#-\[]|[\]-]"));
// named!(escaped<&str, &str>, re_match!("(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(u[0-9A-Z]{4})|(U[0-9A-Z]{8})"));
// named!(basic_char<&str, &str>, alt!(basic_unescaped | escaped));
named!(unquoted_key<&str, &str>, take_while1_s!(is_keychar));
named!(quoted_key<&str, &str>, re_find!("\"( |!|[#-\\[]|[\\]-]|(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\\\u[0-9A-Z]{4})|(\\\\U[0-9A-Z]{8})){1,}\""));

named!(key<&str, &str>, alt!(unquoted_key | quoted_key));
named!(keyval_sep<&str, ast::WSSep>,
       chain!(
         ws1: ws ~
              tag_s!("=") ~
         ws2: ws,
              || {ast::WSSep{ws1: ws1, ws2: ws2}}
             )
      );
// TODO: named!(val<&str, &str>, ...);
// TODO: named!(keyval<&str, ast::KeyVal>, ...);

// Standard Table
named!(table_sub_key<&str, ast::WSKeySep>,
       chain!(
         ws1: ws ~
              tag_s!(".") ~
         ws2: ws ~
         key: key,
              || {ast::WSKeySep{ws: ast::WSSep{ws1: ws1, ws2: ws2}, key: key}}
             )
      );
named!(table_sub_keys<&str, Vec<ast::WSKeySep> >, many0!(table_sub_key));
named!(std_table<&str, ast::Table>,
       chain!(
              tag_s!("[") ~
         ws1: ws ~
         key: key ~
     subkeys: table_sub_keys ~
         ws2: ws ~
              tag_s!("]"),
              || {ast::Table{ttype: ast::TableType::Standard,
                             ws: ast::WSSep{ws1: ws1, ws2: ws2},
                             key: key, subkeys: subkeys}}
             )
      );

// Array Table
named!(array_table<&str, ast::Table>,
       chain!(
              tag_s!("[[") ~
         ws1: ws ~
         key: key ~
     subkeys: table_sub_keys ~
         ws2: ws ~
              tag_s!("]]"),
              || {ast::Table{ttype: ast::TableType::Array,
                             ws: ast::WSSep{ws1: ws1, ws2: ws2},
                             key: key, subkeys: subkeys}}
             )
      );

// Integer
named!(integer<&str, &str>, re_find!("(\\+|-)?([1-9](\\d|(_\\d))+|\\d)"));

// Float
named!(float<&str, &str>,
       re_find!("(\\+|-)?([1-9](\\d|(_\\d))+|\\d)((\\.\\d(\\d|(_\\d))*)((e|E)(\\+|-)?([1-9](\\d|(_\\d))+|\\d))|(\\.\\d(\\d|(_\\d))*)|((e|E)(\\+|-)?([1-9](\\d|(_\\d))+|\\d)))"));

// String
// TODO: named!(string<&str, &str>, alt!(basic_string | ml_basic_string | literal_string | ml_literal_string));

// Basic String
named!(basic_string<&str, &str>,
       re_find!("\"( |!|[#-\\[]|[\\]-]|(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\\\u[0-9A-Z]{4})|(\\\\U[0-9A-Z]{8})){0,}\""));

// Multiline Basic String
named!(ml_basic_string<&str, &str>,
       re_find!("\"\"\"([ -\\[]|[\\]-]|(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\\\u[0-9A-Z]{4})|(\\\\U[0-9A-Z]{8})|\n|(\r\n)|(\\\\(\n|(\r\n))))*\"\"\""));

fn main() {
    let s = r#""""
             HOH\\nA#[]
             """"#;
    let r = ml_basic_string(s);
    println!("{:?}", r);
}<commit_msg>Added literal strings and started multi-line literal strings.<commit_after>#![allow(dead_code)]
mod ast;
#[macro_use]
extern crate nom;
extern crate regex;
// TOML
// TODO: toml
// TODO: expression

// Newline
named!(newline<&str, &str>, alt!(tag_s!("\n") | tag_s!("\r\n")));

named!(newlines<&str, Vec<&str> >, many1!(newline));

// Whitespace
fn is_space(chr: char) -> bool {
    chr as u32 == 0x20 || chr as u32 == 0x09
}

named!(ws<&str, &str>, take_while_s!(is_space));

// Comment
fn not_eol(chr: char) -> bool {
  chr as u32 == 0x09 || (chr as u32 >= 0x20 && chr as u32 <=0x10FFF)
}

named!(comment<&str, ast::Comment>,
       chain!(
              tag_s!("#") ~
 comment_txt: take_while_s!(not_eol),
              || {ast::Comment{text: comment_txt}}
             )
      );

// Key-Value pairs
fn is_keychar(chr: char) -> bool {
  let uchr = chr as u32;
  uchr >= 0x41 && uchr <= 0x5A || // A-Z
  uchr >= 0x61 && uchr <= 0x7A || // A-Z
  uchr >= 0x30 && uchr <= 0x39 || // 0-9
  uchr == 0x2D || uchr == 0x5f // "-", "_"
}

// named!(basic_unescaped<&str, &str>, re_match!(r" |!|[#-\[]|[\]-]"));
// named!(escaped<&str, &str>, re_match!("(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(u[0-9A-Z]{4})|(U[0-9A-Z]{8})"));
// named!(basic_char<&str, &str>, alt!(basic_unescaped | escaped));
named!(unquoted_key<&str, &str>, take_while1_s!(is_keychar));
named!(quoted_key<&str, &str>, re_find!("\"( |!|[#-\\[]|[\\]-]|(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\\\u[0-9A-Z]{4})|(\\\\U[0-9A-Z]{8})){1,}\""));

named!(key<&str, &str>, alt!(unquoted_key | quoted_key));
named!(keyval_sep<&str, ast::WSSep>,
       chain!(
         ws1: ws ~
              tag_s!("=") ~
         ws2: ws,
              || {ast::WSSep{ws1: ws1, ws2: ws2}}
             )
      );
// TODO: named!(val<&str, &str>, ...);
// TODO: named!(keyval<&str, ast::KeyVal>, ...);

// Standard Table
named!(table_sub_key<&str, ast::WSKeySep>,
       chain!(
         ws1: ws ~
              tag_s!(".") ~
         ws2: ws ~
         key: key,
              || {ast::WSKeySep{ws: ast::WSSep{ws1: ws1, ws2: ws2}, key: key}}
             )
      );
named!(table_sub_keys<&str, Vec<ast::WSKeySep> >, many0!(table_sub_key));
named!(std_table<&str, ast::Table>,
       chain!(
              tag_s!("[") ~
         ws1: ws ~
         key: key ~
     subkeys: table_sub_keys ~
         ws2: ws ~
              tag_s!("]"),
              || {ast::Table{ttype: ast::TableType::Standard,
                             ws: ast::WSSep{ws1: ws1, ws2: ws2},
                             key: key, subkeys: subkeys}}
             )
      );

// Array Table
named!(array_table<&str, ast::Table>,
       chain!(
              tag_s!("[[") ~
         ws1: ws ~
         key: key ~
     subkeys: table_sub_keys ~
         ws2: ws ~
              tag_s!("]]"),
              || {ast::Table{ttype: ast::TableType::Array,
                             ws: ast::WSSep{ws1: ws1, ws2: ws2},
                             key: key, subkeys: subkeys}}
             )
      );

// Integer
named!(integer<&str, &str>, re_find!("(\\+|-)?([1-9](\\d|(_\\d))+|\\d)"));

// Float
named!(float<&str, &str>,
       re_find!("(\\+|-)?([1-9](\\d|(_\\d))+|\\d)((\\.\\d(\\d|(_\\d))*)((e|E)(\\+|-)?([1-9](\\d|(_\\d))+|\\d))|(\\.\\d(\\d|(_\\d))*)|((e|E)(\\+|-)?([1-9](\\d|(_\\d))+|\\d)))"));

// String
// TODO: named!(string<&str, &str>, alt!(basic_string | ml_basic_string | literal_string | ml_literal_string));

// Basic String
named!(basic_string<&str, &str>,
       re_find!("\"( |!|[#-\\[]|[\\]-]|(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\\\u[0-9A-Z]{4})|(\\\\U[0-9A-Z]{8})){0,}\""));

// Multiline Basic String
named!(ml_basic_string<&str, &str>,
       re_find!("\"\"\"([ -\\[]|[\\]-]|(\\\\\")|(\\\\)|(\\\\/)|(\\b)|(\\f)|(\\n)|(\\r)|(\\t)|(\\\\u[0-9A-Z]{4})|(\\\\U[0-9A-Z]{8})|\n|(\r\n)|(\\\\(\n|(\r\n))))*\"\"\""));

// Literal String
named!(literal_string<&str, &str>,
       re_find!("'(	|[ -&]|[\\(-])*'"));

//Multiline Literal String
// TODO: finish this function
named!(ml_literal_string<&str, &str>,
	   re_find("'''(	|)*'''"));
fn main() {
    let s = r#""""
             HOH\\nA#[]
             """"#;
    let r = ml_basic_string(s);
    println!("{:?}", r);
}

#[cfg(test)]
mod test {
	use nom::IResult::{Done};
	use ::literal_string;
	#[test]
	fn test_literal_string() {
		assert_eq!(literal_string("'Abc џ'"), Done("", "'Abc џ'"));
	}
}<|endoftext|>


<commit_before>#![allow(unstable, dead_code)]

extern crate libc;

mod args;
mod ansi;
mod matching;
mod screen;

use std::os;
use std::io;
use std::cmp::min;
use screen::Screen;
use screen::Key::*;

fn main() {
  let args = match args::parse_args() {
    Some(args) => args,
    None => {
      os::set_exit_status(1);
      return;
    },
  };

  if args.help { return; }

  let choices = read_choices();
  let initial_search = args.initial_search.clone();
  if args.use_first {
    let matches = matching::compute_matches(&choices, initial_search.as_slice());
    println!("{}", matches[0]);
    return;
  } else {
    event_loop(choices, initial_search.as_slice());
  }
}

fn event_loop(choices: Vec<String>, initial_search: &str) {
  let mut screen = Screen::open_screen();
  let mut index = 0;

  let mut search = Search {
    query: initial_search.to_string(),
    matches: Vec::new(),
    stale: true,
  };
  loop {
    if search.stale {
      search.matches = matching::compute_matches(&choices, search.query.as_slice());
      search.stale = false;
    }

    draw_screen(&mut screen, &search.matches, search.query.as_slice(), choices.len(), index);

    let chars = screen.get_buffered_keys();
    for char in chars.iter() {
      match *char {
        Char(x) => {
          search.query.push(x);
          index = 0;
          search.stale = true;
        }
        Backspace => { search.backspace(); }
        Control('h') => { search.backspace(); }
        Control('u') => { search.clear_query(); }
        Control('c') => { return; }
        Control('n') => { index = min(index + 1, min(screen.visible_choices as usize - 1, search.matches.len() - 1)); }
        Control('p') => { index = if index == 0 { 0 } else { index - 1 }; }
        Enter => {
          screen.move_cursor_to_bottom();
          if search.stale {
            search.matches = matching::compute_matches(&choices, search.query.as_slice());
          }
          println!("{}", search.matches[index]);
          return;
        }
        _ => panic!("Unexpected input"),
      }
    }
  }
}

struct Search<'a> {
  query: String,
  matches: Vec<&'a String>,
  stale: bool,
}

impl<'a> Search<'a> {
  fn backspace(&mut self) {
    self.query.pop();
    self.stale = true;
  }

  fn clear_query(&mut self) {
    self.query.clear();
    self.stale = true;
  }
}

fn draw_screen(screen: &mut Screen, matches: &Vec<&String>, search: &str, choices: usize, index: usize) {
  screen.hide_cursor();
  screen.blank_screen();
  screen.write(format!("> {} ({} choices)\n", search, choices).as_slice());

  print_matches(screen, matches, index);

  let start = screen.start_line;
  screen.move_cursor(start, 2 + search.len() as u16);
  screen.show_cursor();
}

fn print_matches(screen: &mut Screen, matches: &Vec<&String>, index: usize) {
  let mut i = 1;
  for choice in matches.iter() {
    if i == index + 1 {
      screen.write_inverted(choice.as_slice());
    } else {
      screen.write(choice.as_slice());
    }
    if i >= screen.visible_choices as usize {
      return;
    } else {
      screen.write("\n");
    }
    i += 1;
  }
}

fn read_choices() -> Vec<String> {
  let mut stdin = io::stdio::stdin();
  let mut lines = Vec::new();

  while let Ok(mut s) = stdin.read_line() {
    trim(&mut s);
    lines.push(s);
  }

  lines
}

fn trim(s: &mut String) {
  while let Some(x) = s.pop() {
    if x != '\n' {
      s.push(x);
      return;
    }
  }
}
<commit_msg>Move recompute_matches to Search<commit_after>#![allow(unstable, dead_code)]

extern crate libc;

mod args;
mod ansi;
mod matching;
mod screen;

use std::os;
use std::io;
use std::cmp::min;
use screen::Screen;
use screen::Key::*;

fn main() {
  let args = match args::parse_args() {
    Some(args) => args,
    None => {
      os::set_exit_status(1);
      return;
    },
  };

  if args.help { return; }

  let choices = read_choices();
  let initial_search = args.initial_search.clone();
  if args.use_first {
    let matches = matching::compute_matches(&choices, initial_search.as_slice());
    println!("{}", matches[0]);
    return;
  } else {
    event_loop(choices, initial_search.as_slice());
  }
}

fn event_loop(choices: Vec<String>, initial_search: &str) {
  let mut screen = Screen::open_screen();
  let mut index = 0;

  let mut search = Search {
    choices: &choices,
    query: initial_search.to_string(),
    matches: Vec::new(),
    stale: true,
  };
  loop {
    search.recompute_matches();
    draw_screen(&mut screen, &search.matches, search.query.as_slice(), search.choices.len(), index);

    let chars = screen.get_buffered_keys();
    for char in chars.iter() {
      match *char {
        Char(x) => {
          search.query.push(x);
          index = 0;
          search.stale = true;
        }
        Backspace => { search.backspace(); }
        Control('h') => { search.backspace(); }
        Control('u') => { search.clear_query(); }
        Control('c') => { return; }
        Control('n') => { index = min(index + 1, min(screen.visible_choices as usize - 1, search.matches.len() - 1)); }
        Control('p') => { index = if index == 0 { 0 } else { index - 1 }; }
        Enter => {
          screen.move_cursor_to_bottom();
          search.recompute_matches();
          println!("{}", search.matches[index]);
          return;
        }
        _ => panic!("Unexpected input"),
      }
    }
  }
}

struct Search<'a> {
  choices: &'a Vec<String>,
  query: String,
  matches: Vec<&'a String>,
  stale: bool,
}

impl<'a> Search<'a> {
  fn backspace(&mut self) {
    self.query.pop();
    self.stale = true;
  }

  fn clear_query(&mut self) {
    self.query.clear();
    self.stale = true;
  }

  fn recompute_matches(&mut self) {
    if self.stale {
      self.matches = matching::compute_matches(self.choices, self.query.as_slice());
      self.stale = false;
    }
  }
}

fn draw_screen(screen: &mut Screen, matches: &Vec<&String>, search: &str, choices: usize, index: usize) {
  screen.hide_cursor();
  screen.blank_screen();
  screen.write(format!("> {} ({} choices)\n", search, choices).as_slice());

  print_matches(screen, matches, index);

  let start = screen.start_line;
  screen.move_cursor(start, 2 + search.len() as u16);
  screen.show_cursor();
}

fn print_matches(screen: &mut Screen, matches: &Vec<&String>, index: usize) {
  let mut i = 1;
  for choice in matches.iter() {
    if i == index + 1 {
      screen.write_inverted(choice.as_slice());
    } else {
      screen.write(choice.as_slice());
    }
    if i >= screen.visible_choices as usize {
      return;
    } else {
      screen.write("\n");
    }
    i += 1;
  }
}

fn read_choices() -> Vec<String> {
  let mut stdin = io::stdio::stdin();
  let mut lines = Vec::new();

  while let Ok(mut s) = stdin.read_line() {
    trim(&mut s);
    lines.push(s);
  }

  lines
}

fn trim(s: &mut String) {
  while let Some(x) = s.pop() {
    if x != '\n' {
      s.push(x);
      return;
    }
  }
}
<|endoftext|>


<commit_before>#![feature(custom_derive)]

extern crate hyper;
extern crate rustc_serialize;

use std::fs;
use std::path::Path;
use std::fs::File;
use std::io::{Read, Write};
use std::collections::{HashSet, HashMap};

use hyper::client::{Client, Response, RequestBuilder};
use hyper::header::{Accept, Connection, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};

use rustc_serialize::json;

struct MyClient {
    client : Client,
    app_id : String,
    app_key : String,
    cache_dir : String,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct Line {
    id : String,
    name : String,
    modeName : String,
    routeSections : Vec<RouteSection>
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct RouteSection {
    name : String,
    direction : String,
    originator : String,
    destination : String,
    timetable : Option<TimeTable>,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct Interval {
    stopId : String,
    timeToArrival: f64,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct StationInterval {
    id : i64,
    intervals : Vec<Interval>
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct KnownJourney {
    intervalId : i64,
    hour : String,
    minute : String,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct Schedule {
    name : String,
    knownJourneys : Vec<KnownJourney>,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct TimeTable {
    stationIntervals : Vec<StationInterval>,
    schedules : Vec<Schedule>,
}

#[derive(Debug, RustcEncodeable, RustcDecodable)]
struct RoutesTimeTables {
    routes : Vec<TimeTable>,
}

#[derive(Debug, RustcEncodeable, RustcDecodable)]
struct TimeTableResponse {
    timetable : RoutesTimeTables,
}

impl MyClient {
    fn new() -> MyClient {
        let cachePath : &Path = Path::new("./cache");
        fs::create_dir(cachePath);
        return MyClient{
            client : Client::new(),
            app_id : String::new(),
            app_key : String::new(),
            cache_dir : String::from("./cache"),
        }
    }

    fn get(&mut self, endpoint : &str) -> String {
        match self.cache_get(endpoint) {
            Some(body) => body,
            None => self.remote_get(endpoint)
        }
    }

    fn remote_get(&mut self, endpoint : &str) -> String {
        let req_uri = format!("https://api.tfl.gov.uk{}?app_id={}&app_key={}", endpoint, self.app_id, self.app_key);
        let mut body = String::new();
        let mut resp = self.client.get(&req_uri)
            .header(Accept(vec![
                qitem(Mime(TopLevel::Application,
                    SubLevel::Ext("json".to_owned()), vec![])),
            ]))
            .send().unwrap();
        resp.read_to_string(&mut body).unwrap();
        self.cache_put(endpoint, body)
    }

    fn cache_fname(&mut self, endpoint : &str) -> String {
        let fname = String::from(endpoint);
        let fname0 = fname.replace("/", "_");
        self.cache_dir.clone() + "/" + &fname0
    }

    fn cache_put(&mut self, endpoint : &str, body : String) -> String {
        let mut f = File::create(self.cache_fname(endpoint)).unwrap();
        f.write_all(body.as_bytes());
        body
    }

    fn cache_get(&mut self, endpoint : &str) -> Option<String> {
        let mut body = String::new();
        match File::open(self.cache_fname(endpoint)) {
            Ok(ref mut f) => {
                f.read_to_string(&mut body);
                Some(body)
            },
            Err(_) => None,
        }
    }
}

fn get_lines(client : &mut MyClient) -> Vec<Line> {
    let body = client.get("/line/route");
    json::decode(&body).unwrap()
}

fn get_timetable(client : &mut MyClient, line_id : &str, originator: &str, destination : &str) -> Option<TimeTable> {
    let req_uri = format!("/line/{}/timetable/{}/to/{}", line_id, originator, destination);
    let body = client.get(&req_uri);
    match json::decode::<TimeTableResponse>(&body) {
        Ok(ttresp) => Some(ttresp.timetable.routes[0].clone()),
        Err(_) => None,
    }
}

fn main() {
    let mut line_names : HashSet<String> = HashSet::new();
    let mut route_section_names : HashSet<String> = HashSet::new();
    let mut client = MyClient::new();
    let mut lines = get_lines(&mut client);
    for line in &mut lines {
        let line_known = line_names.contains(&line.name);
        println!("{}, Duplicate: {}:", line.name, line_known);
        line_names.insert(line.name.clone());
        for routeSection in &mut line.routeSections {
            let route_section_known = route_section_names.contains(&routeSection.name);
            println!("\t{}, Duplicate: {}", routeSection.name, route_section_known);
            route_section_names.insert(routeSection.name.clone());
            routeSection.timetable = get_timetable(&mut client, &line.id, &routeSection.originator, &routeSection.destination);
        }
    }
}
<commit_msg>Threaded http data retrieval<commit_after>#![feature(custom_derive)]

extern crate hyper;
extern crate rustc_serialize;
extern crate scoped_threadpool;

use std::fs;
use std::path::Path;
use std::fs::File;
use std::io::{Read, Write};
use std::collections::{HashSet, HashMap};

use hyper::client::{Client, Response, RequestBuilder};
use hyper::header::{Accept, Connection, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};

use rustc_serialize::json;

use scoped_threadpool::Pool;

struct MyClient {
    client : Client,
    app_id : String,
    app_key : String,
    cache_dir : String,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct Line {
    id : String,
    name : String,
    modeName : String,
    routeSections : Vec<RouteSection>
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct RouteSection {
    name : String,
    direction : String,
    originator : String,
    destination : String,
    timetable : Option<TimeTable>,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct Interval {
    stopId : String,
    timeToArrival: f64,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct StationInterval {
    id : i64,
    intervals : Vec<Interval>
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct KnownJourney {
    intervalId : i64,
    hour : String,
    minute : String,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct Schedule {
    name : String,
    knownJourneys : Vec<KnownJourney>,
}

#[derive(Clone, Debug, RustcEncodeable, RustcDecodable)]
struct TimeTable {
    stationIntervals : Vec<StationInterval>,
    schedules : Vec<Schedule>,
}

#[derive(Debug, RustcEncodeable, RustcDecodable)]
struct RoutesTimeTables {
    routes : Vec<TimeTable>,
}

#[derive(Debug, RustcEncodeable, RustcDecodable)]
struct TimeTableResponse {
    timetable : RoutesTimeTables,
}

impl MyClient {
    fn new() -> MyClient {
        let cachePath : &Path = Path::new("./cache");
        fs::create_dir(cachePath);
        return MyClient{
            client : Client::new(),
            app_id : String::new(),
            app_key : String::new(),
            cache_dir : String::from("./cache"),
        }
    }

    fn get(&mut self, endpoint : &str) -> String {
        match self.cache_get(endpoint) {
            Some(body) => body,
            None => self.remote_get(endpoint)
        }
    }

    fn remote_get(&mut self, endpoint : &str) -> String {
        let req_uri = format!("https://api.tfl.gov.uk{}?app_id={}&app_key={}", endpoint, self.app_id, self.app_key);
        let mut body = String::new();
        let mut resp = self.client.get(&req_uri)
            .header(Accept(vec![
                qitem(Mime(TopLevel::Application,
                    SubLevel::Ext("json".to_owned()), vec![])),
            ]))
            .send().unwrap();
        resp.read_to_string(&mut body).unwrap();
        self.cache_put(endpoint, body)
    }

    fn cache_fname(&mut self, endpoint : &str) -> String {
        let fname = String::from(endpoint);
        let fname0 = fname.replace("/", "_");
        self.cache_dir.clone() + "/" + &fname0
    }

    fn cache_put(&mut self, endpoint : &str, body : String) -> String {
        let mut f = File::create(self.cache_fname(endpoint)).unwrap();
        f.write_all(body.as_bytes());
        body
    }

    fn cache_get(&mut self, endpoint : &str) -> Option<String> {
        let mut body = String::new();
        match File::open(self.cache_fname(endpoint)) {
            Ok(ref mut f) => {
                f.read_to_string(&mut body);
                Some(body)
            },
            Err(_) => None,
        }
    }
}

fn get_lines(client : &mut MyClient) -> Vec<Line> {
    let body = client.get("/line/route");
    json::decode(&body).unwrap()
}

fn get_timetable(client : &mut MyClient, line_id : &str, originator: &str, destination : &str) -> Option<TimeTable> {
    let req_uri = format!("/line/{}/timetable/{}/to/{}", line_id, originator, destination);
    let body = client.get(&req_uri);
    match json::decode::<TimeTableResponse>(&body) {
        Ok(ttresp) => Some(ttresp.timetable.routes[0].clone()),
        Err(_) => None,
    }
}

fn route_section_id(line : &Line, section : &RouteSection) -> String {
    return line.id.clone() + " " + &section.originator + " to " + &section.destination;
}

fn main() {
    // Fetch data
    let mut client = MyClient::new();
    let mut lines = get_lines(&mut client);
    let mut pool = Pool::new(10);

    pool.scoped(|scope| {
        for line in &mut lines {
            scope.execute(move || {
                let mut client = MyClient::new();
                for route_section in &mut line.routeSections {
                    println!("Getting Timetable for Line: {}, Route Section: {} ...", line.name, route_section.name);
                    route_section.timetable = get_timetable(&mut client, &line.id, &route_section.originator, &route_section.destination);
                }
            });
        }
    });

    // Generate a report
    let mut line_ids : HashSet<String> = HashSet::new();
    let mut route_section_ids: HashSet<String> = HashSet::new();
    for line in &lines {
        println!("{}, Duplicate: {}", line.id, line_ids.contains(&line.id));
        for route_section in &line.routeSections {
            let id = route_section_id(&line, &route_section);
            println!("\t{}, Duplicate: {}", id, route_section_ids.contains(&id));
            route_section_ids.insert(id.clone());
        }
        line_ids.insert(line.id.clone());
    }

    // Generate CSV files from fetched data

}
<|endoftext|>


<commit_before>#![warn(clippy::all)]

use avsser::input::determine_input_type;
use avsser::input::get_list_of_files;
use avsser::output::*;
use clap::App;
use clap::Arg;
use clap::ArgMatches;
use std::path::Path;

fn main() {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::with_name("input").help("the input file to generate a script for").required(true).index(1))
        .arg(Arg::with_name("subtitle")
            .short("s")
            .long("subtitle")
            .help("include subtitles with TextSub(input_filename.ass)"))
        .arg(Arg::with_name("sub-extract").short("S").long("sub-extract").help("extract subtitles from the input files (defaults to track 0)"))
        .arg(Arg::with_name("sub-track").short("T").long("sub-track").help("select which subtitle track to extract, 0-indexed (does nothing without -S)")
            .takes_value(true).value_name("TRACK"))
        .arg(Arg::with_name("audio").short("a").long("audio").help("include audio from video"))
        .arg(Arg::with_name("audio-ext").short("A").long("audio-ext").help("include audio from separate file with specified extension (takes precedence over audio \
         from video)").takes_value(true).value_name("EXT"))
        .arg(Arg::with_name("fonts").short("f").long("fonts").help("extract fonts from mkv container"))
        .arg(Arg::with_name("resize").short("R").long("resize").help("resize video to the given width and height").takes_value(true).value_name("W,H"))
        .arg(Arg::with_name("filters").short("F").long("filters").help("use a custom filter chain instead of RemoveGrain(1)"))
        .arg(Arg::with_name("keep-grain").short("G").long("keep-grain").help("don't add a RemoveGrain(1) filter"))
        .arg(Arg::with_name("120").long("120").help("convert VFR to 120fps CFR (only works with MKVs)"))
        .arg(Arg::with_name("downsample").long("downsample").alias("ds").help("downsample video to YUV420P8"))
        .arg(Arg::with_name("vapour").long("vs").help("generate a vapoursynth script instead"))
        .arg(Arg::with_name("fast-fp").alias("with-fp").long("fast-fp").help("also generate a fast .fp.vpy script"))
        .get_matches();

    let input = matches.value_of("input").unwrap();
    let input = get_list_of_files(Path::new(&input), false).unwrap();
    for path in input {
        if determine_input_type(path.as_ref()).is_none() {
            continue;
        }
        if matches.is_present("fonts") {
            extract_fonts(path.as_ref()).unwrap();
        }
        if let Err(e) = create_output(&path, &matches) {
            eprintln!("An error occurred on {}: {}", path.to_str().unwrap(), e);
        }
    }
}

fn resize_opt_into_dimensions(pair: &str) -> (u32, u32) {
    let items: Vec<&str> = pair.split(|c| c == ',' || c == 'x' || c == 'X').collect();
    if items.len() != 2 {
        panic!("Expected exactly 2 arguments (comma-separated or x-separated) for 'resize'");
    }

    (
        items[0].parse().expect("Invalid width supplied to resizer"),
        items[1]
            .parse()
            .expect("Invalid height supplied to resizer"),
    )
}

fn create_output(path: &Path, matches: &ArgMatches) -> Result<(), String> {
    let opts = AvsOptions {
        filters: if matches.is_present("filters") {
            // FIXME: This is probably broken with avs, definitely broken with vpy
            vec![matches
                .value_of("filters")
                .unwrap()
                .trim_start_matches('.')
                .to_string()]
        } else {
            vec![]
        },
        ass: matches.is_present("subtitle"),
        ass_extract: if matches.is_present("sub-extract") {
            Some(
                matches
                    .value_of("sub-track")
                    .map(|track| track.parse().expect("Invalid argument supplied for track"))
                    .unwrap_or(0),
            )
        } else {
            None
        },
        audio: (
            matches.is_present("audio"),
            matches.value_of("audio-ext").map(|ext| ext.to_string()),
        ),
        resize: matches
            .value_of("resize")
            .map(|resize| resize_opt_into_dimensions(resize)),
        to_cfr: matches.is_present("120"),
        downsample: matches.is_present("downsample"),
        fast_fp: matches.is_present("fast-fp"),
    };
    let mut writer: Box<dyn ScriptFormat> = if matches.is_present("vapour") {
        Box::new(VapoursynthWriter::new(
            opts,
            !matches.is_present("keep-grain"),
            if matches.is_present("audio") {
                Some(path.with_extension("flac"))
            } else {
                None
            },
        ))
    } else {
        Box::new(AvisynthWriter::new(opts, !matches.is_present("keep-grain")))
    };
    writer.create_script(path, &path.with_extension(writer.get_script_extension()))
}
<commit_msg>Don't apply RemoveGrain by default<commit_after>#![warn(clippy::all)]

use avsser::input::determine_input_type;
use avsser::input::get_list_of_files;
use avsser::output::*;
use clap::App;
use clap::Arg;
use clap::ArgMatches;
use std::path::Path;

fn main() {
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::with_name("input").help("the input file to generate a script for").required(true).index(1))
        .arg(Arg::with_name("subtitle")
            .short("s")
            .long("subtitle")
            .help("include subtitles with TextSub(input_filename.ass)"))
        .arg(Arg::with_name("sub-extract").short("S").long("sub-extract").help("extract subtitles from the input files (defaults to track 0)"))
        .arg(Arg::with_name("sub-track").short("T").long("sub-track").help("select which subtitle track to extract, 0-indexed (does nothing without -S)")
            .takes_value(true).value_name("TRACK"))
        .arg(Arg::with_name("audio").short("a").long("audio").help("include audio from video"))
        .arg(Arg::with_name("audio-ext").short("A").long("audio-ext").help("include audio from separate file with specified extension (takes precedence over audio \
         from video)").takes_value(true).value_name("EXT"))
        .arg(Arg::with_name("fonts").short("f").long("fonts").help("extract fonts from mkv container"))
        .arg(Arg::with_name("resize").short("R").long("resize").help("resize video to the given width and height").takes_value(true).value_name("W,H"))
        .arg(Arg::with_name("filters").short("F").long("filters").help("use a custom filter chain instead of RemoveGrain(1)"))
        .arg(Arg::with_name("remove-grain").short("G").long("remove-grain").help("simple add a RemoveGrain(1) filter"))
        .arg(Arg::with_name("120").long("120").help("convert VFR to 120fps CFR (only works with MKVs)"))
        .arg(Arg::with_name("downsample").long("downsample").alias("ds").help("downsample video to YUV420P8"))
        .arg(Arg::with_name("vapour").long("vs").help("generate a vapoursynth script instead"))
        .arg(Arg::with_name("fast-fp").alias("with-fp").long("fast-fp").help("also generate a fast .fp.vpy script"))
        .get_matches();

    let input = matches.value_of("input").unwrap();
    let input = get_list_of_files(Path::new(&input), false).unwrap();
    for path in input {
        if determine_input_type(path.as_ref()).is_none() {
            continue;
        }
        if matches.is_present("fonts") {
            extract_fonts(path.as_ref()).unwrap();
        }
        if let Err(e) = create_output(&path, &matches) {
            eprintln!("An error occurred on {}: {}", path.to_str().unwrap(), e);
        }
    }
}

fn resize_opt_into_dimensions(pair: &str) -> (u32, u32) {
    let items: Vec<&str> = pair.split(|c| c == ',' || c == 'x' || c == 'X').collect();
    if items.len() != 2 {
        panic!("Expected exactly 2 arguments (comma-separated or x-separated) for 'resize'");
    }

    (
        items[0].parse().expect("Invalid width supplied to resizer"),
        items[1]
            .parse()
            .expect("Invalid height supplied to resizer"),
    )
}

fn create_output(path: &Path, matches: &ArgMatches) -> Result<(), String> {
    let opts = AvsOptions {
        filters: if matches.is_present("filters") {
            // FIXME: This is probably broken with avs, definitely broken with vpy
            vec![matches
                .value_of("filters")
                .unwrap()
                .trim_start_matches('.')
                .to_string()]
        } else {
            vec![]
        },
        ass: matches.is_present("subtitle"),
        ass_extract: if matches.is_present("sub-extract") {
            Some(
                matches
                    .value_of("sub-track")
                    .map(|track| track.parse().expect("Invalid argument supplied for track"))
                    .unwrap_or(0),
            )
        } else {
            None
        },
        audio: (
            matches.is_present("audio"),
            matches.value_of("audio-ext").map(|ext| ext.to_string()),
        ),
        resize: matches
            .value_of("resize")
            .map(|resize| resize_opt_into_dimensions(resize)),
        to_cfr: matches.is_present("120"),
        downsample: matches.is_present("downsample"),
        fast_fp: matches.is_present("fast-fp"),
    };
    let mut writer: Box<dyn ScriptFormat> = if matches.is_present("vapour") {
        Box::new(VapoursynthWriter::new(
            opts,
            matches.is_present("remove-grain"),
            if matches.is_present("audio") {
                Some(path.with_extension("flac"))
            } else {
                None
            },
        ))
    } else {
        Box::new(AvisynthWriter::new(
            opts,
            matches.is_present("remove-grain"),
        ))
    };
    writer.create_script(path, &path.with_extension(writer.get_script_extension()))
}
<|endoftext|>


<commit_before>#![feature(globs)]

extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate serialize;

use neovim::nvim_main;
use rgtk::*;
use std::collections::HashSet;
use std::{io, str, time};

mod projects;
mod ui;
mod utils;

mod ffi {
    pub use libc::{c_char, c_int, c_uchar, c_void, uint64_t};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
        pub fn channel_from_fds (read_fd: c_int, write_fd: c_int) -> uint64_t;
        pub fn channel_subscribe(id: uint64_t, event: *const c_char);
    }
}

fn gui_main(
    pty: &mut gtk::VtePty,
    read_fd: ffi::c_int,
    write_fd: ffi::c_int,
    pid: ffi::c_int)
{
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.75) as i32;

    // create the window

    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title("SolidOak");
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(|_| {
        unsafe {
            ffi::close(read_fd);
            ffi::close(write_fd);
            ffi::kill(pid, 15);
        }
        gtk::main_quit();
        true
    }));

    // create the panes

    let new_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut proj_btns = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    proj_btns.set_size_request(-1, -1);
    proj_btns.add(&new_button);
    proj_btns.add(&import_button);
    proj_btns.add(&rename_button);
    proj_btns.add(&remove_button);

    let mut proj_tree = gtk::TreeView::new().unwrap();
    let selection = proj_tree.get_selection().unwrap();
    let column_types = [glib::ffi::g_type_string, glib::ffi::g_type_string];
    let store = gtk::TreeStore::new(&column_types).unwrap();
    let model = store.get_model().unwrap();
    proj_tree.set_model(&model);
    proj_tree.set_headers_visible(false);

    let mut scroll_pane = gtk::ScrolledWindow::new(None, None).unwrap();
    scroll_pane.add(&proj_tree);

    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    proj_tree.append_column(&column);

    let mut proj_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    proj_pane.set_size_request(-1, -1);
    proj_pane.pack_start(&proj_btns, false, true, 0);
    proj_pane.pack_start(&scroll_pane, true, true, 0);

    let mut editor_pane = gtk::VteTerminal::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);
    editor_pane.set_pty(pty);
    editor_pane.watch_child(pid);

    let run_button = gtk::Button::new_with_label("Run").unwrap();
    let build_button = gtk::Button::new_with_label("Build").unwrap();
    let test_button = gtk::Button::new_with_label("Test").unwrap();
    let clean_button = gtk::Button::new_with_label("Clean").unwrap();
    let stop_button = gtk::Button::new_with_label("Stop").unwrap();

    let mut build_btns = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    build_btns.set_size_request(-1, -1);
    build_btns.add(&run_button);
    build_btns.add(&build_button);
    build_btns.add(&test_button);
    build_btns.add(&clean_button);
    build_btns.add(&stop_button);

    let build_term = gtk::VteTerminal::new().unwrap();

    let mut build_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    build_pane.pack_start(&build_btns, false, true, 0);
    build_pane.pack_start(&build_term, true, true, 0);

    let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    let mut hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&proj_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // populate the project tree

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model,
        tree_store: &store,
        tree_selection: &selection,
        rename_button: &rename_button,
        remove_button: &remove_button,
    };

    ::utils::create_data_dir();
    ::utils::read_prefs(&mut state);
    ::ui::update_project_tree(&mut state, &mut proj_tree);

    // connect to the signals

    new_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::new_project(&mut state, &mut proj_tree);
    }));
    import_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::import_project(&mut state, &mut proj_tree);
    }));
    rename_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::rename_file(&mut state);
    }));
    remove_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::remove_item(&mut state);
    }));
    selection.connect(gtk::signals::Changed::new(|| {
        ::projects::update_selection(&mut state);
    }));
    proj_tree.connect(gtk::signals::RowCollapsed::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::remove_expansion(&mut state, &iter);
    }));
    proj_tree.connect(gtk::signals::RowExpanded::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::add_expansion(&mut state, &iter);
    }));

    // show the window

    window.show_all();
    gtk::main();
}

fn main() {
    // takes care of piping stdin/stdout between the gui and nvim
    let mut pty = gtk::VtePty::new().unwrap();

    // two pairs of anonymous pipes for msgpack-rpc between the gui and nvim
    let mut nvim_from_gui : [ffi::c_int, ..2] = [0, ..2];
    let mut gui_from_nvim : [ffi::c_int, ..2] = [0, ..2];
    unsafe {
        ffi::pipe(nvim_from_gui.as_mut_ptr());
        ffi::pipe(gui_from_nvim.as_mut_ptr());
    };

    // split into two processes
    let pid = unsafe { ffi::fork() };

    if pid > 0 { // the gui process
        // listen for messages from nvim
        spawn(proc() {
            let mut buf : [ffi::c_uchar, ..100] = [0, ..100];
            unsafe {
                loop {
                    let buf_ptr = buf.as_mut_ptr() as *mut ffi::c_void;
                    let n = ffi::read(gui_from_nvim[0], buf_ptr, 100);
                    if n < 0 { break; }
                    let msg = str::from_utf8(buf.slice_to(n as uint)).unwrap();
                    println!("Received: {}", msg);
                }
            }
        });

        // start the gui
        gui_main(&mut pty, gui_from_nvim[0], gui_from_nvim[1], pid);
    } else { // the nvim process
        // prepare this process to be piped into the gui
        pty.child_setup();

        // listen for messages from the gui
        spawn(proc() {
            io::timer::sleep(time::Duration::seconds(1));
            unsafe {
                let id = ffi::channel_from_fds(nvim_from_gui[0], gui_from_nvim[1]);
                let cmd = "test";
                ffi::channel_subscribe(id, cmd.to_c_str().as_ptr());

                let msg = "Hello, world!";
                let msg_c = msg.to_c_str();
                let msg_ptr = msg_c.as_ptr() as *const ffi::c_void;
                ffi::write(gui_from_nvim[1], msg_ptr, msg_c.len() as ffi::size_t);
            }
        });

        // start nvim
        nvim_main();
    }
}
<commit_msg>Add space<commit_after>#![feature(globs)]

extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate serialize;

use neovim::nvim_main;
use rgtk::*;
use std::collections::HashSet;
use std::{io, str, time};

mod projects;
mod ui;
mod utils;

mod ffi {
    pub use libc::{c_char, c_int, c_uchar, c_void, uint64_t};
    pub use libc::funcs::posix88::unistd::{close, pipe, read, write};
    pub use libc::types::os::arch::c95::size_t;

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
        pub fn channel_from_fds (read_fd: c_int, write_fd: c_int) -> uint64_t;
        pub fn channel_subscribe (id: uint64_t, event: *const c_char);
    }
}

fn gui_main(
    pty: &mut gtk::VtePty,
    read_fd: ffi::c_int,
    write_fd: ffi::c_int,
    pid: ffi::c_int)
{
    gtk::init();

    // constants

    let width = 1242;
    let height = 768;
    let editor_height = ((height as f32) * 0.75) as i32;

    // create the window

    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title("SolidOak");
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

    window.connect(gtk::signals::DeleteEvent::new(|_| {
        unsafe {
            ffi::close(read_fd);
            ffi::close(write_fd);
            ffi::kill(pid, 15);
        }
        gtk::main_quit();
        true
    }));

    // create the panes

    let new_button = gtk::Button::new_with_label("New Project").unwrap();
    let import_button = gtk::Button::new_with_label("Import").unwrap();
    let rename_button = gtk::Button::new_with_label("Rename").unwrap();
    let remove_button = gtk::Button::new_with_label("Remove").unwrap();

    let mut proj_btns = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    proj_btns.set_size_request(-1, -1);
    proj_btns.add(&new_button);
    proj_btns.add(&import_button);
    proj_btns.add(&rename_button);
    proj_btns.add(&remove_button);

    let mut proj_tree = gtk::TreeView::new().unwrap();
    let selection = proj_tree.get_selection().unwrap();
    let column_types = [glib::ffi::g_type_string, glib::ffi::g_type_string];
    let store = gtk::TreeStore::new(&column_types).unwrap();
    let model = store.get_model().unwrap();
    proj_tree.set_model(&model);
    proj_tree.set_headers_visible(false);

    let mut scroll_pane = gtk::ScrolledWindow::new(None, None).unwrap();
    scroll_pane.add(&proj_tree);

    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();
    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    proj_tree.append_column(&column);

    let mut proj_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    proj_pane.set_size_request(-1, -1);
    proj_pane.pack_start(&proj_btns, false, true, 0);
    proj_pane.pack_start(&scroll_pane, true, true, 0);

    let mut editor_pane = gtk::VteTerminal::new().unwrap();
    editor_pane.set_size_request(-1, editor_height);
    editor_pane.set_pty(pty);
    editor_pane.watch_child(pid);

    let run_button = gtk::Button::new_with_label("Run").unwrap();
    let build_button = gtk::Button::new_with_label("Build").unwrap();
    let test_button = gtk::Button::new_with_label("Test").unwrap();
    let clean_button = gtk::Button::new_with_label("Clean").unwrap();
    let stop_button = gtk::Button::new_with_label("Stop").unwrap();

    let mut build_btns = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    build_btns.set_size_request(-1, -1);
    build_btns.add(&run_button);
    build_btns.add(&build_button);
    build_btns.add(&test_button);
    build_btns.add(&clean_button);
    build_btns.add(&stop_button);

    let build_term = gtk::VteTerminal::new().unwrap();

    let mut build_pane = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    build_pane.pack_start(&build_btns, false, true, 0);
    build_pane.pack_start(&build_term, true, true, 0);

    let mut content = gtk::Box::new(gtk::Orientation::Vertical, 0).unwrap();
    content.pack_start(&editor_pane, false, true, 0);
    content.pack_start(&build_pane, true, true, 0);

    let mut hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0).unwrap();
    hbox.pack_start(&proj_pane, false, true, 0);
    hbox.pack_start(&content, true, true, 0);
    window.add(&hbox);

    // populate the project tree

    let mut state = ::utils::State{
        projects: HashSet::new(),
        expansions: HashSet::new(),
        selection: None,
        tree_model: &model,
        tree_store: &store,
        tree_selection: &selection,
        rename_button: &rename_button,
        remove_button: &remove_button,
    };

    ::utils::create_data_dir();
    ::utils::read_prefs(&mut state);
    ::ui::update_project_tree(&mut state, &mut proj_tree);

    // connect to the signals

    new_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::new_project(&mut state, &mut proj_tree);
    }));
    import_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::import_project(&mut state, &mut proj_tree);
    }));
    rename_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::rename_file(&mut state);
    }));
    remove_button.connect(gtk::signals::Clicked::new(|| {
        ::projects::remove_item(&mut state);
    }));
    selection.connect(gtk::signals::Changed::new(|| {
        ::projects::update_selection(&mut state);
    }));
    proj_tree.connect(gtk::signals::RowCollapsed::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::remove_expansion(&mut state, &iter);
    }));
    proj_tree.connect(gtk::signals::RowExpanded::new(|iter_raw, _| {
        let iter = gtk::TreeIter::wrap_pointer(iter_raw);
        ::projects::add_expansion(&mut state, &iter);
    }));

    // show the window

    window.show_all();
    gtk::main();
}

fn main() {
    // takes care of piping stdin/stdout between the gui and nvim
    let mut pty = gtk::VtePty::new().unwrap();

    // two pairs of anonymous pipes for msgpack-rpc between the gui and nvim
    let mut nvim_from_gui : [ffi::c_int, ..2] = [0, ..2];
    let mut gui_from_nvim : [ffi::c_int, ..2] = [0, ..2];
    unsafe {
        ffi::pipe(nvim_from_gui.as_mut_ptr());
        ffi::pipe(gui_from_nvim.as_mut_ptr());
    };

    // split into two processes
    let pid = unsafe { ffi::fork() };

    if pid > 0 { // the gui process
        // listen for messages from nvim
        spawn(proc() {
            let mut buf : [ffi::c_uchar, ..100] = [0, ..100];
            unsafe {
                loop {
                    let buf_ptr = buf.as_mut_ptr() as *mut ffi::c_void;
                    let n = ffi::read(gui_from_nvim[0], buf_ptr, 100);
                    if n < 0 { break; }
                    let msg = str::from_utf8(buf.slice_to(n as uint)).unwrap();
                    println!("Received: {}", msg);
                }
            }
        });

        // start the gui
        gui_main(&mut pty, gui_from_nvim[0], gui_from_nvim[1], pid);
    } else { // the nvim process
        // prepare this process to be piped into the gui
        pty.child_setup();

        // listen for messages from the gui
        spawn(proc() {
            io::timer::sleep(time::Duration::seconds(1));
            unsafe {
                let id = ffi::channel_from_fds(nvim_from_gui[0], gui_from_nvim[1]);
                let cmd = "test";
                ffi::channel_subscribe(id, cmd.to_c_str().as_ptr());

                let msg = "Hello, world!";
                let msg_c = msg.to_c_str();
                let msg_ptr = msg_c.as_ptr() as *const ffi::c_void;
                ffi::write(gui_from_nvim[1], msg_ptr, msg_c.len() as ffi::size_t);
            }
        });

        // start nvim
        nvim_main();
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::collections::HashMap;
use std::mem::transmute;

struct Graph {
	vertices: HashMap<i64, Box<Vertex>>,
}

impl Graph {
	fn new() -> Box<Graph> {
		let vertices: HashMap<i64, Box<Vertex>> = HashMap::new();
		Box::new(Graph{vertices:vertices})
	}
	fn add_vertex(&mut self) -> VertexProxy {
		let new_id = 1;
		let vertex = Vertex{id:new_id};

		let mut v = Box::new(vertex);
		let ptr: *const Box<Vertex> = &v as *const Box<Vertex>;

		self.vertices.insert(new_id, v);

		// return the proxy which knows it's own id
		VertexProxy{id:new_id, v: ptr}
	}
}

struct Vertex {
	id: i64,
}

impl Vertex {
	fn query(self) {

	}
}

struct VertexProxy {
	id: i64,
	v: *const Box<Vertex>,
}

//let i: u32 = 1;
//// explicit cast
//let p_imm: *const u32 = &i as *const u32;
//let mut m: u32 = 2;
//// implicit coercion
//let p_mut: *mut u32 = &mut m;
//
//unsafe {
//let ref_imm: &u32 = &*p_imm;
//let ref_mut: &mut u32 = &mut *p_mut;
//}

impl VertexProxy {
	fn add_edge(&self, to_vertex: &VertexProxy) {
		unsafe {
			let in_vertex = &*self.v;
			let out_vertex = &*to_vertex.v;
		}
	}
}

struct Edge {
	id: i32,
	from_vertex: *const Vertex,
	to_vertex: *const Vertex
}

fn main() {
	let mut g = Graph::new();

    println!("Hello, world!");
}

#[test]
fn test_unsafe_vertex() {
	let mut g = Graph::new();
	let mut v1 = g.add_vertex();
	let mut v2 = g.add_vertex();

	v1.test()

}
<commit_msg>edges vector on Vertex coming along<commit_after>use std::mem;
use std::collections::HashMap;
use std::mem::transmute;

struct Graph {
	vertices: HashMap<i64, Box<Vertex>>,
}

impl Graph {
	fn new() -> Box<Graph> {
		let vertices: HashMap<i64, Box<Vertex>> = HashMap::new();
		Box::new(Graph{vertices:vertices})
	}
	fn add_vertex(&mut self) -> VertexProxy {
		let new_id = 1;
		let v = Vertex::new(new_id);

		let ptr: *const Box<Vertex> = &v as *const Box<Vertex>;

		self.vertices.insert(new_id, v);

		// return the proxy which knows it's own id
		VertexProxy{id:new_id, v: ptr}
	}
}

struct Vertex {
	id: i64,
	edges: *mut Vec<Edge>,
}

impl Vertex {
	fn new(id: i64) -> Box<Vertex> {

		let mut edges : Vec<Edge> = Vec::new();
		let edges_ptr :	*mut Vec<Edge> = &mut edges;
		let vertex = Vertex{id:id, edges:edges_ptr};
		let mut v = Box::new(vertex);
		return v;
	}

	fn query(self) {

	}
}

struct VertexProxy {
	id: i64,
	v: *const Box<Vertex>,
}

//let i: u32 = 1;
//// explicit cast
//let p_imm: *const u32 = &i as *const u32;
//let mut m: u32 = 2;
//// implicit coercion
//let p_mut: *mut u32 = &mut m;
//
//unsafe {
//let ref_imm: &u32 = &*p_imm;
//let ref_mut: &mut u32 = &mut *p_mut;
//}

impl VertexProxy {
	fn add_edge(& self, to_vertex: &VertexProxy) {
		unsafe {
			let in_vertex = &* self .v;
			let out_vertex = &*to_vertex.v;
		}
		// create the edge
		let e = Edge{from_vertex: self.v,
					 to_vertex:to_vertex.v};

	}
}

struct Edge {
	from_vertex: *const Box<Vertex>,
	to_vertex: *const Box<Vertex>
}

fn main() {
	let mut g = Graph::new();

    println!("Hello, world!");
}

#[test]
fn test_unsafe_vertex() {
	let mut g = Graph::new();
	let mut v1 = g.add_vertex();
	let mut v2 = g.add_vertex();

	v1.test()

}
<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate tokio_service;

use std::io;
use std::str;
use tokio_core::io::{Codec, EasyBuf};
use tokio_core::io::{Io, Framed};
use tokio_proto::pipeline::ServerProto;

#[derive(Default)]
pub struct CliCodec {
    /// Offset within the incoming EasyBuf at which newline search last ended
    search_offset: usize,
}

impl Codec for CliCodec {
    /// Input type is a tuple with the command name and an optional argument string
    type In = (String, Option<String>);

    /// Response type is just a string
    type Out = String;

    /// Find a newline, decode to a tuple of command name and argument string
    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>> {
        // Find newline
        let m = buf
            .as_slice()
            .iter()
            .skip(self.search_offset)
            .position(|&b| b == b'\n');

        match m {
            // Process the line if a newline was found
            Some(idx) => {
                println!("Found newline at position {}, started at {}", idx, self.search_offset); // XXX

                let line = buf.drain_to(self.search_offset + idx);
                buf.drain_to(1);

                self.search_offset = 0;

                match str::from_utf8(line.as_slice()) {
                    // Return the string on successful UTF-8 decode
                    // (TODO: split on the first space)
                    Ok(s) => Ok(Some(
                            ("Received".to_string(), Some(s.trim().to_string()))
                            )),

                    // Return an error if invalid UTF-8 is received
                    Err(e) => Err(io::Error::new(io::ErrorKind::Other, format!("invalid UTF-8: {:?}", e))),
                }
            },

            // Save our position if a newline wasn't found
            _ => {
                println!("Haven't received newline yet!  We started at offset {}, now at {}", self.search_offset, buf.len()); // XXX

                self.search_offset = buf.len();

                Ok(None)
            }
        }
    }

    /// Append the String to the outgoing buffer
    fn encode(&mut self, msg: String, buf: &mut Vec<u8>) -> io::Result<()> {
        buf.extend(msg.as_bytes());
        buf.push(b'\n');
        Ok(())
    }
}

pub struct CliProto;

impl<T: Io + 'static> ServerProto<T> for CliProto {
    type Request = (String, Option<String>);
    type Response = String;

    type Transport = Framed<T, CliCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(CliCodec::default()))
    }
}

fn main() {
    // TODO
    println!("Hello, world!");
}
<commit_msg>Added placeholder CliServer Service definition.<commit_after>extern crate futures;
extern crate tokio_core;
extern crate tokio_proto;
extern crate tokio_service;

use std::io;
use std::str;
use tokio_core::io::{Codec, EasyBuf};
use tokio_core::io::{Io, Framed};
use tokio_proto::pipeline::ServerProto;
use tokio_service::Service;
use futures::{future, Future, BoxFuture};

#[derive(Default)]
pub struct CliCodec {
    /// Offset within the incoming EasyBuf at which newline search last ended
    search_offset: usize,
}

impl Codec for CliCodec {
    /// Input type is a tuple with the command name and an optional argument string
    type In = (String, Option<String>);

    /// Response type is just a string
    type Out = String;

    /// Find a newline, decode to a tuple of command name and argument string
    fn decode(&mut self, buf: &mut EasyBuf) -> io::Result<Option<Self::In>> {
        // Find newline
        let m = buf
            .as_slice()
            .iter()
            .skip(self.search_offset)
            .position(|&b| b == b'\n');

        match m {
            // Process the line if a newline was found
            Some(idx) => {
                println!("Found newline at position {}, started at {}", idx, self.search_offset); // XXX

                let line = buf.drain_to(self.search_offset + idx);
                buf.drain_to(1);

                self.search_offset = 0;

                match str::from_utf8(line.as_slice()) {
                    // Return the string on successful UTF-8 decode
                    // (TODO: split on the first space, ignore blank lines)
                    Ok(s) => Ok(Some(
                            ("Received".to_string(), Some(s.trim().to_string()))
                            )),

                    // Return an error if invalid UTF-8 is received
                    Err(e) => Err(io::Error::new(io::ErrorKind::Other, format!("invalid UTF-8: {:?}", e))),
                }
            },

            // Save our position if a newline wasn't found
            _ => {
                println!("Haven't received newline yet!  We started at offset {}, now at {}", self.search_offset, buf.len()); // XXX

                self.search_offset = buf.len();

                Ok(None)
            }
        }
    }

    /// Append the String to the outgoing buffer
    fn encode(&mut self, msg: String, buf: &mut Vec<u8>) -> io::Result<()> {
        buf.extend(msg.as_bytes());
        buf.push(b'\n');
        Ok(())
    }
}

pub struct CliProto;

impl<T: Io + 'static> ServerProto<T> for CliProto {
    type Request = (String, Option<String>);
    type Response = String;

    type Transport = Framed<T, CliCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(CliCodec::default()))
    }
}

pub struct CliServer;

impl Service for CliServer {
    type Request = (String, Option<String>);
    type Response = String;

    type Error = io::Error;

    type Future = BoxFuture<Self::Response, Self::Error>;

    fn call(&self, req: Self::Request) -> Self::Future {
        future::ok(format!("Received: {:?}", req)).boxed()
    }
}

fn main() {
    // TODO
    println!("Hello, world!");
}
<|endoftext|>