<commit_before>use std::env;
use std::fs::File;
use std::io;
use std::io::prelude::*;

#[derive(Debug)]
enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(u32),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    Eof,
    // These are not described in the book but they simplify the parser
    Comment,
    Whitespace,
}

#[derive(Debug)]
struct TokenWithContext {
    token: Token,
    lexeme: String, // TODO: make a reference
    line: usize,
}

struct Scanner {
    start: usize,
    current: usize,
    line: usize,
    source: String, // TODO: make a reference
}
impl Scanner {
    fn initialize(source: &String) -> Scanner {
        Scanner {
            start: 0,
            current: 0,
            line: 0,
            source: source.clone(),
        }
    }

    fn is_at_end(&self) -> bool {
        self.current >= self.source.len()
    }

    fn char_at(&self, index: usize) -> char {
        // TODO: there must be a better way
        self.source.chars().nth(index).unwrap()
    }

    fn peek(&self) -> char() {
        if (self.is_at_end()) {
            '\0'
        } else {
            self.char_at(self.current)
        }
    }

    fn advance(&mut self) -> char {
        self.current += 1;
        self.char_at(self.current - 1)
    }

    fn is_match(&mut self, expected: char) -> bool {
        if (self.is_at_end()) {
            return false;
        }
        if (self.char_at(self.current) != expected) {
            return false;
        }
        self.current += 1;
        return true;
    }

    fn add_context(&self, token: Token) -> TokenWithContext {
        TokenWithContext {
            token: token,
            lexeme: self.source.chars().skip(self.start).take(self.current - self.start).collect(),
            line: self.line,
        }
    }

    fn scan_next(&mut self) -> Result<TokenWithContext, String> {
        self.start = self.current;
        let token = match self.advance() {
            '(' => Token::LeftParen,
            ')' => Token::RightParen,
            '{' => Token::LeftBrace,
            '}' => Token::RightBrace,
            ',' => Token::Comma,
            '.' => Token::Dot,
            '-' => Token::Minus,
            '+' => Token::Plus,
            ';' => Token::Semicolon,
            '*' => Token::Star,
            '!' => {
                if self.is_match('=') {
                    Token::BangEqual
                } else {
                    Token::Bang
                }
            }
            '=' => {
                if self.is_match('=') {
                    Token::EqualEqual
                } else {
                    Token::Equal
                }
            }
            '<' => {
                if self.is_match('=') {
                    Token::LessEqual
                } else {
                    Token::Less
                }
            }
            '>' => {
                if self.is_match('=') {
                    Token::GreaterEqual
                } else {
                    Token::Greater
                }
            }
            '/' => {
                if self.is_match('/') {
                    // Comments go on till the end of the line
                    while (self.peek() != '\n' && !self.is_at_end()) {
                        self.advance();
                    }
                    Token::Comment
                } else {
                    Token::Slash
                }
            }
            ' ' => Token::Whitespace,
            '\r' => Token::Whitespace,
            '\t' => Token::Whitespace,
            '\n' => {
                self.line += 1;
                Token::Whitespace
            }
            _ => {
                return Err(format!("Unexpected character at line {}, pos {}",
                                   self.line,
                                   self.current))
            }
        };
        Ok(self.add_context(token))
    }
}

fn tokenize(source: &String) -> Result<Vec<TokenWithContext>, String> {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    while !scanner.is_at_end() {
        match scanner.scan_next() {
            Ok(tokenWithContext) => {
                match tokenWithContext.token {
                    // Ignoring tokens we don't care about
                    Token::Comment => {}
                    Token::Whitespace => {}
                    _ => tokens.push(tokenWithContext),
                }
            }
            Err(message) => return Err(message),
        }
    }
    tokens.push(TokenWithContext {
        token: Token::Eof,
        lexeme: "".into(),
        line: scanner.line,
    });
    Ok(tokens)
}

fn run(source: &String) -> Result<(), String> {
    let tokens = try!(tokenize(source));
    for token in tokens {
        println!("{:?}", token);
    }
    Ok(())
}

fn run_file(file_name: &String) -> Result<(), String> {
    match File::open(file_name) {
        Err(_) => {
            Err("Error opening file".into()) // TODO: add context
        }
        Ok(mut file) => {
            let mut source = String::new();
            match file.read_to_string(&mut source) {
                Err(_) => {
                    Err("Error reading file".into()) // TODO: add context
                }
                Ok(_) => run(&source),
            }
        }
    }
}

fn run_prompt() -> Result<(), String> {
    loop {
        print!("> ");
        io::stdout().flush();
        let mut source = String::new();
        io::stdin().read_line(&mut source);
        try!(run(&source));
        ()
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let result = match args.len() {
        // The first argument is the program name
        1 => run_prompt(),
        2 => run_file(&args[1]),
        _ => {
            println!("Usage: rulox [script]");
            Ok(())
        }
    };
    let exit_code = match result {
        Ok(_) => 0,
        Err(e) => {
            println!("{}", e);
            1
        }
    };
    std::process::exit(exit_code)
}
<commit_msg>String literals<commit_after>use std::env;
use std::fs::File;
use std::io;
use std::io::prelude::*;

#[derive(Debug)]
enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(u32),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    Eof,
    // These are not described in the book but they simplify the parser
    Comment,
    Whitespace,
}

#[derive(Debug)]
struct TokenWithContext {
    token: Token,
    lexeme: String, // TODO: make a reference
    line: usize,
}

struct Scanner {
    start: usize,
    current: usize,
    line: usize,
    source: String, // TODO: make a reference
}
impl Scanner {
    fn initialize(source: &String) -> Scanner {
        Scanner {
            start: 0,
            current: 0,
            line: 0,
            source: source.clone(),
        }
    }

    fn is_at_end(&self) -> bool {
        self.current >= self.source.len()
    }

    fn char_at(&self, index: usize) -> char {
        // TODO: there must be a better way
        self.source.chars().nth(index).unwrap()
    }

    fn substring(&self, start: usize, end: usize) -> String{
        self.source.chars().skip(start).take(end - start).collect()
    }

    fn peek(&self) -> char() {
        if self.is_at_end() {
            '\0'
        } else {
            self.char_at(self.current)
        }
    }

    fn advance(&mut self) -> char {
        self.current += 1;
        self.char_at(self.current - 1)
    }

    fn is_match(&mut self, expected: char) -> bool {
        if self.is_at_end() {
            return false;
        }
        if self.char_at(self.current) != expected {
            return false;
        }
        self.current += 1;
        return true;
    }

    fn add_context(&self, token: Token) -> TokenWithContext {
        TokenWithContext {
            token: token,
            lexeme: self.substring(self.start, self.current),
            line: self.line,
        }
    }

    fn string(&mut self) -> Result<Token, String>{
        let initial_line = self.line;
        while self.peek() != '"' && !self.is_at_end(){
            if(self.peek() == '\n'){
                self.line += 1
            }
            self.advance();
        }
        if self.is_at_end(){
            return Err(format!("Unterminated string at line {}", initial_line))
        }
        self.advance();
        Ok(Token::StringLiteral(self.substring(self.start + 1, self.current - 1)))
    }

    fn scan_next(&mut self) -> Result<TokenWithContext, String> {
        self.start = self.current;
        let token = match self.advance() {
            '(' => Token::LeftParen,
            ')' => Token::RightParen,
            '{' => Token::LeftBrace,
            '}' => Token::RightBrace,
            ',' => Token::Comma,
            '.' => Token::Dot,
            '-' => Token::Minus,
            '+' => Token::Plus,
            ';' => Token::Semicolon,
            '*' => Token::Star,
            '!' => {
                if self.is_match('=') {
                    Token::BangEqual
                } else {
                    Token::Bang
                }
            }
            '=' => {
                if self.is_match('=') {
                    Token::EqualEqual
                } else {
                    Token::Equal
                }
            }
            '<' => {
                if self.is_match('=') {
                    Token::LessEqual
                } else {
                    Token::Less
                }
            }
            '>' => {
                if self.is_match('=') {
                    Token::GreaterEqual
                } else {
                    Token::Greater
                }
            }
            '/' => {
                if self.is_match('/') {
                    // Comments go on till the end of the line
                    while self.peek() != '\n' && !self.is_at_end() {
                        self.advance();
                    }
                    Token::Comment
                } else {
                    Token::Slash
                }
            }
            ' ' => Token::Whitespace,
            '\r' => Token::Whitespace,
            '\t' => Token::Whitespace,
            '\n' => {
                self.line += 1;
                Token::Whitespace
            }
            '"' => try!(self.string()),
            _ => {
                return Err(format!("Unexpected character at line {}, pos {}",
                                   self.line,
                                   self.current))
            }
        };
        Ok(self.add_context(token))
    }
}

fn tokenize(source: &String) -> Result<Vec<TokenWithContext>, String> {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    while !scanner.is_at_end() {
        match scanner.scan_next() {
            Ok(tokenWithContext) => {
                match tokenWithContext.token {
                    // Ignoring tokens we don't care about
                    Token::Comment => {}
                    Token::Whitespace => {}
                    _ => tokens.push(tokenWithContext),
                }
            }
            Err(message) => return Err(message),
        }
    }
    tokens.push(TokenWithContext {
        token: Token::Eof,
        lexeme: "".into(),
        line: scanner.line,
    });
    Ok(tokens)
}

fn run(source: &String) -> Result<(), String> {
    let tokens = try!(tokenize(source));
    for token in tokens {
        println!("{:?}", token);
    }
    Ok(())
}

fn run_file(file_name: &String) -> Result<(), String> {
    match File::open(file_name) {
        Err(_) => {
            Err("Error opening file".into()) // TODO: add context
        }
        Ok(mut file) => {
            let mut source = String::new();
            match file.read_to_string(&mut source) {
                Err(_) => {
                    Err("Error reading file".into()) // TODO: add context
                }
                Ok(_) => run(&source),
            }
        }
    }
}

