<commit_before>#![feature(globs)]

extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate "rustc-serialize" as rustc_serialize;

use rgtk::*;
use std::collections::HashSet;
use std::io::fs;
use std::io::fs::PathExtensions;

mod projects;
mod ui;
mod utils;

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

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
    }
}

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

    // constants

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

    // create the window

    let title = format!("SolidOak {}.{}.{}",
                        option_env!("CARGO_PKG_VERSION_MAJOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_MINOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_PATCH").unwrap());
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title(title.as_slice());
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

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

    // create the panes

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

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

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

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

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

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

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

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

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

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

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

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

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

    // populate the project tree

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

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

    // connect to the signals

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

    // show the window

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

fn receive_message (fd: ffi::c_int) -> bool {
    let mut buf : [ffi::c_uchar, ..1024] = [0, ..1024];
    let n = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut ffi::c_void, 1024) };
    if n < 0 {
        return false;
    } else if n > 0 {
        let msg = unsafe { ::std::string::String::from_raw_buf_len(buf.as_ptr(), n as uint) };
        let arr = neovim::deserialize_message(&msg);
        println!("Received: {}", arr);
    }

    true
}

fn main() {
    // create data dir
    let home_dir = ::utils::get_home_dir();
    let data_dir = home_dir.join(::utils::DATA_DIR);
    if !data_dir.exists() {
        match fs::mkdir(&data_dir, ::std::io::USER_DIR) {
            Ok(_) => {
                for res in ::utils::DATA_CONTENT.iter() {
                    let res_path = data_dir.join_many(res.path);
                    ::std::io::fs::mkdir_recursive(&res_path.dir_path(), ::std::io::USER_DIR).ok();
                    ::std::io::File::create(&res_path).write(res.data.as_bytes()).ok();
                }
                println!("Created data dir at {}", data_dir.as_str().unwrap());
            },
            Err(e) => { println!("Error creating data dir: {}", e) }
        }
    }

    // set $VIM to the data dir if it isn't already set
    if ::std::os::getenv("VIM").is_none() {
        ::std::os::setenv("VIM", data_dir.as_str().unwrap());
    }

    // create config file
    let config_file = home_dir.join(::utils::CONFIG_FILE);
    if !config_file.exists() {
        match ::std::io::File::create(&config_file).write(::utils::CONFIG_CONTENT.as_bytes()) {
            Ok(_) => { println!("Created config file at {}", config_file.as_str().unwrap()) },
            Err(e) => { println!("Error creating config file: {}", e) }
        }
    }

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

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

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

    if pid > 0 { // the gui process
        ::std::thread::Thread::spawn(move || {
            // send attach_ui message
            {
                let mut arr = neovim::Array::new();
                arr.add_integer(80);
                arr.add_integer(24);
                let msg = neovim::serialize_message(1, "attach_ui", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
            }
            receive_message(gui_from_nvim[0]);

            // send vim_command message
/*
            {
                let mut arr = neovim::Array::new();
                arr.add_string("");
                let msg = neovim::serialize_message(1, "vim_command", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
            }
            receive_message(gui_from_nvim[0]);
*/

            // listen for messages
            loop {
                if !receive_message(gui_from_nvim[0]) {
                    break;
                }
            }
        }).detach();

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

        // start nvim
        let mut args = ::std::os::args().clone();
        args.push_all(&["-u".to_string(), config_file.as_str().unwrap().to_string()]);
        neovim::main_setup(args);
        neovim::channel_from_fds(nvim_from_gui[0], gui_from_nvim[1]);
        neovim::main_loop();
    }
}
<commit_msg>Add example of subscribing to an event<commit_after>#![feature(globs)]

extern crate libc;
extern crate neovim;
extern crate rgtk;
extern crate "rustc-serialize" as rustc_serialize;

use rgtk::*;
use std::collections::HashSet;
use std::io::fs;
use std::io::fs::PathExtensions;

mod projects;
mod ui;
mod utils;

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

    extern "C" {
        pub fn fork () -> c_int;
        pub fn kill (pid: c_int, sig: c_int);
    }
}

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

    // constants

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

    // create the window

    let title = format!("SolidOak {}.{}.{}",
                        option_env!("CARGO_PKG_VERSION_MAJOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_MINOR").unwrap(),
                        option_env!("CARGO_PKG_VERSION_PATCH").unwrap());
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    window.set_title(title.as_slice());
    window.set_window_position(gtk::WindowPosition::Center);
    window.set_default_size(width, height);

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

    // create the panes

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

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

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

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

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

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

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

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

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

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

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

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

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

    // populate the project tree

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

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

    // connect to the signals

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

    // show the window

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

fn receive_message (fd: ffi::c_int) -> Option<neovim::Array> {
    let mut buf : [ffi::c_uchar, ..1024] = [0, ..1024];
    let n = unsafe { ffi::read(fd, buf.as_mut_ptr() as *mut ffi::c_void, 1024) };
    if n < 0 {
        return None;
    }
    let s = unsafe { ::std::string::String::from_raw_buf_len(buf.as_ptr(), n as uint) };
    Some(neovim::deserialize_message(&s))
}