fn run_prompt() -> Result<(), String> {
    loop {
        print!("> ");
        io::stdout().flush();
        let mut source = String::new();
        io::stdin().read_line(&mut source);
        try!(run(&source));
        ()
    }
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let result = match args.len() {
        // The first argument is the program name
        1 => run_prompt(),
        2 => run_file(&args[1]),
        _ => {
            println!("Usage: rulox [script]");
            Ok(())
        }
    };
    let exit_code = match result {
        Ok(_) => 0,
        Err(e) => {
            println!("{}", e);
            1
        }
    };
    std::process::exit(exit_code)
}
<|endoftext|>


<commit_before>/*
    Copyright © 2021 Alastair Feille

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at https://mozilla.org/MPL/2.0/.

    SPDX-License-Identifier: MPL-2.0
*/

use std::{env,
          fs,
          io,
          io::Write,
          process,
          process::Command};

fn main()
{
    loop
    {
        let cwd: String = env::current_dir().map(|p| {
                                                // Attempt to canonicalize the path else return "???"
                                                fs::canonicalize(p).unwrap_or("???".into())
                                                                   .to_string_lossy()
                                                                   .into()
                                            })
                                            // Attempt to get the current path else return "???"
                                            .unwrap_or("???".into());
        // Print prompt
        print!("{}> ", cwd);
        io::stdout().flush().expect("failed to print prompt");

        // Read in line
        let mut line = String::new();
        io::stdin().read_line(&mut line)
                   .expect("failed to read from stdin");

        // Skip empty lines
        if line.trim().is_empty()
        {
            continue;
        }

        // Split line into command and arguments
        let tokens: Vec<&str> = line.split_whitespace().collect();
        let (head, args) = tokens.split_at(1);
        if let Some(cmd) = head.get(0)
        {
            if cmd.to_string() == "exit"
            {
                process::exit(0);
            }
            match Command::new(cmd).args(args).spawn()
            {
                Ok(mut child) =>
                {
                    let _ecode = child.wait().expect("failed to wait on child");
                },
                Err(e) => eprintln!("mush: could not run command {}: {}", cmd, e),
            }
        }
    }
}
<commit_msg>feat(cd): add cd command<commit_after>/*
    Copyright © 2021 Alastair Feille

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at https://mozilla.org/MPL/2.0/.

    SPDX-License-Identifier: MPL-2.0
*/

use std::{env,
          fs,
          io,
          io::Write,
          path::PathBuf,
          process,
          process::Command};

fn main()
{
    loop
    {
        let cwd: String = env::current_dir().map(|p| {
                                                // Attempt to canonicalize the path else return "???"
                                                fs::canonicalize(p).unwrap_or("???".into())
                                                                   .to_string_lossy()
                                                                   .into()
                                            })
                                            // Attempt to get the current path else return "???"
                                            .unwrap_or("???".into());
        // Print prompt
        print!("{}> ", cwd);
        io::stdout().flush().expect("failed to print prompt");

        // Read in line
        let mut line = String::new();
        io::stdin().read_line(&mut line)
                   .expect("failed to read from stdin");

        // Skip empty lines
        if line.trim().is_empty()
        {
            continue;
        }

        // Split line into command and arguments
        let tokens: Vec<&str> = line.split_whitespace().collect();
        let (head, args) = tokens.split_at(1);
        if let Some(cmd) = head.get(0)
        {
            if cmd.to_string() == "exit"
            {
                process::exit(0);
            }
            if cmd.to_string() == "cd"
            {
                let p = PathBuf::from(args.join(" "));
                if let Err(e) = env::set_current_dir(&p)
                {
                    eprintln!("mush: cd: {}: {}", p.display(), e);
                }
                continue;
            }
            match Command::new(cmd).args(args).spawn()
            {
                Ok(mut child) =>
                {
                    let _ecode = child.wait().expect("failed to wait on child");
                },
                Err(e) => eprintln!("mush: could not run command {}: {}", cmd, e),
            }
        }
    }
}
<|endoftext|>


<commit_before>// MIT License
//
// Copyright (c) 2016 Alexander Thaller <alexander@thaller.ws>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#![feature(custom_derive)]
#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

extern crate chrono;
extern crate csv;
extern crate env_logger;
extern crate loggerv;
extern crate rustc_serialize;
extern crate walkdir;
extern crate xdg;

use chrono::*;
use clap::App;
use clap::ArgMatches as Args;
use log::LogLevel;
use std::collections::BTreeMap as Map;
use std::collections::BTreeSet as Set;
use std::fs;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::PathBuf;
use walkdir::WalkDir;
use xdg::BaseDirectories;

const PROJECT_SEPPERATOR: &'static str = ".";

fn main() {
    let yaml = load_yaml!("cli.yml");
    let app = App::from_yaml(yaml)
        .version(crate_version!())
        .get_matches();

    let matches = match app.subcommand.clone() {
        Some(subcommand) => subcommand.matches,
        None => app.clone(),
    };

    let loglevel: LogLevel = app.value_of("loglevel").unwrap().parse().unwrap();
    loggerv::init_with_level(loglevel).unwrap();

    trace!("app: {:#?}", app);
    trace!("matches: {:#?}", matches);

    run(app)
}

fn run(args: Args) {
    match args.subcommand.clone() {
        Some(command) => {
            match command.name.as_str() {
                "note" => add_note(command.matches),
                "notes" => list_notes(command.matches),
                "projects" => list_projects(command.matches),
                "migrate" => migrate_notes(command.matches),
                _ => {
                    error!("do not know what to do with this command: {}",
                           command.name.as_str())
                }
            }
        }
        None => list_projects(args),
    }
}

fn migrate_notes(args: Args) {
    let datadir = get_datadir(&args);
    let sourcedir = PathBuf::from(args.value_of("sourcedir").unwrap());
    debug!("datadir: {:#?}", datadir);
    debug!("sourcedir: {:#?}", sourcedir);

    for file in WalkDir::new(&sourcedir)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| e.path().is_file())
        .filter(|e| match e.path().extension() {
            Some(ext) => ext.to_str().unwrap() == "csv",
            None => false,
        })
        .filter(|e| {
            !e.path().strip_prefix(&sourcedir).unwrap().to_str().unwrap().starts_with(".")
        }) {
        debug!("file: {:#?}", file.path());

        let mut rdr =
            csv::Reader::from_file(file.path()).unwrap().has_headers(false).flexible(true);

        for record in rdr.decode() {
            let (entry_type, time_stamp_raw, value): (String, String, String) = record.unwrap();
            trace!("entry_type: {}", entry_type);
            trace!("time_stamp_raw: {}", time_stamp_raw);
            trace!("value: {}", value);

            if entry_type != "note" {
                continue;
            }

            let project = file.path()
                .clone()
                .strip_prefix(&sourcedir).unwrap()
                .with_extension("")
                .to_str()
                .unwrap()
                .replace("/", PROJECT_SEPPERATOR);

            let time_stamp = time_stamp_raw.as_str().parse().unwrap();

            let note = Note {
                time_stamp: time_stamp,
                value: value,
            };
            trace!("datadir: {:#?}", datadir);
            trace!("project: {:#?}", project);

            write_note(&datadir, project.as_str(), note);
        }
    }
}

fn get_datadir(args: &Args) -> PathBuf {
    let datadir = match args.value_of("datadir").unwrap() {
        "$XDG_DATA_HOME/lablog" => {
            let xdg = BaseDirectories::new().unwrap();
            xdg.create_data_directory("lablog").unwrap()
        }
        _ => PathBuf::from(args.value_of("datadir").unwrap()),
    };
    debug!("datadir: {:?}", datadir);
    datadir
}

fn add_note(args: Args) {
    trace!("add_note args: {:#?}", args);
    let datadir = get_datadir(&args);
    let text = args.value_of("text").unwrap();
    let project = args.value_of("project").unwrap();
    debug!("project: {}", project);
    debug!("text: {}", text);

    let note = Note {
        time_stamp: UTC::now().into(),
        value: text.into(),
    };

    write_note(&datadir, project, note)
}

fn list_notes(args: Args) {
    trace!("list_notes args: {:#?}", args);
    let datadir = get_datadir(&args);
    let project_arg = args.value_of("project").unwrap();
    debug!("project_arg: {}", project_arg);

    let projects = match project_arg {
        "" => get_projects(&datadir),
        _ => {
            let mut out = Set::default();
            out.insert(project_arg.into());
            out
        }
    };

    let project_notes = get_projects_notes(&datadir, &projects);

    trace!("project_notes: {:#?}", project_notes);

    for (project, notes) in project_notes {
        println!("= {}", project);
        for (time_stamp, note) in notes {
            println!("== {}\n{}\n", time_stamp, note.value)
        }
    }
}

fn get_projects_notes<'a>(datadir: &PathBuf,
                          projects: &'a Set<String>)
                          -> Map<&'a str, Map<DateTime<UTC>, Note>> {
    let mut map = Map::default();

    for project in projects.iter().map(|x| x.as_str()) {
        let mut project_path = datadir.clone();
        project_path.push(normalize_project_path(project));

        let notes = get_notes(project_path);
        map.insert(project.clone(), notes);
    }

    map
}

fn list_projects(args: Args) {
    trace!("list_projects args: {:#?}", args);
    let datadir = get_datadir(&args);

    let projects = get_projects(&datadir);
    trace!("projects: {:#?}", projects);

    for project in projects {
        println!("{}", project)
    }
}

fn get_projects(datadir: &PathBuf) -> Set<String> {
    let ok_walkdir: Vec<walkdir::DirEntry> = WalkDir::new(&datadir)
        .into_iter()
        .filter_map(|e| e.ok())
        .collect();

    trace!("ok_walkdir: {:#?}", ok_walkdir);

    let stripped_paths: Vec<PathBuf> = ok_walkdir.iter()
        .filter(|e| e.path().is_file())
        .filter(|e| match e.path().extension() {
            Some(ext) => ext.to_str().unwrap() == "csv",
            None => false,
        })
        .map(|e| e.path().strip_prefix(&datadir))
        .filter_map(|e| e.ok())
        .filter(|e| !e.to_str().unwrap().starts_with("."))
        .map(|e| e.with_extension(""))
        .collect();

    trace!("stripped_paths: {:#?}", stripped_paths);

    let projects = stripped_paths.into_iter()
        .map(|e| e.to_str().unwrap().replace("/", PROJECT_SEPPERATOR))
        .collect();

    trace!("projects: {:#?}", projects);

    projects
}

fn get_notes(project_path: PathBuf) -> Map<DateTime<UTC>, Note> {
    let mut map = Map::default();
    let mut rdr = csv::Reader::from_file(project_path).unwrap().has_headers(false);

    for record in rdr.decode() {
        let note: Note = record.unwrap();

        trace!("note: {:#?}", note);

        map.insert(note.time_stamp, note);
    }

    map
}

fn normalize_project_path(project: &str) -> String {
    format!("{}.csv", project.replace(".", "/").as_str())
}

fn write_note(datadir: &PathBuf, project: &str, note: Note) {
    let mut project_path = datadir.clone();
    project_path.push(normalize_project_path(project));

    trace!("project_path: {:#?}", project_path);
    fs::create_dir_all(project_path.parent().unwrap()).unwrap();

    let mut file = match OpenOptions::new().append(true).open(&project_path) {
        Ok(file) => file,
        Err(_) => OpenOptions::new().append(true).create(true).open(&project_path).unwrap(),
    };

    let mut wtr = csv::Writer::from_memory();
    wtr.encode(note).unwrap();
    file.write_fmt(format_args!("{}", wtr.as_string())).unwrap();
}

#[derive(Debug,RustcEncodable,RustcDecodable)]
struct Note {
    time_stamp: DateTime<UTC>,
    value: String,
}
<commit_msg>Added migration for todos.<commit_after>// MIT License
//
// Copyright (c) 2016 Alexander Thaller <alexander@thaller.ws>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#![feature(custom_derive)]
#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

extern crate chrono;
extern crate csv;
extern crate env_logger;
extern crate loggerv;
extern crate rustc_serialize;
extern crate walkdir;
extern crate xdg;

use chrono::*;
use clap::App;
use clap::ArgMatches as Args;
use log::LogLevel;
use std::collections::BTreeMap as Map;
use std::collections::BTreeSet as Set;
use std::fs;
use std::fs::OpenOptions;
use std::io::Write;
use std::path::PathBuf;
use walkdir::WalkDir;
use xdg::BaseDirectories;

const PROJECT_SEPPERATOR: &'static str = ".";

fn main() {
    let yaml = load_yaml!("cli.yml");
    let app = App::from_yaml(yaml)
        .version(crate_version!())
        .get_matches();

    let matches = match app.subcommand.clone() {
        Some(subcommand) => subcommand.matches,
        None => app.clone(),
    };

    let loglevel: LogLevel = app.value_of("loglevel").unwrap().parse().unwrap();
    loggerv::init_with_level(loglevel).unwrap();

    trace!("app: {:#?}", app);
    trace!("matches: {:#?}", matches);

    run(app)
}

fn run(args: Args) {
    match args.subcommand.clone() {
        Some(command) => {
            match command.name.as_str() {
                "note" => add_note(command.matches),
                "notes" => list_notes(command.matches),
                "projects" => list_projects(command.matches),
                "migrate" => migrate_notes(command.matches),
                _ => {
                    error!("do not know what to do with this command: {}",
                           command.name.as_str())
                }
            }
        }
        None => list_projects(args),
    }
}

fn migrate_notes(args: Args) {
    let datadir = get_datadir(&args);
    let sourcedir = PathBuf::from(args.value_of("sourcedir").unwrap());
    debug!("datadir: {:#?}", datadir);
    debug!("sourcedir: {:#?}", sourcedir);

    for file in WalkDir::new(&sourcedir)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|e| e.path().is_file())
        .filter(|e| match e.path().extension() {
            Some(ext) => ext.to_str().unwrap() == "csv",
            None => false,
        })
        .filter(|e| {
            !e.path().strip_prefix(&sourcedir).unwrap().to_str().unwrap().starts_with(".")
        }) {
        trace!("file: {:#?}", file.path());

        let project = file.path()
            .clone()
            .strip_prefix(&sourcedir)
            .unwrap()
            .with_extension("")
            .to_str()
            .unwrap()
            .replace("/", PROJECT_SEPPERATOR);

        info!("Migrating project {}", project);

        let mut rdr =
            csv::Reader::from_file(file.path()).unwrap().has_headers(false).flexible(true);
        for record in rdr.decode() {
            let (entry_type, time_stamp_raw, value): (String, String, String) = record.unwrap();

            trace!("entry_type: {}", entry_type);
            trace!("time_stamp_raw: {}", time_stamp_raw);
            trace!("value: {}", value);

            if entry_type != "note" {
                continue;
            }

            let time_stamp = time_stamp_raw.as_str().parse().unwrap();

            let note = Note {
                time_stamp: time_stamp,
                value: value,
            };
            trace!("datadir: {:#?}", datadir);
            trace!("project: {:#?}", project);
            trace!("note: {:#?}", note);

            write_note(&datadir, project.as_str(), note);
        }

        let mut rdr =
            csv::Reader::from_file(file.path()).unwrap().has_headers(false).flexible(true);
        for record in rdr.decode() {
            match record {
                Ok(_) => {}
                Err(_) => continue,
            };

            let (entry_type, time_stamp_raw, value1, value2): (String, String, String, String) =
                record.unwrap();

            trace!("entry_type: {}", entry_type);
            trace!("time_stamp_raw: {}", time_stamp_raw);
            trace!("value1: {}", value1);
            trace!("value2: {}", value2);

            if entry_type != "todo" {
                warn!("Don't know how to parse this entry type: {}", entry_type);
                continue;
            }

            let time_stamp = time_stamp_raw.as_str().parse().unwrap();

            let todo = Note {
                time_stamp: time_stamp,
                value: format!("TODO:: {}", value2),
            };
            trace!("datadir: {:#?}", datadir);
            trace!("project: {:#?}", project);
            trace!("todo: {:#?}", todo);

            write_note(&datadir, project.as_str(), todo);
        }
    }
}

fn get_datadir(args: &Args) -> PathBuf {
    let datadir = match args.value_of("datadir").unwrap() {
        "$XDG_DATA_HOME/lablog" => {
            let xdg = BaseDirectories::new().unwrap();
            xdg.create_data_directory("lablog").unwrap()
        }
        _ => PathBuf::from(args.value_of("datadir").unwrap()),
    };
    debug!("datadir: {:?}", datadir);
    datadir
}

fn add_note(args: Args) {
    trace!("add_note args: {:#?}", args);
    let datadir = get_datadir(&args);
    let text = args.value_of("text").unwrap();
    let project = args.value_of("project").unwrap();
    debug!("project: {}", project);
    debug!("text: {}", text);

    let note = Note {
        time_stamp: UTC::now().into(),
        value: text.into(),
    };

    write_note(&datadir, project, note)
}

fn list_notes(args: Args) {
    trace!("list_notes args: {:#?}", args);
    let datadir = get_datadir(&args);
    let project_arg = args.value_of("project").unwrap();
    debug!("project_arg: {}", project_arg);

    let projects = match project_arg {
        "" => get_projects(&datadir),
        _ => {
            let mut out = Set::default();
            out.insert(project_arg.into());
            out
        }
    };

    let project_notes = get_projects_notes(&datadir, &projects);

    trace!("project_notes: {:#?}", project_notes);

    for (project, notes) in project_notes {
        println!("= {}", project);
        for (time_stamp, note) in notes {
            println!("== {}\n{}\n", time_stamp, note.value)
        }
    }
}

fn get_projects_notes<'a>(datadir: &PathBuf,
                          projects: &'a Set<String>)
                          -> Map<&'a str, Map<DateTime<UTC>, Note>> {
    let mut map = Map::default();

    for project in projects.iter().map(|x| x.as_str()) {
        let mut project_path = datadir.clone();
        project_path.push(normalize_project_path(project));

        let notes = get_notes(project_path);
        map.insert(project.clone(), notes);
    }

    map
}

fn list_projects(args: Args) {
    trace!("list_projects args: {:#?}", args);
    let datadir = get_datadir(&args);

    let projects = get_projects(&datadir);
    trace!("projects: {:#?}", projects);

    for project in projects {
        println!("{}", project)
    }
}

fn get_projects(datadir: &PathBuf) -> Set<String> {
    let ok_walkdir: Vec<walkdir::DirEntry> = WalkDir::new(&datadir)
        .into_iter()
        .filter_map(|e| e.ok())
        .collect();

    trace!("ok_walkdir: {:#?}", ok_walkdir);

    let stripped_paths: Vec<PathBuf> = ok_walkdir.iter()
        .filter(|e| e.path().is_file())
        .filter(|e| match e.path().extension() {
            Some(ext) => ext.to_str().unwrap() == "csv",
            None => false,
        })
        .map(|e| e.path().strip_prefix(&datadir))
        .filter_map(|e| e.ok())
        .filter(|e| !e.to_str().unwrap().starts_with("."))
        .map(|e| e.with_extension(""))
        .collect();

    trace!("stripped_paths: {:#?}", stripped_paths);

    let projects = stripped_paths.into_iter()
        .map(|e| e.to_str().unwrap().replace("/", PROJECT_SEPPERATOR))
        .collect();

    trace!("projects: {:#?}", projects);

    projects
}

fn get_notes(project_path: PathBuf) -> Map<DateTime<UTC>, Note> {
    let mut map = Map::default();
    let mut rdr = csv::Reader::from_file(project_path).unwrap().has_headers(false);

    for record in rdr.decode() {
        let note: Note = record.unwrap();

        trace!("note: {:#?}", note);

        map.insert(note.time_stamp, note);
    }

    map
}

fn normalize_project_path(project: &str) -> String {
    format!("{}.csv", project.replace(".", "/").as_str())
}

fn write_note(datadir: &PathBuf, project: &str, note: Note) {
    if note.value == "" {
        warn!("Note with empty value");
        return;
    }

    let mut project_path = datadir.clone();
    project_path.push(normalize_project_path(project));

    trace!("project_path: {:#?}", project_path);
    fs::create_dir_all(project_path.parent().unwrap()).unwrap();

    let mut file = match OpenOptions::new().append(true).open(&project_path) {
        Ok(file) => file,
        Err(_) => OpenOptions::new().append(true).create(true).open(&project_path).unwrap(),
    };

    let mut wtr = csv::Writer::from_memory();
    wtr.encode(note).unwrap();
    file.write_fmt(format_args!("{}", wtr.as_string())).unwrap();
}