fn main() {
    // create data dir
    let home_dir = ::utils::get_home_dir();
    let data_dir = home_dir.join(::utils::DATA_DIR);
    if !data_dir.exists() {
        match fs::mkdir(&data_dir, ::std::io::USER_DIR) {
            Ok(_) => {
                for res in ::utils::DATA_CONTENT.iter() {
                    let res_path = data_dir.join_many(res.path);
                    ::std::io::fs::mkdir_recursive(&res_path.dir_path(), ::std::io::USER_DIR).ok();
                    ::std::io::File::create(&res_path).write(res.data.as_bytes()).ok();
                }
                println!("Created data dir at {}", data_dir.as_str().unwrap());
            },
            Err(e) => { println!("Error creating data dir: {}", e) }
        }
    }

    // set $VIM to the data dir if it isn't already set
    if ::std::os::getenv("VIM").is_none() {
        ::std::os::setenv("VIM", data_dir.as_str().unwrap());
    }

    // create config file
    let config_file = home_dir.join(::utils::CONFIG_FILE);
    if !config_file.exists() {
        match ::std::io::File::create(&config_file).write(::utils::CONFIG_CONTENT.as_bytes()) {
            Ok(_) => { println!("Created config file at {}", config_file.as_str().unwrap()) },
            Err(e) => { println!("Error creating config file: {}", e) }
        }
    }

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

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

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

    if pid > 0 { // the gui process
        ::std::thread::Thread::spawn(move || {
            // send attach_ui message
            {
                let mut arr = neovim::Array::new();
                arr.add_integer(80);
                arr.add_integer(24);
                let msg = neovim::serialize_message(1, "attach_ui", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
                if let Some(recv_arr) = receive_message(gui_from_nvim[0]) {
                    println!("Received: {}", recv_arr);
                }
            }

            // send vim_subscribe message
            {
                let mut arr = neovim::Array::new();
                arr.add_string("bufread");
                let msg = neovim::serialize_message(1, "vim_subscribe", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
                if let Some(recv_arr) = receive_message(gui_from_nvim[0]) {
                    println!("Received: {}", recv_arr);
                }
            }

            // send vim_command message
            {
                let mut arr = neovim::Array::new();
                let s = format!("au BufRead * call rpcnotify(1, \"bufread\", bufname(\"\"))");
                arr.add_string(s.as_slice());
                let msg = neovim::serialize_message(1, "vim_command", &arr);
                let msg_ptr = msg.as_slice().as_ptr() as *const ffi::c_void;
                unsafe { ffi::write(nvim_from_gui[1], msg_ptr, msg.len() as ffi::size_t) };
                if let Some(recv_arr) = receive_message(gui_from_nvim[0]) {
                    println!("Received: {}", recv_arr);
                }
            }

            // listen for messages
            while let Some(recv_arr) = receive_message(gui_from_nvim[0]) {
                if recv_arr.len() > 0 {
                    println!("Received: {}", recv_arr);
                }
            }
        }).detach();

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

        // start nvim
        let mut args = ::std::os::args().clone();
        args.push_all(&["-u".to_string(), config_file.as_str().unwrap().to_string()]);
        neovim::main_setup(args);
        neovim::channel_from_fds(nvim_from_gui[0], gui_from_nvim[1]);
        neovim::main_loop();
    }
}
<|endoftext|>


<commit_before>extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate rustless;
extern crate hyper;
extern crate iron;
extern crate rustc_serialize as serialize;
extern crate valico;

use valico::json_dsl;
use hyper::status::StatusCode;
use rustless::json::ToJson;
use rustless::{
    Application, Api, Nesting, Versioning
};

fn main() {
    let api = Api::build(|api| {
        // Specify API version
        api.prefix("api");

        account_api.post("signin", |endpoint| {
            endpoint.desc("Login user by login-password pair");
            endpoint.handle(|client, params| {
                unimplemented!()
            })
        })

        account_api.post("signup", |endpoint| {
            endpoint.desc("Sign-up user with provided info");
            endpoint.handle(|client, params| {
                unimplemented!()
            })
        })
    });

    let app = Application::new(api);
    iron::Iron::new(app).http("0.0.0.0:8080").unwrap();
}
<commit_msg>Fixed wrong name<commit_after>extern crate postgres;
extern crate r2d2;
extern crate r2d2_postgres;
extern crate rustless;
extern crate hyper;
extern crate iron;
extern crate rustc_serialize as serialize;
extern crate valico;

use valico::json_dsl;
use hyper::status::StatusCode;
use rustless::json::ToJson;
use rustless::{
    Application, Api, Nesting, Versioning
};

fn main() {
    let api = Api::build(|api| {
        // Specify API version
        api.prefix("api");

        api.post("signin", |endpoint| {
            endpoint.desc("Login user by login-password pair");
            endpoint.handle(|client, params| {
                unimplemented!()
            })
        })

        api.post("signup", |endpoint| {
            endpoint.desc("Sign-up user with provided info");
            endpoint.handle(|client, params| {
                unimplemented!()
            })
        })
    });

    let app = Application::new(api);
    iron::Iron::new(app).http("0.0.0.0:8080").unwrap();
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Test analyze log file<commit_after>use std::io::prelude::*;
use std::io::{BufReader};
use std::fs::File;
use std::collections::HashMap;

include!("./sentiment.rs");

fn main() {
    let path = "/tmp/log".to_string();
    let f = match File::open(&path) {
        Err(why) => panic!("Couldn't open {}: {}", path, why),
        Ok(f) => f,
    };
    let f = BufReader::new(f);

    let mut result = HashMap::new();

    let analizer = sentiment::new("/Users/coornail/rust/ircbot/src/wordlist.txt".to_string());

    let mut i = 0;

    for line in f.lines() {
        // Parse lines.
        let l = line.unwrap();
        let parts = l.split("\t").collect::<Vec<&str>>();
        let who = parts[1].to_string();

        // Skip ignored names.
        if ["*", "**", "***", "--", "---", "-->", "<--"].contains(&who.as_str()) {
            continue;
        }
        i = i+1;

        // Calculate new comment value.
        let comment_value = analizer.analyze(parts[2]);
        let sum_comment_value = match result.get(&who) {
            Some(existing_comment_value) => existing_comment_value + comment_value,
            None => comment_value,
        };
        result.insert(who, sum_comment_value);
    }

    print!("{:?}\n", result);
    print!("{} lines analyzed.\n", i);
}
<|endoftext|>


<commit_before>extern crate regex;

fn main() {
	println!("!!!!");
	let input = "(begin (define r 10) (* pi (* r r)))";
	let parsed_code = parse(input);
	println!("{}", parsed_code);
	// Execute script from the command line
}

fn parse(code: &str) -> String {
	// code.to_string()
	let left_paren_re = regex::Regex::new(r"\s*\(\s*").unwrap();
	let right_paren_re = regex::Regex::new(r"\s*\)\s*").unwrap();
	let partial_parsed_code = left_paren_re.replace_all(&code, " ( ");
	let parsed_code = right_paren_re.replace_all(&partial_parsed_code," ) ");
	// let parsed_code = code.replace(" (", "(").replace("( ", "(").replace("(", " ( ").replace()
	let final_string : String = parsed_code.split(" ").collect();
	final_string.clone()
}

// fn tokenize() {

// }

// fn read_from_tokens() {

// }

// #[test]
<commit_msg>logging nightmare<commit_after>extern crate regex;

fn main() {
	println!("!!!!");
	let input = "(begin (define r 10) (* pi (* r r)))";
	let parsed_code = parse(input);
	println!("{}", arr2str(parsed_code));
	// Execute script from the command line
}

fn arr2str(a:Vec<&str>) -> &str {
	let mut s = "[";
	for i in a.iter() {
		s = concat!(s, i);
	}
	s = concat!(s, " ]");
	s;
}

fn parse(code: &str) -> Vec<&str> {
	// code.to_string()
	let left_paren_re = regex::Regex::new(r"\s*\(\s*").unwrap();
	let right_paren_re = regex::Regex::new(r"\s*\)\s*").unwrap();
	let partial_parsed_code = left_paren_re.replace_all(&code, " ( ");
	let parsed_code = right_paren_re.replace_all(&partial_parsed_code," ) ");
	// let parsed_code = code.replace(" (", "(").replace("( ", "(").replace("(", " ( ").replace()
	let final_string : Vec<&str> = parsed_code.split(" ").collect();
	final_string.clone()
}

// fn tokenize() {

// }

// fn read_from_tokens() {

// }

// #[test]
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

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

use std::env;
use std::path::PathBuf;
use std::process::{Command, Output};
use clap::{App, SubCommand, AppSettings};
use walkdir::{DirEntry, WalkDirIterator};

fn announce(banner: &str) {
    let mut line = String::new();
    for _ in 0..banner.len() {
        line.push('-');
    }
    println!("{}", line);
    println!("{}", banner);
    println!("{}", line);
}

fn display_path(path: &PathBuf) {
    path.file_name()
        .and_then(|p| p.to_str())
        .map(|p| println!("{}:", p));
}

fn print_ident(buf: Vec<u8>) {
    for line in String::from_utf8_lossy(&buf[..]).lines() {
        println!("        {}", line);
    }
}

fn report_output(output: Output) {
    if output.status.success() {
        print_ident(output.stdout);
    } else {
        print_ident(output.stderr);
    }
    // I am still not sure what is more idiomatic - the 'if' above or the 'match' below
    //
    // match output.status.success() {
    //     true => print_ident(output.stdout),
    //     false => print_ident(output.stderr),
    // }
    println!("");
}

const CARGO: &'static str = "cargo";
const MIN_DEPTH: usize = 1;
const MAX_DEPTH: usize = 1;

fn main() {

    let mut cmd = Command::new(CARGO);
    let mut banner = String::from("Executing ") + CARGO;

    let matches = App::new(CARGO)
                      .bin_name(CARGO)
                      .version(crate_version!())
                      .about("Run cargo command on multiple crates")
                      .setting(AppSettings::SubcommandRequired)
                      .setting(AppSettings::ArgRequiredElseHelp)
                      .subcommand(SubCommand::with_name("multi")
                                      .version(crate_version!())
                                      .setting(AppSettings::ArgRequiredElseHelp)
                                      .setting(AppSettings::TrailingVarArg)
                                      .arg_from_usage("<cmd>... 'cargo command to run'"))
                      .get_matches();

    if let Some(arg_cmd) = matches.subcommand_matches("multi")
                                  .and_then(|m| m.values_of("cmd")) {
        for arg in arg_cmd {
            cmd.arg(arg);
            banner = banner + " " + arg;
        }
    }

    announce(&banner);

    let is_crate = |e: &DirEntry| e.path().join("Cargo.toml").exists();
    let to_path_buf = |e: DirEntry| e.path().to_path_buf();
    let execute = move |p| cmd.current_dir(p).output().map(report_output);

    let cwd = env::current_dir().unwrap();
    walkdir::WalkDir::new(cwd)
        .min_depth(MIN_DEPTH)
        .max_depth(MAX_DEPTH)
        .into_iter()
        .filter_entry(is_crate)
        .filter_map(|e| e.ok())
        .map(to_path_buf)
        .inspect(display_path)
        .map(execute)
        .last(); // XXX Non-idiomatic perhaps, but gets the job done. May need to revisit later.
}
<commit_msg>Code refactor<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

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

use std::env;
use std::path::PathBuf;
use std::process::{Command, Output};
use clap::{App, SubCommand, AppSettings};
use walkdir::{DirEntry, WalkDirIterator};

fn announce(banner: &str) {
    let mut line = String::new();
    for _ in 0..banner.len() {
        line.push('-');
    }
    println!("{}", line);
    println!("{}", banner);
    println!("{}", line);
}

fn display_path(path: &PathBuf) {
    path.file_name()
        .and_then(|p| p.to_str())
        .map(|p| println!("{}:", p));
}

fn print_ident(buf: Vec<u8>) {
    for line in String::from_utf8_lossy(&buf[..]).lines() {
        println!("        {}", line);
    }
}

fn report_output(output: Output) {
    if output.status.success() {
        print_ident(output.stdout);
    } else {
        print_ident(output.stderr);
    }
    // I am still not sure what is more idiomatic - the 'if' above or the 'match' below
    //
    // match output.status.success() {
    //     true => print_ident(output.stdout),
    //     false => print_ident(output.stderr),
    // }
    println!("");
}

const CARGO: &'static str = "cargo";
const MIN_DEPTH: usize = 1;
const MAX_DEPTH: usize = 1;

fn main() {

    let matches = App::new(CARGO)
                      .bin_name(CARGO)
                      .version(crate_version!())
                      .about("Run cargo command on multiple crates")
                      .setting(AppSettings::SubcommandRequired)
                      .setting(AppSettings::ArgRequiredElseHelp)
                      .subcommand(SubCommand::with_name("multi")
                                      .version(crate_version!())
                                      .setting(AppSettings::ArgRequiredElseHelp)
                                      .setting(AppSettings::TrailingVarArg)
                                      .arg_from_usage("<cmd>... 'cargo command to run'"))
                      .get_matches();

    let mut cargo_cmd = Command::new(CARGO);
    let mut banner = String::from("Executing ") + CARGO;

    if let Some(arg_cmd) = matches.subcommand_matches("multi")
                                  .and_then(|m| m.values_of("cmd")) {
        for arg in arg_cmd {
            cargo_cmd.arg(arg);
            banner = banner + " " + arg;
        }
    }

    let is_crate = |e: &DirEntry| e.path().join("Cargo.toml").exists();
    let to_path_buf = |e: DirEntry| e.path().to_path_buf();
    let execute = move |p| cargo_cmd.current_dir(p).output().map(report_output);

    if let Ok(cwd) = env::current_dir() {
        announce(&banner);
        walkdir::WalkDir::new(cwd)
            .min_depth(MIN_DEPTH)
            .max_depth(MAX_DEPTH)
            .into_iter()
            .filter_entry(is_crate)
            .filter_map(|e| e.ok())
            .map(to_path_buf)
            .inspect(display_path)
            .map(execute)
            .last(); // XXX Non-idiomatic perhaps, but gets the job done. May need to revisit later.
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagutil;

use std::process::exit;

use clap::ArgMatches;

use libimagrt::runtime::Runtime;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Result as StoreResult;
use libimagstore::storeid::StoreId;
use libimagutil::trace::trace_error;

mod ui;
mod viewer;

use ui::build_ui;
use viewer::Viewer;
use viewer::ViewInformation;
use viewer::stdout::StdoutViewer;

fn main() {
    let name = "imag-view";
    let version = &version!()[..];
    let about = "View entries (readonly)";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    rt.init_logger();

    debug!("Hello. Logging was just enabled");
    debug!("I already set up the Runtime object and build the commandline interface parser.");
    debug!("Lets get rollin' ...");

    info!("No implementation yet");

    let entry_id = rt.cli().value_of("id").unwrap(); // enforced by clap

    if rt.cli().is_present("versions") {
        view_versions_of(entry_id, &rt);
    } else {
        let entry_version   = rt.cli().value_of("version");
        let view_header     = rt.cli().is_present("view-header");
        let view_content    = rt.cli().is_present("view-content");
        let view_copy       = rt.cli().is_present("view-copy");
        let keep_copy       = rt.cli().is_present("keep-copy");

        let scmd = rt.cli().subcommand_matches("view-in");
        if scmd.is_none() {
            debug!("No commandline call");
            exit(1);
        }
        let scmd = scmd.unwrap();

        let viewer = build_viewer(scmd);
        let entry = load_entry(entry_id, entry_version, &rt);
        if entry.is_err() {
            trace_error(&entry.err().unwrap());
            exit(1);
        }
        let entry = entry.unwrap();

        let view_info = ViewInformation {
            entry:          entry,
            view_header:    view_header,
            view_content:   view_content,
            view_copy:      view_copy,
            keep_copy:      keep_copy,
        };

        view_info.view(view_info);
    }
}

// TODO: This is a shameless adaption of imag-store/src/util.rs
fn load_entry<'a>(id: &str,
                  version: Option<&str>,
                  rt: &'a Runtime)
    -> StoreResult<FileLockEntry<'a>>
{
    use std::ops::Deref;

    debug!("Checking path element for version");

    let version = {
        version.unwrap_or_else(|| {
            id.split("~").last().unwrap_or_else(|| {
                warn!("No version");
                exit(1);
            })
        })
    };

    debug!("Building path from {:?} and {:?}", id, version);
    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~{}", &id[1..id.len()], version));
    } else {
        path.push(format!("{}~{}", id, version));
    }

    // the above is the adaption...

    rt.store().retrieve(path)
}

fn view_versions_of(id: &str, rt: &Runtime) {
    use glob::glob;

    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~*", &id[1..id.len()]));
    } else {
        path.push(format!("{}~*", id));
    }

    if let Some(path) = path.to_str() {
        match glob(path) {
            Ok(paths) =>
                for entry in paths {
                    match entry {
                        Ok(path) => println!("{}", path.file_name().and_then(|s| s.to_str()).unwrap()),
                        Err(e)   => trace_error(e.error()),
                    }
                },
            Err(e) => {
                // trace_error(&e); // error seems not to be implemented
                debug!("Error in pattern");
                exit(1);
            },
        }
    } else {
        warn!("Could not build glob() argument!");
    }
}

<commit_msg>Use StdoutViewer by now<commit_after>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagutil;

use std::process::exit;

use clap::ArgMatches;

use libimagrt::runtime::Runtime;
use libimagstore::store::Entry;
use libimagstore::store::FileLockEntry;
use libimagstore::store::Result as StoreResult;
use libimagstore::storeid::StoreId;
use libimagutil::trace::trace_error;

mod ui;
mod viewer;

use ui::build_ui;
use viewer::Viewer;
use viewer::ViewInformation;
use viewer::stdout::StdoutViewer;

fn main() {
    let name = "imag-view";
    let version = &version!()[..];
    let about = "View entries (readonly)";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));
    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.err().unwrap());
            exit(1);
        }
    };

    rt.init_logger();

    debug!("Hello. Logging was just enabled");
    debug!("I already set up the Runtime object and build the commandline interface parser.");
    debug!("Lets get rollin' ...");

    info!("No implementation yet");

    let entry_id = rt.cli().value_of("id").unwrap(); // enforced by clap

    if rt.cli().is_present("versions") {
        view_versions_of(entry_id, &rt);
    } else {
        let entry_version   = rt.cli().value_of("version");
        let view_header     = rt.cli().is_present("view-header");
        let view_content    = rt.cli().is_present("view-content");
        let view_copy       = rt.cli().is_present("view-copy");
        let keep_copy       = rt.cli().is_present("keep-copy");

        let scmd = rt.cli().subcommand_matches("view-in");
        if scmd.is_none() {
            debug!("No commandline call");
            exit(1);
        }
        let scmd = scmd.unwrap();

        let viewer = build_viewer(scmd);
        let entry = load_entry(entry_id, entry_version, &rt);
        if entry.is_err() {
            trace_error(&entry.err().unwrap());
            exit(1);
        }
        let entry = entry.unwrap();

        let view_info = ViewInformation {
            entry:          entry,
            view_header:    view_header,
            view_content:   view_content,
            view_copy:      view_copy,
            keep_copy:      keep_copy,
        };

        let viewer = StdoutViewer::new();
        viewer.view(view_info);
    }
}