#[derive(Debug,RustcEncodable,RustcDecodable)]
struct Note {
    time_stamp: DateTime<UTC>,
    value: String,
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate iron_vhosts;
extern crate handlebars_iron as hbs;
extern crate router;
extern crate rustc_serialize;
extern crate modules;
extern crate mount;
extern crate staticfile;

use iron::prelude::*;
use iron::{status};
use iron::middleware::AfterMiddleware;
use iron::headers::{ContentType};
use iron::modifiers::Header;
use iron::mime::{Mime, TopLevel, SubLevel};
use iron_vhosts::Vhosts;
use hbs::{Template, HandlebarsEngine }; //, Watchable}; // Watchable doesn't appear to work 100%
use mount::Mount;
use staticfile::Static;
use rustc_serialize::json::{ToJson, Json};
use router::{Router};
use std::collections::BTreeMap;
use std::error::Error;
use std::sync::Arc;
use std::path::Path;

fn make_data () -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();
    data.insert("year".to_string(), "2015".to_json());
    data
}

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = make_data();
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

struct FourOhFour;

impl AfterMiddleware for FourOhFour {
    fn after(&self, _: &mut Request, res: Response) -> IronResult<Response> {
        //do nothing 'cause we dont care
        Ok(res)
    }

    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        match err.description() {
            "No Route" => {
                let header = Header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
                Ok(Response::with((status::NotFound, header, "<title>File not found</title>Could not find the requested URL.")))}
            ,
            _ => Err(err)
        }
    }
}

fn main () {
    //Default handler passed to new
    let mut vhosts = Vhosts::new(|_: &mut Request| Ok(Response::with((status::Ok, "vhost"))));

    //Add any host specific handlers
    vhosts.add_host("localhost", hello_world);
    let mut mount = Mount::new();
    mount.mount("/",Static::new(Path::new("media")));
    vhosts.add_host("media", mount);

    //initialize modules and their routes
    let mut router = Router::new();
    modules::init(&mut router);

    vhosts.add_host("myapp", router);

    let mut chain = Chain::new(vhosts);
    let template_engine_ref = Arc::new(HandlebarsEngine::new("./templates/", ".hbs"));
    //template_engine_ref.watch();

    chain.link_after(template_engine_ref);
    chain.link_after(FourOhFour);

    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>multiple servers on differnt ports working<commit_after>extern crate iron;
extern crate iron_vhosts;
extern crate handlebars_iron as hbs;
extern crate router;
extern crate rustc_serialize;
extern crate modules;
extern crate mount;
extern crate staticfile;

use iron::prelude::*;
use iron::{status};
use iron::middleware::AfterMiddleware;
use iron::headers::{ContentType};
use iron::modifiers::Header;
use iron::mime::{Mime, TopLevel, SubLevel};
use iron_vhosts::Vhosts;
use hbs::{Template, HandlebarsEngine }; //, Watchable}; // Watchable doesn't appear to work 100%
use mount::Mount;
use staticfile::Static;
use rustc_serialize::json::{ToJson, Json};
use router::{Router};
use std::collections::BTreeMap;
use std::error::Error;
use std::sync::Arc;
use std::path::Path;
use std::thread;

fn make_data () -> BTreeMap<String, Json> {
    let mut data = BTreeMap::new();
    data.insert("year".to_string(), "2015".to_json());
    data
}

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = make_data();
    resp.set_mut(Template::new("index", data)).set_mut(status::Ok);
    Ok(resp)
}

struct FourOhFour;

impl AfterMiddleware for FourOhFour {
    fn after(&self, _: &mut Request, res: Response) -> IronResult<Response> {
        //do nothing 'cause we dont care
        Ok(res)
    }

    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        match err.description() {
            "No Route" => {
                let header = Header(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
                Ok(Response::with((status::NotFound, header, "<title>File not found</title>Could not find the requested URL.")))}
            ,
            _ => Err(err)
        }
    }
}

fn create_server() -> Iron<Chain> {
    //Default handler passed to new
    let mut vhosts = Vhosts::new(|_: &mut Request| Ok(Response::with((status::Ok, "vhost"))));

    //Add any host specific handlers
    vhosts.add_host("localhost", hello_world);
    let mut mount = Mount::new();
    mount.mount("/",Static::new(Path::new("media")));
    vhosts.add_host("media", mount);

    //initialize modules and their routes
    let mut router = Router::new();
    modules::init(&mut router);

    vhosts.add_host("myapp", router);

    let mut chain = Chain::new(vhosts);
    let template_engine_ref = Arc::new(HandlebarsEngine::new("./templates/", ".hbs"));
    //template_engine_ref.watch();

    chain.link_after(template_engine_ref);
    chain.link_after(FourOhFour);

    Iron::new(chain)
}

fn main () {

    let servers = vec!["localhost:3000", "localhost:3001"];
    let mut processes = Vec::new();

    for server in servers {
        let child = thread::spawn(move || {
            let iron = create_server();
            println!("Server running at {}", server);
            iron.http(server).unwrap();
        });
        processes.push(child);
    }

    for process in processes {
        match process.join() {
            Ok(_) => println!("Ran successfully"),
            Err(_) => println!("nope not even once")
        }
    }
}
<|endoftext|>


<commit_before>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

#[cfg(not(test))]
extern crate rustwlc;

extern crate getopts;

#[cfg(test)]
extern crate dummy_rustwlc as rustwlc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;
extern crate rustc_serialize;
#[macro_use]
extern crate json_macro;

extern crate nix;

extern crate petgraph;

extern crate uuid;

#[macro_use]
extern crate wayland_client;

extern crate tempfile;

extern crate byteorder;

use std::env;
use getopts::Options;
use log::LogLevel;

use nix::sys::signal::{SigHandler, SigSet, SigAction, SaFlags};
use nix::sys::signal;

use rustwlc::types::LogType;

#[macro_use] // As it happens, it's important to declare the macros first.
mod macros;
mod convert;

mod callbacks;
mod keys;

mod lua;
mod registry;
mod commands;
mod ipc;

mod layout;
mod compositor;
mod background;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    let color = match record.level() {
        LogLevel::Info => "",
        LogLevel::Trace => "\x1B[37m",
        LogLevel::Debug => "\x1B[37m",
        LogLevel::Warn =>  "\x1B[33m",
        LogLevel::Error => "\x1B[31m",
    };
    let location = record.location();
    let file = location.file();
    let line = location.line();
    let mut module_path = location.module_path();
    if let Some(index) = module_path.find("way_cooler::") {
        let index = index + "way_cooler::".len();
        module_path = &module_path[index..];
    }
    format!("{} {} [{}] \x1B[37m{}:{}\x1B[0m{0} {} \x1B[0m",
            color, record.level(), module_path, file, line, record.args())
}

/// Initializes the logging system.
/// Can be called from within test methods.
pub fn init_logs() {
    // Prepare log builder
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").expect("Asserted unwrap!"));
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handlers.");
}

/// Handler for signals, should close the ipc
extern "C" fn sig_handle(_: nix::libc::c_int) {
    rustwlc::terminate();
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("", "version", "get the version of Way Cooler");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f.to_string());
            std::process::exit(1);
        }
    };
    if matches.opt_present("version") {
        println!("{}", VERSION);
        return
    }
    println!("Launching way-cooler...");

    let sig_action = SigAction::new(SigHandler::Handler(sig_handle), SaFlags::empty(), SigSet::empty());
    unsafe {signal::sigaction(signal::SIGINT, &sig_action).unwrap() };

    // Start logging first
    init_logs();

    // Initialize callbacks
    callbacks::init();

    // Handle wlc logs
    rustwlc::log_set_rust_handler(log_handler);

    // Prepare to launch wlc
    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    // (Future config initialization goes here)
    // Initialize commands
    commands::init();
    // Add API to registry
    registry::init();
    // Register Alt+Esc keybinding
    keys::init();
    // Start listening for clients
    let _ipc = ipc::init();

    // Hand control over to wlc's event loop
    info!("Running wlc...");
    run_wlc();
}
<commit_msg>Improve version output<commit_after>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

#[cfg(not(test))]
extern crate rustwlc;

extern crate getopts;

#[cfg(test)]
extern crate dummy_rustwlc as rustwlc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;
extern crate rustc_serialize;
#[macro_use]
extern crate json_macro;

extern crate nix;

extern crate petgraph;

extern crate uuid;

#[macro_use]
extern crate wayland_client;

extern crate tempfile;

extern crate byteorder;

use std::env;
use getopts::Options;
use log::LogLevel;

use nix::sys::signal::{SigHandler, SigSet, SigAction, SaFlags};
use nix::sys::signal;

use rustwlc::types::LogType;

#[macro_use] // As it happens, it's important to declare the macros first.
mod macros;
mod convert;

mod callbacks;
mod keys;

mod lua;
mod registry;
mod commands;
mod ipc;

mod layout;
mod compositor;
mod background;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    let color = match record.level() {
        LogLevel::Info => "",
        LogLevel::Trace => "\x1B[37m",
        LogLevel::Debug => "\x1B[37m",
        LogLevel::Warn =>  "\x1B[33m",
        LogLevel::Error => "\x1B[31m",
    };
    let location = record.location();
    let file = location.file();
    let line = location.line();
    let mut module_path = location.module_path();
    if let Some(index) = module_path.find("way_cooler::") {
        let index = index + "way_cooler::".len();
        module_path = &module_path[index..];
    }
    format!("{} {} [{}] \x1B[37m{}:{}\x1B[0m{0} {} \x1B[0m",
            color, record.level(), module_path, file, line, record.args())
}

/// Initializes the logging system.
/// Can be called from within test methods.
pub fn init_logs() {
    // Prepare log builder
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").expect("Asserted unwrap!"));
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handlers.");
}

/// Handler for signals, should close the ipc
extern "C" fn sig_handle(_: nix::libc::c_int) {
    rustwlc::terminate();
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("", "version", "show version information");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f.to_string());
            std::process::exit(1);
        }
    };
    if matches.opt_present("version") {
        println!("Way Cooler {}", VERSION);
        println!("Way Cooler IPC version {}", ipc::VERSION);
        return
    }
    println!("Launching way-cooler...");

    let sig_action = SigAction::new(SigHandler::Handler(sig_handle), SaFlags::empty(), SigSet::empty());
    unsafe {signal::sigaction(signal::SIGINT, &sig_action).unwrap() };

    // Start logging first
    init_logs();

    // Initialize callbacks
    callbacks::init();

    // Handle wlc logs
    rustwlc::log_set_rust_handler(log_handler);

    // Prepare to launch wlc
    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    // (Future config initialization goes here)
    // Initialize commands
    commands::init();
    // Add API to registry
    registry::init();
    // Register Alt+Esc keybinding
    keys::init();
    // Start listening for clients
    let _ipc = ipc::init();

    // Hand control over to wlc's event loop
    info!("Running wlc...");
    run_wlc();
}
<|endoftext|>


<commit_before>/*
                    License stuff
----------------------------------------------------------
Copyright 2013 Joris Rehm

Licensed under the Apache License, Version 2.0.
Licensed under The MIT License.

See joined files "LICENSE-APACHE" and "LICENSE-MIT".
----------------------------------------------------------
*/

/* ----------------------------------------------------------- */

struct FunctionalTable<C> {
  priv name : ~str,
  priv map : ~std::hashmap::HashMap<Entity, C>
}

impl<C : ToStr + Clone> FunctionalTable<C> {

  fn new(name : ~str) -> FunctionalTable<C>{
    info!("create_table name={}",name);
    FunctionalTable{
      name : name,
      map : ~std::hashmap::HashMap::new()
    }
  }

  fn set(&mut self, e : Entity, v : C) {
    info!("set id={} cmpt={} val={}", e, self.name, v.to_str() );
    self.map.swap(e,v);
  }

  /* fail if the entity e does not have a component */
  fn get<'a>(&'a self, e : Entity) -> &'a C {
    self.map.get(&e)
  }

  /* TODO create an own iterator type (or re-use some trait) */
  fn iter<'a>(&'a self) -> std::hashmap::HashMapIterator<'a, Entity, C> {
    self.map.iter()
  }

  fn apply(&mut self, f : &fn(Entity, &C) -> C) {
    let copy = self.map.clone();
    // TODO do I really need to copy all the map ?
    for (&e,c) in copy.iter() {
      let new_c = f(e, c);
      info!("set id={} cmpt={} val={}", e, self.name, new_c.to_str() );
      self.map.swap(e, new_c);
    }
  }

}

#[test]
fn test_FunctionalTable_get_set(){
  let mut table : FunctionalTable<Vec> = FunctionalTable::new(~"test");
  let vec = Vec(12., 56., 3.);
  let e1 = 42;
  table.set(e1,vec);
  assert!( vec == *table.get(e1) );
}

/* ----------------------------------------------------------- */

/* We need a type for the entities, which is just an identifier. */
type Entity = uint;

/* Let's defining a data structure for managing our ECS. */
struct Manager {
  /* There is a data to remember the numbers of created entities. */
  priv entities_numbers : uint
}

impl Manager {
  /* Inializing an empty ECS */
  fn new() -> ~Manager {
    ~Manager {
      entities_numbers : 0
    }
  }

  /* Creating an new entity is just taking a unused id. */
  fn new_entity(&mut self) -> Entity {
    let res = self.entities_numbers;
    self.entities_numbers = self.entities_numbers + 1;
    info!("create_entity id={}", res);
    res
  }

  /* TODO: how to manage the deletion of entities ?
     It depend if we iterate on entity id or on component tables.
     Maybe it's enought to delete the associated components.
     We may use a pool of unused id for recycling (probably not
     very needed) or just search for not associated id.*/

} /* impl Manager */

#[test]
fn test_entity_management() {
  let mut mng = Manager::new();
  let e1 = mng.new_entity();
  assert!( e1 == 0 );
  let e2 = mng.new_entity();
  assert!( e2 == 1 );
}

/* ----------------------------------------------------------- */

/* We're using double size float */
type MyFloat = f64;

/* Simple vector type for 3D position */
#[deriving(Eq,Clone)]
struct Vec(MyFloat, MyFloat, MyFloat);

impl ToStr for Vec {
  fn to_str(&self) -> ~str {
    let &Vec(x,y,z) = self;
    format!("({},{},{})", x, y, z)
  }
}

impl Add<Vec, Vec> for Vec {
  fn add(&self, rhs: &Vec) -> Vec {
    let &Vec(ax, ay, az) = self;
    let &Vec(bx, by, bz) = rhs;
    Vec(bx+ax, by+ay, bz+az)
  }
}

impl Sub<Vec, Vec> for Vec {
  fn sub(&self, rhs: &Vec) -> Vec{
    let &Vec(ax, ay, az) = self;
    let &Vec(bx, by, bz) = rhs;
    Vec(ax-bx, ay-by, az-bz)
  }
}

#[test]
fn test_add_vector(){
  let a = Vec(1., 2., 3.);
  let b = Vec(3., 2., 1.);
  let c = Vec(4., 4., 4.);
  assert!( a + b == c );
}

#[test]
fn test_sub_vector(){
  let a = Vec(1., 2., 3.);
  let b = Vec(3., 2., 1.);
  let c = Vec(4., 4., 4.);
  assert!( c - b == a);
}

impl Vec{
  // multiply by a scalar
  fn scale(&self, a: MyFloat) -> Vec {
    let Vec(sx, sy, sz) = *self;
    Vec(sx*a, sy*a, sz*a)
  }

  fn length(&self) -> MyFloat {
    let Vec(sx, sy, sz) = *self;
    (sx*sx + sy*sy + sz*sz).sqrt()
  }

  fn normalize(&self) -> Vec {
    let l = self.length();
    self.scale(1. / l)
  }

  fn is_nan(&self) -> bool {
    let Vec(sx, sy, sz) = *self;
    sx.is_nan() ||
    sy.is_nan() ||
    sz.is_nan()
  }

}

#[test]
fn test_scale_vector(){
  let a = Vec(1., 2., 3.);
  let b : MyFloat = 10.;
  let c = Vec(10., 20., 30.);
  assert!( a.scale(b) == c );
}

#[test]
fn test_length_vector(){
  let a = Vec(2., 2., 1.);
  assert!( a.length() == 3. );
}

#[test]
fn test_norm_vector(){
  let a = Vec(0., 2., 0.);
  let b = Vec(0., 1., 0.);
  assert!( a.normalize() == b );
}

/* ----------------------------------------------------------- */

fn main(){
  let mut mng = Manager::new();
  let mut table_position = FunctionalTable::new(~"position");
  let mut table_velocity = FunctionalTable::new(~"velocity");
  let mut table_acceleration = FunctionalTable::new(~"acceleration");
  let mut table_mass = FunctionalTable::new(~"mass");
  let zero = Vec(0., 0., 0.);
  let vec_1x = Vec(1.,0.,0.);
  let vec_1y = Vec(0.,1.,0.);
  let delta_time = 1./24. as MyFloat;
  let earth_gravity = 9.80665; // in m/s²

  // TODO I'm not very happy to use lambda just for
  // accessing the data.

  let gravity_force_at = |pos: Vec| {
    let planet_center = Vec(0.,0.,0.);

    // the vector from planet center to the pos
    let pos_from_planet = pos - planet_center;
    // TODO and yes it's useless :)

    let dist = pos_from_planet.length();

    let gravity_force =
      pos_from_planet.normalize(
      ).scale(- earth_gravity
      ).scale(1./(dist*dist));

    if gravity_force.is_nan() {
      Vec(0.,0.,0.)
    } else {
      gravity_force
    }

  };

  // Having an acceleration imply having a velocity!
  // Having an acceleration imply having a mass!
  let compute_acceleration = || {
    let fun = |e, accel: &Vec| {
      // note: accel not used
      let pos = table_position.get(e);
      let force = gravity_force_at(*pos);
      let mass = *table_mass.get(e);
      force.scale(1./mass)
    };
    table_acceleration.apply(fun);
  };

  // TODO define an integration function and refactor
  // compute_velocity and compute_position.

  // integration of acceleration
  // having a acceleration imply having a velocity
  let compute_velocity = |dt| {
    for x in table_acceleration.iter() {
      let (&e,accel) : (&Entity,&Vec) = x;
      let vel : Vec = *table_velocity.get(e);
      let new_vel = vel + accel.scale(dt);
      table_velocity.set(e, new_vel);
    }
  };

  /* Move all the entities with the velocity applied during dt time.
   Having a velocity imply having a position! */
  let compute_position = |dt| {
    for x in table_velocity.iter() {
      let (&e,vel) : (&Entity,&Vec) = x;
      let pos = *table_position.get(e);
      let new_pos = pos + vel.scale(dt);
      table_position.set(e, new_pos);
    }
  };

  let entity1 = mng.new_entity();
  table_position.set(entity1, vec_1y.scale(10.) );
  table_velocity.set(entity1, vec_1x.scale(10.) );
  table_acceleration.set(entity1, zero);
  table_mass.set(entity1, 1.);

  println("use RUST_LOG=3 to see log");
  for cycle in range(1u, 25) {
    println!("start_cycle {}",cycle);
    compute_acceleration();
    compute_velocity(delta_time);
    compute_position(delta_time);
  }

}
<commit_msg>use sdl library to open a window (compile rust-sdl lib.rs and add to -L path)<commit_after>/*
                    License stuff
----------------------------------------------------------
Copyright 2013 Joris Rehm

Licensed under the Apache License, Version 2.0.
Licensed under The MIT License.

See joined files "LICENSE-APACHE" and "LICENSE-MIT".
----------------------------------------------------------
*/

extern mod sdl;

/* ----------------------------------------------------------- */

struct FunctionalTable<C> {
  priv name : ~str,
  priv map : ~std::hashmap::HashMap<Entity, C>
}

impl<C : ToStr + Clone> FunctionalTable<C> {