// TODO: This is a shameless adaption of imag-store/src/util.rs
fn load_entry<'a>(id: &str,
                  version: Option<&str>,
                  rt: &'a Runtime)
    -> StoreResult<FileLockEntry<'a>>
{
    use std::ops::Deref;

    debug!("Checking path element for version");

    let version = {
        version.unwrap_or_else(|| {
            id.split("~").last().unwrap_or_else(|| {
                warn!("No version");
                exit(1);
            })
        })
    };

    debug!("Building path from {:?} and {:?}", id, version);
    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~{}", &id[1..id.len()], version));
    } else {
        path.push(format!("{}~{}", id, version));
    }

    // the above is the adaption...

    rt.store().retrieve(path)
}

fn view_versions_of(id: &str, rt: &Runtime) {
    use glob::glob;

    let mut path = rt.store().path().clone();

    if id.chars().next() == Some('/') {
        path.push(format!("{}~*", &id[1..id.len()]));
    } else {
        path.push(format!("{}~*", id));
    }

    if let Some(path) = path.to_str() {
        match glob(path) {
            Ok(paths) =>
                for entry in paths {
                    match entry {
                        Ok(path) => println!("{}", path.file_name().and_then(|s| s.to_str()).unwrap()),
                        Err(e)   => trace_error(e.error()),
                    }
                },
            Err(e) => {
                // trace_error(&e); // error seems not to be implemented
                debug!("Error in pattern");
                exit(1);
            },
        }
    } else {
        warn!("Could not build glob() argument!");
    }
}