  fn new(name : ~str) -> FunctionalTable<C>{
    info!("create_table name={}",name);
    FunctionalTable{
      name : name,
      map : ~std::hashmap::HashMap::new()
    }
  }

  fn set(&mut self, e : Entity, v : C) {
    info!("set id={} cmpt={} val={}", e, self.name, v.to_str() );
    self.map.swap(e,v);
  }

  /* fail if the entity e does not have a component */
  fn get<'a>(&'a self, e : Entity) -> &'a C {
    self.map.get(&e)
  }

  /* TODO create an own iterator type (or re-use some trait) */
  fn iter<'a>(&'a self) -> std::hashmap::HashMapIterator<'a, Entity, C> {
    self.map.iter()
  }

  fn apply(&mut self, f : &fn(Entity, &C) -> C) {
    let copy = self.map.clone();
    // TODO do I really need to copy all the map ?
    for (&e,c) in copy.iter() {
      let new_c = f(e, c);
      info!("set id={} cmpt={} val={}", e, self.name, new_c.to_str() );
      self.map.swap(e, new_c);
    }
  }

}

#[test]
fn test_FunctionalTable_get_set(){
  let mut table : FunctionalTable<Vec> = FunctionalTable::new(~"test");
  let vec = Vec(12., 56., 3.);
  let e1 = 42;
  table.set(e1,vec);
  assert!( vec == *table.get(e1) );
}

/* ----------------------------------------------------------- */

/* We need a type for the entities, which is just an identifier. */
type Entity = uint;

/* Let's defining a data structure for managing our ECS. */
struct Manager {
  /* There is a data to remember the numbers of created entities. */
  priv entities_numbers : uint
}

impl Manager {
  /* Inializing an empty ECS */
  fn new() -> ~Manager {
    ~Manager {
      entities_numbers : 0
    }
  }

  /* Creating an new entity is just taking a unused id. */
  fn new_entity(&mut self) -> Entity {
    let res = self.entities_numbers;
    self.entities_numbers = self.entities_numbers + 1;
    info!("create_entity id={}", res);
    res
  }

  /* TODO: how to manage the deletion of entities ?
     It depend if we iterate on entity id or on component tables.
     Maybe it's enought to delete the associated components.
     We may use a pool of unused id for recycling (probably not
     very needed) or just search for not associated id.*/

} /* impl Manager */

#[test]
fn test_entity_management() {
  let mut mng = Manager::new();
  let e1 = mng.new_entity();
  assert!( e1 == 0 );
  let e2 = mng.new_entity();
  assert!( e2 == 1 );
}

/* ----------------------------------------------------------- */

/* We're using double size float */
type MyFloat = f64;

/* Simple vector type for 3D position */
#[deriving(Eq,Clone)]
struct Vec(MyFloat, MyFloat, MyFloat);

impl ToStr for Vec {
  fn to_str(&self) -> ~str {
    let &Vec(x,y,z) = self;
    format!("({},{},{})", x, y, z)
  }
}

impl Add<Vec, Vec> for Vec {
  fn add(&self, rhs: &Vec) -> Vec {
    let &Vec(ax, ay, az) = self;
    let &Vec(bx, by, bz) = rhs;
    Vec(bx+ax, by+ay, bz+az)
  }
}

impl Sub<Vec, Vec> for Vec {
  fn sub(&self, rhs: &Vec) -> Vec{
    let &Vec(ax, ay, az) = self;
    let &Vec(bx, by, bz) = rhs;
    Vec(ax-bx, ay-by, az-bz)
  }
}

#[test]
fn test_add_vector(){
  let a = Vec(1., 2., 3.);
  let b = Vec(3., 2., 1.);
  let c = Vec(4., 4., 4.);
  assert!( a + b == c );
}

#[test]
fn test_sub_vector(){
  let a = Vec(1., 2., 3.);
  let b = Vec(3., 2., 1.);
  let c = Vec(4., 4., 4.);
  assert!( c - b == a);
}

impl Vec{
  // multiply by a scalar
  fn scale(&self, a: MyFloat) -> Vec {
    let Vec(sx, sy, sz) = *self;
    Vec(sx*a, sy*a, sz*a)
  }

  fn length(&self) -> MyFloat {
    let Vec(sx, sy, sz) = *self;
    (sx*sx + sy*sy + sz*sz).sqrt()
  }

  fn normalize(&self) -> Vec {
    let l = self.length();
    self.scale(1. / l)
  }

  fn is_nan(&self) -> bool {
    let Vec(sx, sy, sz) = *self;
    sx.is_nan() ||
    sy.is_nan() ||
    sz.is_nan()
  }

}

#[test]
fn test_scale_vector(){
  let a = Vec(1., 2., 3.);
  let b : MyFloat = 10.;
  let c = Vec(10., 20., 30.);
  assert!( a.scale(b) == c );
}

#[test]
fn test_length_vector(){
  let a = Vec(2., 2., 1.);
  assert!( a.length() == 3. );
}

#[test]
fn test_norm_vector(){
  let a = Vec(0., 2., 0.);
  let b = Vec(0., 1., 0.);
  assert!( a.normalize() == b );
}

/* ----------------------------------------------------------- */

fn test(){
  let mut mng = Manager::new();
  let mut table_position = FunctionalTable::new(~"position");
  let mut table_velocity = FunctionalTable::new(~"velocity");
  let mut table_acceleration = FunctionalTable::new(~"acceleration");
  let mut table_mass = FunctionalTable::new(~"mass");
  let zero = Vec(0., 0., 0.);
  let vec_1x = Vec(1.,0.,0.);
  let vec_1y = Vec(0.,1.,0.);
  let delta_time = 1./24. as MyFloat;
  let earth_gravity = 9.80665; // in m/s²

  // TODO I'm not very happy to use lambda just for
  // accessing the data.

  let gravity_force_at = |pos: Vec| {
    let planet_center = Vec(0.,0.,0.);

    // the vector from planet center to the pos
    let pos_from_planet = pos - planet_center;
    // TODO and yes it's useless :)

    let dist = pos_from_planet.length();

    let gravity_force =
      pos_from_planet.normalize(
      ).scale(- earth_gravity
      ).scale(1./(dist*dist));

    if gravity_force.is_nan() {
      Vec(0.,0.,0.)
    } else {
      gravity_force
    }

  };

  // Having an acceleration imply having a velocity!
  // Having an acceleration imply having a mass!
  let compute_acceleration = || {
    let fun = |e, accel: &Vec| {
      // note: accel not used
      let pos = table_position.get(e);
      let force = gravity_force_at(*pos);
      let mass = *table_mass.get(e);
      force.scale(1./mass)
    };
    table_acceleration.apply(fun);
  };

  // TODO define an integration function and refactor
  // compute_velocity and compute_position.

  // integration of acceleration
  // having a acceleration imply having a velocity
  let compute_velocity = |dt| {
    for x in table_acceleration.iter() {
      let (&e,accel) : (&Entity,&Vec) = x;
      let vel : Vec = *table_velocity.get(e);
      let new_vel = vel + accel.scale(dt);
      table_velocity.set(e, new_vel);
    }
  };

  /* Move all the entities with the velocity applied during dt time.
   Having a velocity imply having a position! */
  let compute_position = |dt| {
    for x in table_velocity.iter() {
      let (&e,vel) : (&Entity,&Vec) = x;
      let pos = *table_position.get(e);
      let new_pos = pos + vel.scale(dt);
      table_position.set(e, new_pos);
    }
  };

  let entity1 = mng.new_entity();
  table_position.set(entity1, vec_1y.scale(10.) );
  table_velocity.set(entity1, vec_1x.scale(10.) );
  table_acceleration.set(entity1, zero);
  table_mass.set(entity1, 1.);

  println("use RUST_LOG=3 to see log");
  for cycle in range(1u, 25) {
    println!("start_cycle {}",cycle);
    compute_acceleration();
    compute_velocity(delta_time);
    compute_position(delta_time);
  }

}

#[main]
pub fn main() {
    sdl::init([sdl::InitVideo]);
    sdl::wm::set_caption("Bouncing Balls On a Big Ball", "Bobobib");

    let screen = match sdl::video::set_video_mode
      (800, 600, 32, [sdl::video::HWSurface],[sdl::video::DoubleBuf]) {
        Ok(screen) => screen,
        Err(err) => fail!("Impossible to open screen: {}", err)
    };

    'main : loop {
        'event : loop {
            match sdl::event::poll_event() {
                sdl::event::QuitEvent => break 'main,
                sdl::event::NoEvent => break 'event,
                sdl::event::KeyEvent(k, _, _, _)
                    if k == sdl::event::EscapeKey
                        => break 'main,
                _ => {}
            }
        }
        screen.flip();
    }

    sdl::quit();
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]
#![allow(dead_code)]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate nom;
#[macro_use]
extern crate quick_error;
extern crate walkdir;

use std::env;
use std::path::{Path, PathBuf};

mod error;
mod file;
mod parser;
mod questions;
mod stamp;
mod template;
mod template_file;

use clap::{App, AppSettings};

use error::Error;

fn run() -> Result<(), Error> {
    let yaml = load_yaml!("cli.yaml");
    let matches = App::from_yaml(yaml)
        .setting(AppSettings::ArgRequiredElseHelp)
        .get_matches();

    let source_arg = matches.value_of("source").ok_or(Error::SourceNotProvided)?;
    let dest_arg = matches.value_of("destination").unwrap_or("");

    let source = stamp::find_stamp(Path::new(source_arg))?;
    let dest = find_destination(dest_arg)?;

    println!("{:?}", dest);

    let files = file::read_all_files(&source)?;
    let (templates, vars) = stamp::compile_templates(&files);

    let conf = questions::get_vars(&vars)?;
    let rendered = stamp::render_templates(&templates, &conf)?;

    stamp::write_files(&dest, &rendered)?;

    Ok(())
}

fn find_destination(dest_arg: &str) -> Result<PathBuf, Error> {
    let path = Path::new(dest_arg).to_owned();
    if path.is_relative() {
        Ok(env::current_dir()?.join(&path))
    } else {
        Ok(path)
    }
}

fn main() {
    run().unwrap()
}
<commit_msg>Remove debugging code<commit_after>#![allow(unused_variables)]
#![allow(dead_code)]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate nom;
#[macro_use]
extern crate quick_error;
extern crate walkdir;

use std::env;
use std::path::{Path, PathBuf};

mod error;
mod file;
mod parser;
mod questions;
mod stamp;
mod template;
mod template_file;

use clap::{App, AppSettings};

use error::Error;

fn run() -> Result<(), Error> {
    let yaml = load_yaml!("cli.yaml");
    let matches = App::from_yaml(yaml)
        .setting(AppSettings::ArgRequiredElseHelp)
        .get_matches();

    let source_arg = matches.value_of("source").ok_or(Error::SourceNotProvided)?;
    let dest_arg = matches.value_of("destination").unwrap_or("");

    let source = stamp::find_stamp(Path::new(source_arg))?;
    let dest = find_destination(dest_arg)?;

    let files = file::read_all_files(&source)?;
    let (templates, vars) = stamp::compile_templates(&files);

    let conf = questions::get_vars(&vars)?;
    let rendered = stamp::render_templates(&templates, &conf)?;

    stamp::write_files(&dest, &rendered)?;

    Ok(())
}

fn find_destination(dest_arg: &str) -> Result<PathBuf, Error> {
    let path = Path::new(dest_arg).to_owned();
    if path.is_relative() {
        Ok(env::current_dir()?.join(&path))
    } else {
        Ok(path)
    }
}

fn main() {
    run().unwrap()
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{BufReader, BufRead};

extern crate git2;
extern crate glob;
extern crate rustc_serialize;
extern crate tiny_http;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";
static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct CrateInfo {
    name: String,
    vers: String,
    deps: Vec<DepInfo>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct DepInfo {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>
}

fn build_dependency_map() -> HashMap<String, Vec<String>> {
    let mut match_options = glob::MatchOptions::new();
    match_options.require_literal_leading_dot = true;

    let index_paths1 = glob::glob_with("crates.io-index/*/*/*", &match_options).unwrap();
    let index_paths2 = glob::glob_with("crates.io-index/[12]/*", &match_options).unwrap();

    let index_paths = index_paths1.chain(index_paths2);

    let mut map = HashMap::new();

    for glob_result in index_paths {
        let index_path = glob_result.unwrap();
        let file = fs::File::open(&index_path).unwrap();
        let last_line = BufReader::new(file).lines().last().unwrap().unwrap();
        let crate_info: CrateInfo = rustc_serialize::json::decode(&last_line).unwrap();
        let deps_names = crate_info.deps.iter().map(|d| d.name.clone()).collect();
        map.insert(crate_info.name, deps_names);
    }

    map
}

fn main() {
    if fs::metadata(INDEX_LOCAL_PATH).is_err() {
        println!("Cloning crates.io-index");
        git2::Repository::clone(INDEX_GIT_URL, INDEX_LOCAL_PATH).unwrap();
    }

    let dep_map = build_dependency_map();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for req in server.incoming_requests() {
        { println!("{}", req.get_url().trim_left_matches("/")) }
        let response = match dep_map.get(req.get_url().trim_left_matches("/")) {
            Some(d) => d.iter().fold(String::new(), |acc, item| acc + ", " + &item),
            None => String::from("could not find crate"),
        };

        let response = tiny_http::Response::from_string(response);
        req.respond(response);
    }
}
<commit_msg>Remove debugging<commit_after>use std::collections::HashMap;
use std::env;
use std::fs;
use std::io::{BufReader, BufRead};

extern crate git2;
extern crate glob;
extern crate rustc_serialize;
extern crate tiny_http;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";
static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct CrateInfo {
    name: String,
    vers: String,
    deps: Vec<DepInfo>,
    cksum: String,
    features: HashMap<String, Vec<String>>,
    yanked: bool,
}

#[derive(RustcDecodable)]
#[allow(dead_code)]
struct DepInfo {
    name: String,
    req: String,
    features: Vec<String>,
    optional: bool,
    default_features: bool,
    target: Option<String>,
    kind: Option<String>
}

fn build_dependency_map() -> HashMap<String, Vec<String>> {
    let mut match_options = glob::MatchOptions::new();
    match_options.require_literal_leading_dot = true;

    let index_paths1 = glob::glob_with("crates.io-index/*/*/*", &match_options).unwrap();
    let index_paths2 = glob::glob_with("crates.io-index/[12]/*", &match_options).unwrap();

    let index_paths = index_paths1.chain(index_paths2);

    let mut map = HashMap::new();

    for glob_result in index_paths {
        let index_path = glob_result.unwrap();
        let file = fs::File::open(&index_path).unwrap();
        let last_line = BufReader::new(file).lines().last().unwrap().unwrap();
        let crate_info: CrateInfo = rustc_serialize::json::decode(&last_line).unwrap();
        let deps_names = crate_info.deps.iter().map(|d| d.name.clone()).collect();
        map.insert(crate_info.name, deps_names);
    }

    map
}

fn main() {
    if fs::metadata(INDEX_LOCAL_PATH).is_err() {
        println!("Cloning crates.io-index");
        git2::Repository::clone(INDEX_GIT_URL, INDEX_LOCAL_PATH).unwrap();
    }

    let dep_map = build_dependency_map();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for req in server.incoming_requests() {
        let response = match dep_map.get(req.get_url().trim_left_matches("/")) {
            Some(d) => d.iter().fold(String::new(), |acc, item| acc + ", " + &item),
            None => String::from("could not find crate"),
        };

        let response = tiny_http::Response::from_string(response);
        req.respond(response);
    }
}
<|endoftext|>


<commit_before>extern crate reqwest;
extern crate select;
use std::io::Read;
use select::document::Document;
use select::predicate::{Name, Class};

fn scrape_crix_local() {
    // http://crix.hu-berlin.de/

    let document = Document::from(include_str!("../html/crix.html"));

    println!("Top 25 Cryptomonedas");
    for node in document.find(Class("currencies")).take(25) {
      let moneda = node.find(Class("currency-name")).next().unwrap();
      let precio = node.find(Class("price")).next().unwrap().text();
      println!(" Moneda: {} Precio: ${}", moneda.text(), precio);
    }
}

fn scrape_coinmarketcap_remote() {
    // https://coinmarketcap.com/
    let mut response = reqwest::get("https://coinmarketcap.com/").unwrap();
    assert!(response.status().is_success());

    let mut body = String::new();
    response.read_to_string(&mut body).expect("Read failed");

    let document = Document::from(body.as_str());
    for node in document.find(Name("tbody"))
        .next()
        .unwrap()
        .find(Name("tr"))
        .take(3)
    {
        let coin_name = node.find(Class("currency-name")).next().unwrap().text();
        let coin_price = node.find(Class("price")).next().unwrap().text();
        println!("{}:   {}", coin_name.trim(), coin_price.trim());
    }

}

fn main() {
    // Uncomment the function you want to use.

    // scrape_crix_local();
    // scrape_coinmarketcap_remote();

}<commit_msg>scrape_crix_local() function authorship.<commit_after>extern crate reqwest;
extern crate select;
use std::io::Read;
use select::document::Document;
use select::predicate::{Name, Class};

fn scrape_crix_local() {
    // This function by Abiel Parra (https://github.com/Heeled-Jim)

    // http://crix.hu-berlin.de/

    let document = Document::from(include_str!("../html/crix.html"));

    println!("Top 25 Cryptomonedas");
    for node in document.find(Class("currencies")).take(25) {
      let moneda = node.find(Class("currency-name")).next().unwrap();
      let precio = node.find(Class("price")).next().unwrap().text();
      println!(" Moneda: {} Precio: ${}", moneda.text(), precio);
    }
}

fn scrape_coinmarketcap_remote() {
    // https://coinmarketcap.com/
    let mut response = reqwest::get("https://coinmarketcap.com/").unwrap();
    assert!(response.status().is_success());

    let mut body = String::new();
    response.read_to_string(&mut body).expect("Read failed");

    let document = Document::from(body.as_str());
    for node in document.find(Name("tbody"))
        .next()
        .unwrap()
        .find(Name("tr"))
        .take(3)
    {
        let coin_name = node.find(Class("currency-name")).next().unwrap().text();
        let coin_price = node.find(Class("price")).next().unwrap().text();
        println!("{}:   {}", coin_name.trim(), coin_price.trim());
    }

}

fn main() {
    // Uncomment the function you want to use.

    // scrape_crix_local();
    // scrape_coinmarketcap_remote();

}<|endoftext|>


<commit_before>#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use rustc_tools_util::VersionInfo;

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
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

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

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if std::env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if std::env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(std::env::args().skip(2)) {
        std::process::exit(code);
    }
}

fn process<I>(mut old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let mut args = vec!["check".to_owned()];

    for arg in old_args.by_ref() {
        if arg == "--" {
            break;
        }
        args.push(arg);
    }

    let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

    let mut path = std::env::current_exe()
        .expect("current executable path invalid")
        .with_file_name("clippy-driver");
    if cfg!(windows) {
        path.set_extension("exe");
    }

    let target_dir = std::env::var_os("CLIPPY_DOGFOOD")
        .map(|_| {
            std::env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                || std::ffi::OsString::from("clippy_dogfood"),
                |d| {
                    std::path::PathBuf::from(d)
                        .join("target")
                        .join("dogfood")
                        .into_os_string()
                },
            )
        })
        .map(|p| ("CARGO_TARGET_DIR", p));

    // Run the dogfood tests directly on nightly cargo. This is required due
    // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
    if std::env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
        args.insert(0, "+nightly".to_string());
    }

    let exit_status = std::process::Command::new("cargo")
        .args(&args)
        .env("RUSTC_WRAPPER", path)
        .env("CLIPPY_ARGS", clippy_args)
        .envs(target_dir)
        .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>Auto merge of #5363 - yaahc:clippy-fix, r=phansch,flip1995<commit_after>#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use rustc_tools_util::VersionInfo;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::{self, Command};

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
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

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

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(env::args().skip(2)) {
        process::exit(code);
    }
}