<|endoftext|>


<commit_before>extern crate regex;

use regex::Regex;
use std::collections::HashSet;
use std::io::{self, Write};

use super::{Compile, Name, ParseError, Path, Statement, Template};
use self::runtime::RUNTIME;

mod runtime;

/// A program is the final result of Mustache AST to Ruby extension source
/// translation that is presented to the main compiler driver for output.
///
/// It contains all external rendering functions generated by the translator,
/// which are exposed to Ruby code after the extension is compiled.
#[derive(Debug)]
pub struct Program {
    global: Scope,
}

impl Program {
    fn new() -> Self {
        Program { global: Scope::new(Name::new("global")) }
    }

    fn merge(&mut self, scope: Scope) -> &mut Self {
        self.global.merge(scope);
        self
    }
}

impl Compile for Program {
    /// Writes the final translated source code to an output buffer.
    ///
    /// This emits fully-formed Ruby extension source code that may be input
    /// into a mkmf build process, creating a dynamically loadable shared
    /// object file.
    fn emit(&self, buf: &mut Write) -> io::Result<()> {
        // Emit runtime preamble.
        writeln!(buf, "{}", RUNTIME)?;

        // Emit string content declarations.
        for string in &self.global.strings {
            writeln!(buf, "{};", string.decl)?;
        }

        writeln!(buf, "")?;

        // Emit function declarations.
        for fun in &self.global.functions {
            writeln!(buf, "{};", fun.decl)?;
        }

        writeln!(buf, "")?;

        // Emit function definitions.
        for fun in &self.global.functions {
            fun.emit(buf)?
        }

        // Emit public render function.
        let renders: Vec<_> = self.global.functions.iter().filter_map(|f| f.invoke_if()).collect();
        writeln!(buf,
                 r#"static VALUE render(VALUE self, VALUE name, VALUE context) {{
                        const char *ptr = StringValuePtr(name);
                        const long length = RSTRING_LEN(name);
                        VALUE buf = rb_str_buf_new(0);
                        VALUE stack = rb_ary_new_from_args(1, context);
                        {}
                        else {{
                            rb_raise(rb_eArgError, "Template not found");
                        }}
                        return buf;
                    }}"#,
                 renders.join(" else "))?;

        // Emit initialize function.
        writeln!(buf, "static void initialize() {{")?;
        for string in &self.global.strings {
            string.emit(buf)?;
        }
        writeln!(buf, "}}")
    }
}

/// A store for functions created by the translation process of an input
/// template to source code output.
///
/// Scopes have name generators that are used in function naming, providing a
/// stable name that other scopes may rely on for partial template function
/// calls.
///
/// After each template is translated into a scope they are merged into a
/// Program's global scope for final output.
#[derive(Debug)]
struct Scope {
    name: Name,
    functions: Vec<Function>,
    strings: Vec<StaticString>,
}

impl Scope {
    fn new(name: Name) -> Self {
        Scope {
            name: name,
            functions: Vec::new(),
            strings: Vec::new(),
        }
    }

    /// Combines this scope's function definitions with another's.
    fn merge(&mut self, mut other: Scope) -> &mut Self {
        self.functions.append(&mut other.functions);
        self.strings.append(&mut other.strings);
        self
    }

    /// Advances the scope's name generator to the next unique identifier. This
    /// should be called before descending another level in the recursive
    /// tree translation process.
    fn next(&mut self) -> &mut Self {
        self.name.next();
        self
    }

    /// Adds a function to this scope.
    fn register(&mut self, fun: Function) {
        self.functions.push(fun);
    }

    /// Adds a constant string value to this scope.
    fn content(&mut self, string: StaticString) {
        self.strings.push(string);
    }

    /// Returns the template path used to generate function names in this
    /// scope (e.g. "includes/header").
    fn base_name(&self) -> String {
        self.name.base.clone()
    }
}

#[derive(Debug)]
struct StaticString {
    name: String,
    decl: String,
    value: String,
    length: usize,
}

impl StaticString {
    /// Writes the raw content string global to the buffer.
    fn emit(&self, buf: &mut Write) -> io::Result<()> {
        writeln!(buf, "{{")?;
        writeln!(buf, "static const char* content = \"{}\";", self.value)?;
        writeln!(buf,
                 "{} = rb_str_new_static(content, {});",
                 self.name,
                 self.length)?;
        writeln!(buf, "rb_global_variable(&{});", self.name)?;
        writeln!(buf, "}}")
    }
}

#[derive(Debug)]
struct Function {
    name: String,
    decl: String,
    body: Vec<String>,
    export: Option<String>,
}

impl Function {
    /// Writes the function definition to the buffer.
    fn emit(&self, buf: &mut Write) -> io::Result<()> {
        writeln!(buf, "{} {{", self.decl)?;
        for node in &self.body {
            writeln!(buf, "{}", node)?;
        }
        writeln!(buf, "}}\n")
    }

    /// Builds a conditional statement to call the function if the template
    /// name matches the function's exported name, like "includes/header".
    fn invoke_if(&self) -> Option<String> {
        if self.export.is_none() {
            return None;
        }

        let export = self.export.as_ref().unwrap();
        Some(format!("if (length == {len} && strncmp(ptr, \"{path}\", {len}) == 0) {{
                          {fun}(buf, stack);
                      }}",
                     len = export.len(),
                     path = export,
                     fun = self.name))
    }
}