struct ClippyCmd {
    unstable_options: bool,
    cargo_subcommand: &'static str,
    args: Vec<String>,
    clippy_args: String,
}

impl ClippyCmd {
    fn new<I>(mut old_args: I) -> Self
    where
        I: Iterator<Item = String>,
    {
        let mut cargo_subcommand = "check";
        let mut unstable_options = false;
        let mut args = vec![];

        for arg in old_args.by_ref() {
            match arg.as_str() {
                "--fix" => {
                    cargo_subcommand = "fix";
                    continue;
                },
                "--" => break,
                // Cover -Zunstable-options and -Z unstable-options
                s if s.ends_with("unstable-options") => unstable_options = true,
                _ => {},
            }

            args.push(arg);
        }

        if cargo_subcommand == "fix" && !unstable_options {
            panic!("Usage of `--fix` requires `-Z unstable-options`");
        }

        // Run the dogfood tests directly on nightly cargo. This is required due
        // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
        if env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
            args.insert(0, "+nightly".to_string());
        }

        let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

        ClippyCmd {
            unstable_options,
            cargo_subcommand,
            args,
            clippy_args,
        }
    }

    fn path_env(&self) -> &'static str {
        if self.unstable_options {
            "RUSTC_WORKSPACE_WRAPPER"
        } else {
            "RUSTC_WRAPPER"
        }
    }

    fn path() -> PathBuf {
        let mut path = env::current_exe()
            .expect("current executable path invalid")
            .with_file_name("clippy-driver");

        if cfg!(windows) {
            path.set_extension("exe");
        }

        path
    }

    fn target_dir() -> Option<(&'static str, OsString)> {
        env::var_os("CLIPPY_DOGFOOD")
            .map(|_| {
                env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                    || std::ffi::OsString::from("clippy_dogfood"),
                    |d| {
                        std::path::PathBuf::from(d)
                            .join("target")
                            .join("dogfood")
                            .into_os_string()
                    },
                )
            })
            .map(|p| ("CARGO_TARGET_DIR", p))
    }

    fn into_std_cmd(self) -> Command {
        let mut cmd = Command::new("cargo");

        cmd.env(self.path_env(), Self::path())
            .envs(ClippyCmd::target_dir())
            .env("CLIPPY_ARGS", self.clippy_args)
            .arg(self.cargo_subcommand)
            .args(&self.args);

        cmd
    }
}

fn process<I>(old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let cmd = ClippyCmd::new(old_args);

    let mut cmd = cmd.into_std_cmd();

    let exit_status = cmd
        .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))
    }
}

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

    #[test]
    #[should_panic]
    fn fix_without_unstable() {
        let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string);
        let _ = ClippyCmd::new(args);
    }

    #[test]
    fn fix_unstable() {
        let args = "cargo clippy --fix -Zunstable-options"
            .split_whitespace()
            .map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("fix", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
        assert!(cmd.args.iter().any(|arg| arg.ends_with("unstable-options")));
    }

    #[test]
    fn check() {
        let args = "cargo clippy".split_whitespace().map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("check", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WRAPPER", cmd.path_env());
    }

    #[test]
    fn check_unstable() {
        let args = "cargo clippy -Zunstable-options"
            .split_whitespace()
            .map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("check", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
    }
}
<|endoftext|>


<commit_before>#[crate_id = "rboy"];

extern crate native;
extern crate green;
extern crate extra;
extern crate getopts;
extern crate sync;
extern crate time;
extern crate sdl;

use cpu::CPU;
use sync::DuplexStream;
use sync::RWArc;

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;

static SCALE: int = 3;

#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }

fn main() {
	let args: ~[~str] = std::os::args();
	let program = args[0].clone() + " <filename>";

	let opts = ~[ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename: ~str = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		println!("{}", getopts::usage(program, opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE, 144*SCALE, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = sync::duplex();
	let rawscreen = ~[0x00u8,.. 160*144*3];
	let arc = RWArc::new(rawscreen);
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename, &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			std::comm::Disconnected => { break 'main },
			std::comm::Data(_) => recalculate_screen(screen, &arc),
			std::comm::Empty => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &RWArc<~[u8]>) {
	arc.read(|data|
		for y in range(0, 144) {
			for x in range(0, 160) {
				screen.fill_rect(
					Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
					sdl::video::RGB(data[y*160*3 + x*3 + 0],
					                data[y*160*3 + x*3 + 1],
					                data[y*160*3 + x*3 + 2])
				);
			}
		}
	);
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: RWArc<~[u8]>, filename: ~str, matches: &getopts::Matches) {
	let mut c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				arc.write(|data|
					for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				);
				channel.try_send(0);
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			std::comm::Data(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			std::comm::Empty => {},
			std::comm::Disconnected => { break },
		};
	}
}
<commit_msg>Revert the scale to original value<commit_after>#[crate_id = "rboy"];

extern crate native;
extern crate green;
extern crate extra;
extern crate getopts;
extern crate sync;
extern crate time;
extern crate sdl;

use cpu::CPU;
use sync::DuplexStream;
use sync::RWArc;

mod register;
mod mbc;
mod mmu;
mod cpu;
mod serial;
mod timer;
mod keypad;
mod gpu;
mod sound;
mod gbmode;

static SCALE: int = 2;

#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }

fn main() {
	let args: ~[~str] = std::os::args();
	let program = args[0].clone() + " <filename>";

	let opts = ~[ getopts::optflag("s", "serial", "Output serial to stdout"), getopts::optflag("c", "classic", "Force Classic mode") ];
	let matches = match getopts::getopts(args.tail(), opts) {
		Ok(m) => { m }
		Err(f) => { println!("{}", f.to_err_msg()); return }
	};

	let filename: ~str = if !matches.free.is_empty() {
		matches.free[0].clone()
	} else {
		println!("{}", getopts::usage(program, opts));
		return;
	};

	sdl::init([sdl::InitVideo]);
	sdl::wm::set_caption("RBoy - A gameboy in Rust", "rboy");
	let screen = match sdl::video::set_video_mode(160*SCALE, 144*SCALE, 32, [sdl::video::HWSurface], [sdl::video::DoubleBuf]) {
		Ok(screen) => screen,
		Err(err) => fail!("failed to open screen: {}", err),
	};

	let (sdlstream, cpustream) = sync::duplex();
	let rawscreen = ~[0x00u8,.. 160*144*3];
	let arc = RWArc::new(rawscreen);
	let arc2 = arc.clone();
	native::task::spawn(proc() cpuloop(&cpustream, arc2, filename, &matches));

	let mut timer = std::io::timer::Timer::new().unwrap();
	let periodic = timer.periodic(8);

	'main : loop {
		periodic.recv();
		match sdlstream.try_recv() {
			std::comm::Disconnected => { break 'main },
			std::comm::Data(_) => recalculate_screen(screen, &arc),
			std::comm::Empty => {},
		}
		'event : loop {
			match sdl::event::poll_event() {
				sdl::event::QuitEvent => break 'main,
				sdl::event::NoEvent => break 'event,
				sdl::event::KeyEvent(sdl::event::EscapeKey, _, _, _)
					=> break 'main,
				sdl::event::KeyEvent(sdl::event::LShiftKey, true, _, _)
					=> sdlstream.send(SpeedUp),
				sdl::event::KeyEvent(sdl::event::LShiftKey, false, _, _)
					=> sdlstream.send(SlowDown),
				sdl::event::KeyEvent(sdlkey, true, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyDown(key)),
						None => {},
					}
				},
				sdl::event::KeyEvent(sdlkey, false, _, _) => {
					match sdl_to_keypad(sdlkey) {
						Some(key) => sdlstream.send(KeyUp(key)),
						None => {},
					}
				},
				_ => {}
			}
		}
	}
}

fn sdl_to_keypad(key: sdl::event::Key) -> Option<keypad::KeypadKey> {
	match key {
		sdl::event::ZKey => Some(keypad::A),
		sdl::event::XKey => Some(keypad::B),
		sdl::event::UpKey => Some(keypad::Up),
		sdl::event::DownKey => Some(keypad::Down),
		sdl::event::LeftKey => Some(keypad::Left),
		sdl::event::RightKey => Some(keypad::Right),
		sdl::event::SpaceKey => Some(keypad::Select),
		sdl::event::ReturnKey => Some(keypad::Start),
		_ => None,
	}
}

fn recalculate_screen(screen: &sdl::video::Surface, arc: &RWArc<~[u8]>) {
	arc.read(|data|
		for y in range(0, 144) {
			for x in range(0, 160) {
				screen.fill_rect(
					Some(sdl::Rect { x: (x*SCALE) as i16, y: (y*SCALE) as i16, w: SCALE as u16, h: SCALE as u16 }),
					sdl::video::RGB(data[y*160*3 + x*3 + 0],
					                data[y*160*3 + x*3 + 1],
					                data[y*160*3 + x*3 + 2])
				);
			}
		}
	);
	screen.flip();
}

enum GBEvent {
	KeyUp(keypad::KeypadKey),
	KeyDown(keypad::KeypadKey),
	SpeedUp,
	SlowDown,
}

fn cpuloop(channel: &DuplexStream<uint, GBEvent>, arc: RWArc<~[u8]>, filename: ~str, matches: &getopts::Matches) {
	let mut c = match matches.opt_present("classic") {
		true => CPU::new(filename),
		false => CPU::new_cgb(filename),
	};
	c.mmu.serial.tostdout = matches.opt_present("serial");

	let mut timer = std::io::timer::Timer::new().unwrap();
	let mut periodic = timer.periodic(8);

	let waitticks = (4194.304 * 4.0) as uint;

	let mut ticks = 0;
	loop {
		while ticks < waitticks {
			ticks += c.cycle();
			if c.mmu.gpu.updated {
				c.mmu.gpu.updated = false;
				arc.write(|data|
					for i in range(0, data.len()) { data[i] = c.mmu.gpu.data[i]; }
				);
				channel.try_send(0);
			}
		}
		ticks -= waitticks;
		periodic.recv();

		match channel.try_recv() {
			std::comm::Data(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			std::comm::Empty => {},
			std::comm::Disconnected => { break },
		};
	}
}
<|endoftext|>