/// Recursively walks the AST, translating Mustache statement tree nodes into
/// the corresponding Ruby extension source code.
///
/// Sections are extracted into top-level functions paired with a function
/// call at the location the section appeared in the template. Partials are
/// similarly translated into a function call which is expected to be provided
/// by another template in the final tree.
fn transform(scope: &mut Scope, node: &Statement) -> Option<String> {
    match *node {
        Statement::Program(ref block) => {
            let id = scope.name.id();

            // Build private render function.
            let children = block.statements
                .iter()
                .filter_map(|stmt| transform(scope.next(), stmt))
                .collect();

            let render = Function {
                name: format!("render_{}", id),
                decl: format!("static void render_{}(VALUE buf, VALUE stack)", id),
                body: children,
                export: Some(scope.base_name()),
            };

            scope.register(render);
            None
        }
        Statement::Section(ref path, ref block) => {
            let children = block.statements
                .iter()
                .filter_map(|stmt| transform(scope.next(), stmt))
                .collect();

            let fun = Function {
                name: format!("section_{}", scope.name),
                decl: format!("static void section_{}(VALUE buf, VALUE stack)", scope.name),
                body: children,
                export: None,
            };

            let call = format!("{{ {} section(buf, stack, &path, {}); }}",
                               path_ary(path),
                               fun.name);

            scope.register(fun);
            Some(call)
        }
        Statement::Inverted(ref path, ref block) => {
            let children = block.statements
                .iter()
                .filter_map(|stmt| transform(scope.next(), stmt))
                .collect();

            let fun = Function {
                name: format!("section_{}", scope.name),
                decl: format!("static void section_{}(VALUE buf, VALUE stack)", scope.name),
                body: children,
                export: None,
            };

            let call = format!("{{ {} inverted(buf, stack, &path, {}); }}",
                               path_ary(path),
                               fun.name);

            scope.register(fun);
            Some(call)
        }
        Statement::Partial(ref name, ref padding) => {
            let name = Name::new(name);
            Some(format!("render_{}(buf, stack);", name.id()))
        }
        Statement::Comment(_) => None,
        Statement::Content(ref text) => {
            let content = clean(text);

            let name = format!("content_{}", scope.next().name);
            let string = StaticString {
                decl: format!("static VALUE {}", name),
                name: name,
                value: content,
                length: text.len(),
            };

            let append = format!("rb_str_buf_append(buf, {});", string.name);

            scope.content(string);
            Some(append)
        }
        Statement::Variable(ref path) => {
            let path = path_ary(path);
            Some(format!("{{ {} append_value(buf, stack, &path, true); }}", path))
        }
        Statement::Html(ref path) => {
            let path = path_ary(path);
            Some(format!("{{ {} append_value(buf, stack, &path, false); }}", path))
        }
    }
}

/// Transforms the AST of each parsed template into a source code tree
/// and links each template together into a single executable program.
pub fn link(templates: &Vec<Template>) -> Result<Program, ParseError> {
    validate(templates)?;

    let mut program = Program::new();
    templates.iter()
        .map(|template| {
            let mut scope = Scope::new(template.name());
            transform(&mut scope, &template.tree);
            scope
        })
        .fold(&mut program, |program, scope| program.merge(scope));

    Ok(program)
}

/// Ensures all templates may be linked together into an executable.
///
/// This method checks that all partial template paths are provided by
/// another template. For example, a `{{>include/header}}` partial invocation
/// must be provided by an `include/header.mustache` template file.
///
/// Partials can be considered function calls, so the function must be defined.
fn validate(templates: &Vec<Template>) -> Result<(), ParseError> {
    let all: HashSet<_> = templates.iter().map(|temp| &temp.name).collect();

    for template in templates {
        let names: HashSet<_> = template.tree.partials().into_iter().collect();
        let missing = &names - &all;
        if !missing.is_empty() {
            let name = missing.into_iter().next().unwrap();
            return Err(ParseError::UnknownPartial(name.clone(), template.path.clone()));
        }
    }

    Ok(())
}

/// Replaces string literal characters considered invalid inside a cstr with
/// their escaped counterparts.
fn clean(text: &str) -> String {
    let re = Regex::new(r"\\").unwrap();
    let text = re.replace_all(&text, "\\\\");

    let re = Regex::new(r"\r").unwrap();
    let text = re.replace_all(&text, "\\r");

    let re = Regex::new(r"\n").unwrap();
    let text = re.replace_all(&text, "\\n");

    let re = Regex::new(r#"["]"#).unwrap();
    re.replace_all(&text, "\\\"").into_owned()
}

/// Transforms a Mustache variable key path into the source code to build a
/// Ruby array. At runtime, each key in the array is recursively processed to
/// find the replacement text for a Mustache expression.
fn path_ary(path: &Path) -> String {
    let args = path.keys
        .iter()
        .map(|key| format!("\"{}\"", key))
        .collect::<Vec<String>>()
        .join(", ");

    format!("static const struct path path = {{ .keys = {{ {} }}, .length = {} }};",
            args,
            path.keys.len())
}

#[cfg(test)]
mod tests {
    use super::{link, transform, Scope};
    use super::super::{Name, ParseError, Statement, Template};
    use std::path::{Path, PathBuf};

    #[test]
    fn validates_valid_partial_reference() {
        let base = PathBuf::from("app/templates");
        let path = PathBuf::from("app/templates/machines/robots.mustache");
        let tree = Statement::Partial(String::from("machines/robot"), None);
        let master = Template::new(&base, path, tree);

        let path = PathBuf::from("app/templates/machines/robot.mustache");
        let tree = Statement::Content(String::from("hubot"));
        let detail = Template::new(&base, path, tree);

        let templates = vec![master, detail];
        match link(&templates) {
            Ok(_) => (),
            Err(e) => panic!("Must link valid partials: {}", e),
        }
    }

    #[test]
    fn validates_invalid_partial_reference() {
        let base = PathBuf::from("app/templates");
        let path = PathBuf::from("app/templates/machines/robots.mustache");
        let tree = Statement::Partial(String::from("machines/unknown"), None);

        let master = Template::new(&base, path, tree);

        let path = PathBuf::from("app/templates/machines/robot.mustache");
        let tree = Statement::Content(String::from("hubot"));
        let detail = Template::new(&base, path, tree);

        let templates = vec![master, detail];
        match link(&templates) {
            Err(ParseError::UnknownPartial(ref name, ref path)) => {
                assert_eq!("machines/unknown", name);
                assert_eq!(Path::new("app/templates/machines/robots.mustache"), path);
            }
            _ => panic!("Must enforce partial references"),
        }
    }

    #[test]
    fn transforms_tree_into_functions() {
        let text = "
            {{> includes/header }}

                {{# robots}}

{{ name.first }}

                {{/ robots}}
                {{^ robots}}
                    {{! else clause }}
                    No robots
                {{/ robots}}

            {{> includes/footer }}
            {{{ unescaped.html }}}
        ";

        match Statement::parse(text) {
            Ok(tree) => {
                let mut scope = Scope::new(Name::new("machines/robot"));
                transform(&mut scope, &tree);

                // One for each section, private render, and exported template function.
                let names: Vec<_> = scope.functions.iter().map(|fun| &fun.name).collect();
                assert_eq!(vec!["section_machines_robot7",
                                "section_machines_robot10",
                                "render_machines_robot"],
                           names);

                // Single exported function name.
                let exports: Vec<_> =
                    scope.functions.iter().filter_map(|fun| fun.export.as_ref()).collect();
                assert_eq!(vec!["machines/robot"], exports);
            }
            Err(e) => panic!("Failed to parse tree: {}", e),
        }
    }
}
<commit_msg>Fix expected function names<commit_after>extern crate regex;

use regex::Regex;
use std::collections::HashSet;
use std::io::{self, Write};

use super::{Compile, Name, ParseError, Path, Statement, Template};
use self::runtime::RUNTIME;

mod runtime;

/// A program is the final result of Mustache AST to Ruby extension source
/// translation that is presented to the main compiler driver for output.
///
/// It contains all external rendering functions generated by the translator,
/// which are exposed to Ruby code after the extension is compiled.
#[derive(Debug)]
pub struct Program {
    global: Scope,
}

impl Program {
    fn new() -> Self {
        Program { global: Scope::new(Name::new("global")) }
    }

    fn merge(&mut self, scope: Scope) -> &mut Self {
        self.global.merge(scope);
        self
    }
}

impl Compile for Program {
    /// Writes the final translated source code to an output buffer.
    ///
    /// This emits fully-formed Ruby extension source code that may be input
    /// into a mkmf build process, creating a dynamically loadable shared
    /// object file.
    fn emit(&self, buf: &mut Write) -> io::Result<()> {
        // Emit runtime preamble.
        writeln!(buf, "{}", RUNTIME)?;

        // Emit string content declarations.
        for string in &self.global.strings {
            writeln!(buf, "{};", string.decl)?;
        }

        writeln!(buf, "")?;

        // Emit function declarations.
        for fun in &self.global.functions {
            writeln!(buf, "{};", fun.decl)?;
        }

        writeln!(buf, "")?;

        // Emit function definitions.
        for fun in &self.global.functions {
            fun.emit(buf)?
        }

        // Emit public render function.
        let renders: Vec<_> = self.global.functions.iter().filter_map(|f| f.invoke_if()).collect();
        writeln!(buf,
                 r#"static VALUE render(VALUE self, VALUE name, VALUE context) {{
                        const char *ptr = StringValuePtr(name);
                        const long length = RSTRING_LEN(name);
                        VALUE buf = rb_str_buf_new(0);
                        VALUE stack = rb_ary_new_from_args(1, context);
                        {}
                        else {{
                            rb_raise(rb_eArgError, "Template not found");
                        }}
                        return buf;
                    }}"#,
                 renders.join(" else "))?;

        // Emit initialize function.
        writeln!(buf, "static void initialize() {{")?;
        for string in &self.global.strings {
            string.emit(buf)?;
        }
        writeln!(buf, "}}")
    }
}

/// A store for functions created by the translation process of an input
/// template to source code output.
///
/// Scopes have name generators that are used in function naming, providing a
/// stable name that other scopes may rely on for partial template function
/// calls.
///
/// After each template is translated into a scope they are merged into a
/// Program's global scope for final output.
#[derive(Debug)]
struct Scope {
    name: Name,
    functions: Vec<Function>,
    strings: Vec<StaticString>,
}

impl Scope {
    fn new(name: Name) -> Self {
        Scope {
            name: name,
            functions: Vec::new(),
            strings: Vec::new(),
        }
    }

    /// Combines this scope's function definitions with another's.
    fn merge(&mut self, mut other: Scope) -> &mut Self {
        self.functions.append(&mut other.functions);
        self.strings.append(&mut other.strings);
        self
    }

    /// Advances the scope's name generator to the next unique identifier. This
    /// should be called before descending another level in the recursive
    /// tree translation process.
    fn next(&mut self) -> &mut Self {
        self.name.next();
        self
    }

    /// Adds a function to this scope.
    fn register(&mut self, fun: Function) {
        self.functions.push(fun);
    }

    /// Adds a constant string value to this scope.
    fn content(&mut self, string: StaticString) {
        self.strings.push(string);
    }

    /// Returns the template path used to generate function names in this
    /// scope (e.g. "includes/header").
    fn base_name(&self) -> String {
        self.name.base.clone()
    }
}

#[derive(Debug)]
struct StaticString {
    name: String,
    decl: String,
    value: String,
    length: usize,
}

impl StaticString {
    /// Writes the raw content string global to the buffer.
    fn emit(&self, buf: &mut Write) -> io::Result<()> {
        writeln!(buf, "{{")?;
        writeln!(buf, "static const char* content = \"{}\";", self.value)?;
        writeln!(buf,
                 "{} = rb_str_new_static(content, {});",
                 self.name,
                 self.length)?;
        writeln!(buf, "rb_global_variable(&{});", self.name)?;
        writeln!(buf, "}}")
    }
}

#[derive(Debug)]
struct Function {
    name: String,
    decl: String,
    body: Vec<String>,
    export: Option<String>,
}

impl Function {
    /// Writes the function definition to the buffer.
    fn emit(&self, buf: &mut Write) -> io::Result<()> {
        writeln!(buf, "{} {{", self.decl)?;
        for node in &self.body {
            writeln!(buf, "{}", node)?;
        }
        writeln!(buf, "}}\n")
    }

    /// Builds a conditional statement to call the function if the template
    /// name matches the function's exported name, like "includes/header".
    fn invoke_if(&self) -> Option<String> {
        if self.export.is_none() {
            return None;
        }

        let export = self.export.as_ref().unwrap();
        Some(format!("if (length == {len} && strncmp(ptr, \"{path}\", {len}) == 0) {{
                          {fun}(buf, stack);
                      }}",
                     len = export.len(),
                     path = export,
                     fun = self.name))
    }
}

/// Recursively walks the AST, translating Mustache statement tree nodes into
/// the corresponding Ruby extension source code.
///
/// Sections are extracted into top-level functions paired with a function
/// call at the location the section appeared in the template. Partials are
/// similarly translated into a function call which is expected to be provided
/// by another template in the final tree.
fn transform(scope: &mut Scope, node: &Statement) -> Option<String> {
    match *node {
        Statement::Program(ref block) => {
            let id = scope.name.id();

            // Build private render function.
            let children = block.statements
                .iter()
                .filter_map(|stmt| transform(scope.next(), stmt))
                .collect();

            let render = Function {
                name: format!("render_{}", id),
                decl: format!("static void render_{}(VALUE buf, VALUE stack)", id),
                body: children,
                export: Some(scope.base_name()),
            };

            scope.register(render);
            None
        }
        Statement::Section(ref path, ref block) => {
            let children = block.statements
                .iter()
                .filter_map(|stmt| transform(scope.next(), stmt))
                .collect();

            let fun = Function {
                name: format!("section_{}", scope.name),
                decl: format!("static void section_{}(VALUE buf, VALUE stack)", scope.name),
                body: children,
                export: None,
            };

            let call = format!("{{ {} section(buf, stack, &path, {}); }}",
                               path_ary(path),
                               fun.name);

            scope.register(fun);
            Some(call)
        }
        Statement::Inverted(ref path, ref block) => {
            let children = block.statements
                .iter()
                .filter_map(|stmt| transform(scope.next(), stmt))
                .collect();

            let fun = Function {
                name: format!("section_{}", scope.name),
                decl: format!("static void section_{}(VALUE buf, VALUE stack)", scope.name),
                body: children,
                export: None,
            };

            let call = format!("{{ {} inverted(buf, stack, &path, {}); }}",
                               path_ary(path),
                               fun.name);

            scope.register(fun);
            Some(call)
        }
        Statement::Partial(ref name, ref padding) => {
            let name = Name::new(name);
            Some(format!("render_{}(buf, stack);", name.id()))
        }
        Statement::Comment(_) => None,
        Statement::Content(ref text) => {
            let content = clean(text);

            let name = format!("content_{}", scope.next().name);
            let string = StaticString {
                decl: format!("static VALUE {}", name),
                name: name,
                value: content,
                length: text.len(),
            };

            let append = format!("rb_str_buf_append(buf, {});", string.name);

            scope.content(string);
            Some(append)
        }
        Statement::Variable(ref path) => {
            let path = path_ary(path);
            Some(format!("{{ {} append_value(buf, stack, &path, true); }}", path))
        }
        Statement::Html(ref path) => {
            let path = path_ary(path);
            Some(format!("{{ {} append_value(buf, stack, &path, false); }}", path))
        }
    }
}

/// Transforms the AST of each parsed template into a source code tree
/// and links each template together into a single executable program.
pub fn link(templates: &Vec<Template>) -> Result<Program, ParseError> {
    validate(templates)?;

    let mut program = Program::new();
    templates.iter()
        .map(|template| {
            let mut scope = Scope::new(template.name());
            transform(&mut scope, &template.tree);
            scope
        })
        .fold(&mut program, |program, scope| program.merge(scope));

    Ok(program)
}

/// Ensures all templates may be linked together into an executable.
///
/// This method checks that all partial template paths are provided by
/// another template. For example, a `{{>include/header}}` partial invocation
/// must be provided by an `include/header.mustache` template file.
///
/// Partials can be considered function calls, so the function must be defined.
fn validate(templates: &Vec<Template>) -> Result<(), ParseError> {
    let all: HashSet<_> = templates.iter().map(|temp| &temp.name).collect();

    for template in templates {
        let names: HashSet<_> = template.tree.partials().into_iter().collect();
        let missing = &names - &all;
        if !missing.is_empty() {
            let name = missing.into_iter().next().unwrap();
            return Err(ParseError::UnknownPartial(name.clone(), template.path.clone()));
        }
    }

    Ok(())
}

/// Replaces string literal characters considered invalid inside a cstr with
/// their escaped counterparts.
fn clean(text: &str) -> String {
    let re = Regex::new(r"\\").unwrap();
    let text = re.replace_all(&text, "\\\\");

    let re = Regex::new(r"\r").unwrap();
    let text = re.replace_all(&text, "\\r");

    let re = Regex::new(r"\n").unwrap();
    let text = re.replace_all(&text, "\\n");

    let re = Regex::new(r#"["]"#).unwrap();
    re.replace_all(&text, "\\\"").into_owned()
}

/// Transforms a Mustache variable key path into the source code to build a
/// Ruby array. At runtime, each key in the array is recursively processed to
/// find the replacement text for a Mustache expression.
fn path_ary(path: &Path) -> String {
    let args = path.keys
        .iter()
        .map(|key| format!("\"{}\"", key))
        .collect::<Vec<String>>()
        .join(", ");

    format!("static const struct path path = {{ .keys = {{ {} }}, .length = {} }};",
            args,
            path.keys.len())
}

#[cfg(test)]
mod tests {
    use super::{link, transform, Scope};
    use super::super::{Name, ParseError, Statement, Template};
    use std::path::{Path, PathBuf};

    #[test]
    fn validates_valid_partial_reference() {
        let base = PathBuf::from("app/templates");
        let path = PathBuf::from("app/templates/machines/robots.mustache");
        let tree = Statement::Partial(String::from("machines/robot"), None);
        let master = Template::new(&base, path, tree);

        let path = PathBuf::from("app/templates/machines/robot.mustache");
        let tree = Statement::Content(String::from("hubot"));
        let detail = Template::new(&base, path, tree);

        let templates = vec![master, detail];
        match link(&templates) {
            Ok(_) => (),
            Err(e) => panic!("Must link valid partials: {}", e),
        }
    }

    #[test]
    fn validates_invalid_partial_reference() {
        let base = PathBuf::from("app/templates");
        let path = PathBuf::from("app/templates/machines/robots.mustache");
        let tree = Statement::Partial(String::from("machines/unknown"), None);

        let master = Template::new(&base, path, tree);

        let path = PathBuf::from("app/templates/machines/robot.mustache");
        let tree = Statement::Content(String::from("hubot"));
        let detail = Template::new(&base, path, tree);

        let templates = vec![master, detail];
        match link(&templates) {
            Err(ParseError::UnknownPartial(ref name, ref path)) => {
                assert_eq!("machines/unknown", name);
                assert_eq!(Path::new("app/templates/machines/robots.mustache"), path);
            }
            _ => panic!("Must enforce partial references"),
        }
    }

    #[test]
    fn transforms_tree_into_functions() {
        let text = "
            {{> includes/header }}

                {{# robots}}

{{ name.first }}

                {{/ robots}}
                {{^ robots}}
                    {{! else clause }}
                    No robots
                {{/ robots}}

            {{> includes/footer }}
            {{{ unescaped.html }}}
        ";

        match Statement::parse(text) {
            Ok(tree) => {
                let mut scope = Scope::new(Name::new("machines/robot"));
                transform(&mut scope, &tree);

                // One for each section, private render, and exported template function.
                let names: Vec<_> = scope.functions.iter().map(|fun| &fun.name).collect();
                assert_eq!(vec!["section_machines_robot11",
                                "section_machines_robot15",
                                "render_machines_robot"],
                           names);

                // Single exported function name.
                let exports: Vec<_> =
                    scope.functions.iter().filter_map(|fun| fun.export.as_ref()).collect();
                assert_eq!(vec!["machines/robot"], exports);
            }
            Err(e) => panic!("Failed to parse tree: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "sdl2"]
#![crate_type = "lib"]

extern crate num;
pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use common::IntegerOrSdlError;
<commit_msg>Export sdl2-sys as ::sys in sdl2<commit_after>#![crate_name = "sdl2"]
#![crate_type = "lib"]

extern crate num;
pub extern crate libc;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate bitflags;
pub extern crate sdl2_sys as sys;

#[cfg(feature = "gfx")]
extern crate c_vec;

pub use sdl::*;

pub mod clipboard;
pub mod cpuinfo;
#[macro_use] pub mod macros;
pub mod event;
pub mod filesystem;
pub mod gesture;
pub mod touch;
pub mod joystick;
pub mod controller;
pub mod haptic;
pub mod keyboard;
pub mod mouse;
pub mod rect;
pub mod surface;
pub mod pixels;
pub mod video;
pub mod timer;
pub mod render;
pub mod rwops;
pub mod log;
mod sdl;
pub mod audio;
pub mod version;
pub mod messagebox;
pub mod hint;

// modules
#[cfg(feature = "ttf")]
pub mod ttf;
#[cfg(feature = "image")]
pub mod image;
#[cfg(feature = "mixer")]
pub mod mixer;
#[cfg(feature = "gfx")]
pub mod gfx;

mod common;
// Export return types and such from the common module.
pub use common::IntegerOrSdlError;
<|endoftext|>


<commit_before>use num::Num;

#[inline(always)]
pub fn inverse<T: Num>(out: &mut [T; 2], a: [T; 2]) -> &mut [T; 2] {
    out[0] = a[0] * -T::one();
    out[1] = a[1] * -T::one();
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0];
    inverse(&mut v, [1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn lerp<T: Num>(out: &mut [T; 2], a: [T; 2], b: [T; 2], t: T) -> &mut [T; 2] {
    out[0] = a[0] + (b[0] - a[0]) * t;
    out[1] = a[1] + (b[1] - a[1]) * t;
    out
}
#[test]
fn test_lerp() {
    let mut v = [0.0, 0.0];
    lerp(&mut v, [0.0, 0.0], [1.0, 1.0], 0.5);
    assert!(v[0] == 0.5);
    assert!(v[1] == 0.5);
}

#[inline(always)]
pub fn perp<T: Num>(out: &mut [T; 2], a: [T; 2]) -> &mut [T; 2] {
    out[0] = a[1];
    out[1] = -a[0];
    out
}
#[test]
fn test_perp() {
    let mut v = [0, 0];
    perp(&mut v, [1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn perp_r<T: Num>(out: &mut [T; 2], a: [T; 2]) -> &mut [T; 2] {
    out[0] = -a[1];
    out[1] = a[0];
    out
}
#[test]
fn test_perp_r() {
    let mut v = [0, 0];
    perp_r(&mut v, [1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == 1);
}

#[inline(always)]
pub fn min<T: Num>(out: &mut [T; 2], a: [T; 2], b: [T; 2]) -> &mut [T; 2] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0];
    min(&mut v, [1, 0], [0, 1]);
    assert!(v == [0, 0]);
}

#[inline(always)]
pub fn max<T: Num>(out: &mut [T; 2], a: [T; 2], b: [T; 2]) -> &mut [T; 2] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0];
    max(&mut v, [1, 0], [0, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn clamp<T: Num>(out: &mut [T; 2], a: [T; 2], min: [T; 2], max: [T; 2]) -> &mut [T; 2] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0];
    clamp(&mut v, [2, 2], [0, 0], [1, 1]);
    assert!(v == [1, 1]);
}
<commit_msg>updates<commit_after>use num::Num;

#[inline(always)]
pub fn inverse<T: Num>(out: &mut [T; 2], a: [T; 2]) -> &mut [T; 2] {
    out[0] = -a[0];
    out[1] = -a[1];
    out
}
#[test]
fn test_inverse() {
    let mut v = [0, 0];
    inverse(&mut v, [1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn lerp<T: Num>(out: &mut [T; 2], a: [T; 2], b: [T; 2], t: T) -> &mut [T; 2] {
    out[0] = a[0] + (b[0] - a[0]) * t;
    out[1] = a[1] + (b[1] - a[1]) * t;
    out
}
#[test]
fn test_lerp() {
    let mut v = [0.0, 0.0];
    lerp(&mut v, [0.0, 0.0], [1.0, 1.0], 0.5);
    assert!(v[0] == 0.5);
    assert!(v[1] == 0.5);
}

#[inline(always)]
pub fn perp<T: Num>(out: &mut [T; 2], a: [T; 2]) -> &mut [T; 2] {
    out[0] = a[1];
    out[1] = -a[0];
    out
}
#[test]
fn test_perp() {
    let mut v = [0, 0];
    perp(&mut v, [1, 1]);
    assert!(v[0] == 1);
    assert!(v[1] == -1);
}

#[inline(always)]
pub fn perp_r<T: Num>(out: &mut [T; 2], a: [T; 2]) -> &mut [T; 2] {
    out[0] = -a[1];
    out[1] = a[0];
    out
}
#[test]
fn test_perp_r() {
    let mut v = [0, 0];
    perp_r(&mut v, [1, 1]);
    assert!(v[0] == -1);
    assert!(v[1] == 1);
}

#[inline(always)]
pub fn min<T: Num>(out: &mut [T; 2], a: [T; 2], b: [T; 2]) -> &mut [T; 2] {
    out[0] = if b[0] < a[0] {b[0]} else {a[0]};
    out[1] = if b[1] < a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_min() {
    let mut v = [0, 0];
    min(&mut v, [1, 0], [0, 1]);
    assert!(v == [0, 0]);
}

#[inline(always)]
pub fn max<T: Num>(out: &mut [T; 2], a: [T; 2], b: [T; 2]) -> &mut [T; 2] {
    out[0] = if b[0] > a[0] {b[0]} else {a[0]};
    out[1] = if b[1] > a[1] {b[1]} else {a[1]};
    out
}
#[test]
fn test_max() {
    let mut v = [0, 0];
    max(&mut v, [1, 0], [0, 1]);
    assert!(v == [1, 1]);
}

#[inline(always)]
pub fn clamp<T: Num>(out: &mut [T; 2], a: [T; 2], min: [T; 2], max: [T; 2]) -> &mut [T; 2] {
    out[0] = if a[0] < min[0] {min[0]} else if a[0] > max[0] {max[0]} else {a[0]};
    out[1] = if a[1] < min[1] {min[1]} else if a[1] > max[1] {max[1]} else {a[1]};
    out
}
#[test]
fn test_clamp() {
    let mut v = [0, 0];
    clamp(&mut v, [2, 2], [0, 0], [1, 1]);
    assert!(v == [1, 1]);
}
<|endoftext|>


<commit_before>use std::path::{Path, PathBuf};
use walkdir::WalkDir;
use std::io::{BufReader, Read, Result, Write};
use std::fs::{File, create_dir};
use std::iter::Iterator;
use std::collections::HashMap;
use tempdir::TempDir;

pub trait Skeleton {
    type File: SkeletonFile;
    fn files(&self) -> Box<Iterator<Item = Self::File>>;
}

pub trait SkeletonFile: Sized {
    fn path(&self) -> &Path;
    fn contents(&self) -> Result<Box<Read>>;
}

pub struct FsSkeleton {
    pub root: PathBuf,
}

impl Skeleton for FsSkeleton {
    type File = FsFile;
    fn files(&self) -> Box<Iterator<Item = FsFile>> {
        return Box::new(WalkDir::new(self.root.as_path()).into_iter()
        .map(|entry| entry.unwrap())
        .filter(|entry| entry.file_type().is_file())
        .map(|entry| {
            let f = FsFile {
                path: entry.path().to_path_buf(),
            };
            f
        }));
    }
}

pub struct FsFile {
    path: PathBuf,
}

impl SkeletonFile for FsFile {
    fn path(&self) -> &Path {
        self.path.as_path()
    }
    fn contents(&self) -> Result<Box<Read>> {
        let file = File::open(self.path.as_path())?;
        Ok(Box::new(BufReader::new(file)))
    }
}

#[test]
fn test_fs_skeleton_reader(){
    let dir = TempDir::new("yorick-test-skeleton-reader").unwrap();

    // write content
    let mut file1 = File::create(dir.path().join("foo")).unwrap();
    file1.write(b"FOO").unwrap();
    create_dir(dir.path().join("bar")).unwrap();
    let mut file1 = File::create(dir.path().join("bar/baz")).unwrap();
    file1.write(b"QUX").unwrap();

    // test skeleton
    let skel = FsSkeleton{ root: dir.path().to_path_buf() };
    let mut file_map = HashMap::new();
    for file in skel.files() {
        let mut contents = Vec::new();
        file.contents().unwrap().read_to_end(&mut contents).unwrap();
        let path = file.path().to_path_buf();
        file_map.insert(path, contents);
    }
    assert_eq!(file_map.len(), 2);
    println!("files read: {:?}", file_map);
    assert_eq!(file_map.get(Path::new("foo")).unwrap().as_slice(), b"FOO");
    assert_eq!(file_map.get(Path::new("bar/baz")).unwrap().as_slice(), b"QUX");
}
<commit_msg>Make tests actually pass<commit_after>use std::path::{Path, PathBuf};
use walkdir::WalkDir;
use std::io::{BufReader, Read, Result, Write};
use std::fs::{File, create_dir};
use std::iter::Iterator;
use std::collections::HashMap;
use tempdir::TempDir;

pub trait Skeleton {
    type File: SkeletonFile;
    fn files(&self) -> Box<Iterator<Item = Self::File>>;
}

pub trait SkeletonFile: Sized {
    fn path(&self) -> &Path;
    fn contents(&self) -> Result<Box<Read>>;
}

#[derive(Debug)]
pub struct FsSkeleton {
    pub root: PathBuf,
}

impl Skeleton for FsSkeleton {
    type File = FsFile;
    fn files(&self) -> Box<Iterator<Item = FsFile>> {
        let root = self.root.clone();
        return Box::new(WalkDir::new(self.root.as_path()).into_iter()
        .map(|entry| entry.unwrap())
        .filter(|entry| entry.file_type().is_file())
        .map(move |entry| {
            println!("{:?}", root);
            FsFile {
                full_path: entry.path().to_path_buf(),
                path: entry.path().strip_prefix(&root).unwrap().to_path_buf(),
            }
        }));
    }
}

pub struct FsFile {
    path: PathBuf,
    full_path: PathBuf,
}

impl SkeletonFile for FsFile {
    fn path(&self) -> &Path {
        self.path.as_path()
    }
    fn contents(&self) -> Result<Box<Read>> {
        let file = File::open(self.full_path.as_path())?;
        Ok(Box::new(BufReader::new(file)))
    }
}

#[test]
fn test_fs_skeleton_reader(){
    let dir = TempDir::new("yorick-test-skeleton-reader").unwrap();

    // write content
    let mut file1 = File::create(dir.path().join("foo")).unwrap();
    file1.write(b"FOO").unwrap();
    create_dir(dir.path().join("bar")).unwrap();
    let mut file1 = File::create(dir.path().join("bar/baz")).unwrap();
    file1.write(b"QUX").unwrap();

    // test skeleton
    let skel = FsSkeleton{ root: dir.path().to_path_buf() };
    let mut file_map = HashMap::new();
    for file in skel.files() {
        let mut contents = Vec::new();
        file.contents().unwrap().read_to_end(&mut contents).unwrap();
        let path = file.path().to_path_buf();
        file_map.insert(path, contents);
    }
    assert_eq!(file_map.len(), 2);
    println!("files read: {:?}", file_map);
    assert_eq!(file_map.get(Path::new("foo")).unwrap().as_slice(), b"FOO");
    assert_eq!(file_map.get(Path::new("bar/baz")).unwrap().as_slice(), b"QUX");
}
<|endoftext|>


<commit_before>use crate::time::Time;

/// A subtitle item
#[derive(Debug)]
pub struct Subtitle {
    /// A number indicating which subtitle it is in the sequence
    pub pos: usize,
    /// The time that the subtitle should appear
    pub start_time: Time,
    /// The time that the subtitle should disappear
    pub end_time: Time,
    /// The subtitle itself
    pub text: String,
}
<commit_msg>Impl Display for Subtitle<commit_after>use crate::time::Time;
use std::fmt;

/// A subtitle item
#[derive(Debug)]
pub struct Subtitle {
    /// A number indicating which subtitle it is in the sequence
    pub pos: usize,
    /// The time that the subtitle should appear
    pub start_time: Time,
    /// The time that the subtitle should disappear
    pub end_time: Time,
    /// The subtitle itself
    pub text: String,
}

impl fmt::Display for Subtitle {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        write!(
            out,
            "{}\n{}-->{}\n{}",
            self.pos, self.start_time, self.end_time, self.text
        )
    }
}

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

    #[test]
    fn display() {
        let subtitle = Subtitle {
            pos: 1,
            start_time: Time {
                hours: 0,
                minutes: 0,
                seconds: 5,
                milliseconds: 200,
            },
            end_time: Time {
                hours: 0,
                minutes: 0,
                seconds: 6,
                milliseconds: 300,
            },
            text: String::from("test"),
        };
        assert_eq!(subtitle.to_string(), "1\n00:00:05,200-->00:00:06,300\ntest");
    }
}
<|endoftext|>