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

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

#![deny(trivial_casts)]

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

mod draw;
use draw::draw;
use draw::get_absolute_draw_indices;
mod find;
use find::FindOptSubset;

extern crate ncurses;
use ncurses::*;

extern crate getopts;
use getopts::Options;

extern crate pest;
#[macro_use]
extern crate pest_derive;

use pest::Parser;

#[derive(Parser)]
#[grammar = "cmd.pest"]
struct IdentParser;

extern crate memmem;
use memmem::{Searcher, TwoWaySearcher};

#[derive(PartialEq, Copy, Clone)]
pub enum Cursorstate {
    Leftnibble,
    Rightnibble,
    Asciichar,
}

fn main() {
    const VERSION: &str = env!("CARGO_PKG_VERSION");
    let mut buf = vec![];
    let mut cursorpos: usize = 0;
    let mut cstate: Cursorstate = Cursorstate::Leftnibble;
    // 0 = display data from first line of file
    let mut screenoffset: usize = 0;
    const SPALTEN: usize = 16;
    let mut command = String::new();
    let mut lastcommand = String::new();
    let mut debug = String::new();

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

    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("v", "version", "print the version");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            endwin();
            println!("{}", f.to_string());
            println!("Usage: {} FILE [options]", program);
            return;
        }
    };
    if matches.opt_present("v") {
        endwin();
        println!("Version: {}", VERSION);
        return;
    }
    if matches.opt_present("h") {
        endwin();
        println!("Usage: {} FILE [options]", program);
        return;
    }

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

    let patharg = match matches.free.is_empty() {
        true => String::new(),
        false => matches.free[0].clone(),
    };
    let path = Path::new(&patharg);

    if patharg.is_empty() {
        endwin();
        println!("Patharg is empty!\n");
        return;
    }

    let mut file = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(&path) {
        Err(why) => {
            endwin();
            println!("Could not open {}: {}", path.display(), why.to_string());
            return;
        }
        Ok(file) => file,
    };
    file.read_to_end(&mut buf).ok().expect(
        "File could not be read.",
    );

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
    draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);

    let mut quitnow = false;
    let mut autoparse = false;
    while quitnow == false {
        let mut key: char = '0';
        if !autoparse {
            key = std::char::from_u32(getch() as u32).unwrap();
            command.push_str(&key.clone().to_string());
        }
        autoparse = false;

        let parsethisstring = command.clone();
        let commands = IdentParser::parse(Rule::cmd_list, &parsethisstring)
            .unwrap_or_else(|e| panic!("{}", e));

        let mut clear = true;
        let mut save = false;
        for cmd in commands {
            match cmd.as_rule() {
                Rule::down => {
                    // debug.push_str(&format!("{:?}", cmd.as_rule()));
                    if cursorpos + SPALTEN < buf.len() {
                        // not at end
                        cursorpos += SPALTEN;
                    } else {
                        // when at end
                        if buf.len() != 0 {
                            // Suppress underflow
                            cursorpos = buf.len() - 1;
                        }
                    }
                }
                Rule::up => {
                    if cursorpos >= SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                Rule::left => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos > 0 {
                            cursorpos -= 1;
                        }
                    } else if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    } else if cstate == Cursorstate::Leftnibble {
                        if cursorpos > 0 {
                            // not at start
                            cstate = Cursorstate::Rightnibble;
                            cursorpos -= 1;
                        }
                    }
                }
                Rule::right => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cursorpos += 1;
                        }
                    } else if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    } else if cstate == Cursorstate::Rightnibble {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cstate = Cursorstate::Leftnibble;
                            cursorpos += 1;
                        }
                    }
                }
                Rule::start => {
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    }
                }
                Rule::end => {
                    // check if no overflow
                    if cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1) < buf.len() {
                        // jump to end of line
                        cursorpos = cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1);
                    } else {
                        // jump to end of line
                        cursorpos = buf.len() - 1
                    }
                    if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    }
                }
                Rule::bottom => {
                    cursorpos = buf.len() - 1;
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                }
                Rule::replace => {
                    // debug.push_str("next char will be the replacement!");
                    clear = false;
                }
                Rule::remove => {
                    // check if in valid range
                    if buf.len() > 0 && cursorpos < buf.len() {
                        // remove the current char
                        buf.remove(cursorpos);
                    }
                    // always perform the movement if possible
                    if cursorpos > 0 && cursorpos >= buf.len() {
                        cursorpos -= 1;
                    }
                    lastcommand = command.clone();
                }
                Rule::insert => {
                    // debug.push_str("next chars will be inserted!");
                    clear = false;
                }
                Rule::jumpascii => {
                    if cstate == Cursorstate::Asciichar {
                        cstate = Cursorstate::Leftnibble;
                    } else {
                        cstate = Cursorstate::Asciichar;
                    }
                }
                Rule::helpfile => {
                    command.push_str("No helpfile yet");
                }
                Rule::repeat => {
                    command = lastcommand.clone();
                    clear = false;
                    autoparse = true;
                }
                Rule::backspace => {
                    command.pop();
                    command.pop();
                    clear = false;
                }
                Rule::saveandexit => {
                    save = true;
                    quitnow = true;
                }
                Rule::exit => quitnow = true,
                Rule::save => save = true,

                _ => (),
            }

            for inner_cmd in cmd.into_inner() {
                match inner_cmd.as_rule() {
                    Rule::replacement => {
                        // TODO: use inner_cmd and not just "key"
                        // debug.push_str(&format!("Replacement: {:?}", inner_cmd.as_str()));
                        if cstate == Cursorstate::Asciichar {
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // buf[cursorpos] = inner_cmd.as_str();
                            buf[cursorpos] = key as u8;
                        } else {
                            let mask = if cstate == Cursorstate::Leftnibble {
                                0x0F
                            } else {
                                0xF0
                            };
                            let shift = if cstate == Cursorstate::Leftnibble {
                                4
                            } else {
                                0
                            };
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // Change the selected nibble
                            if let Some(c) = key.to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & mask | (c as u8) << shift;
                            }
                        }
                        lastcommand.clear();
                        lastcommand.push_str(&format!("Command repeation for {:?} not yet implemented.", inner_cmd.as_rule()));
                    }
                    Rule::dd_lines => {
                        let amount: usize = inner_cmd.as_str().parse().unwrap_or(1);
                        // check if in valid range
                        if buf.len() > 0 && cursorpos < buf.len() {
                            let startofline = cursorpos - cursorpos % SPALTEN;
                            let mut endofline = cursorpos - (cursorpos % SPALTEN) + (SPALTEN * amount ) ;
                            endofline = cmp::min( endofline, buf.len() );
                            buf.drain(startofline..endofline);
                        }
                        lastcommand = command.clone();
                    }
                    // TODO: use inner_cmd and not just "key"
                    Rule::insertment => {
                        lastcommand = command.clone();
                        // debug.push_str(&format!("Inserted: {:?}", inner_cmd.as_str()));
                        command.pop(); // remove the just inserted thing
                        clear = false;

                        if cstate == Cursorstate::Leftnibble {
                            // Left nibble
                            if let Some(c) = key.to_digit(16) {
                                buf.insert(cursorpos, (c as u8) << 4);
                                cstate = Cursorstate::Rightnibble;
                            }
                        } else if cstate == Cursorstate::Rightnibble {
                            // Right nibble
                            if cursorpos == buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            if let Some(c) = key.to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & 0xF0 | c as u8;
                                cstate = Cursorstate::Leftnibble;
                                cursorpos += 1;
                            }
                        } else if cstate == Cursorstate::Asciichar {
                            buf.insert(cursorpos, key as u8);
                            cursorpos += 1;
                        }
                        lastcommand.clear();
                        lastcommand.push_str(&format!("Command repeation for {:?} not yet implemented.", inner_cmd.as_rule()));
                    }
                    Rule::searchstr => {
                        let search = inner_cmd.as_str().as_bytes();
                        let foundpos = TwoWaySearcher::new(&search);
                        cursorpos = foundpos.search_in(&buf).unwrap_or(cursorpos);
                    }
                    Rule::searchbytes => {
                        let search = inner_cmd.as_str().as_bytes();
                        let mut needle = vec![];
                        for i in 0..search.len() {
                            let nibble = match search[i] as u8 {
                                c @ 48...57 => c - 48, // Numbers from 0 to 9
                                b'x' => 0x10, // x is the wildcard
                                b'X' => 0x10, // X is the wildcard
                                c @ b'a'...b'f' => c - 87,
                                c @ b'A'...b'F' => c - 55,
                                _ => panic!("Should not get to this position!"),
                            };
                            needle.push(nibble);
                        }
                        cursorpos = buf.find_subset(&needle).unwrap_or(cursorpos);
                        // debug.push_str(&format!("Searching for: {:?}", needle ));
                    }
                    Rule::gg_line => {
                        let linenr: usize = inner_cmd.as_str().parse().unwrap_or(0);
                        cursorpos = linenr * SPALTEN; // jump to the line
                        if cursorpos > buf.len() { // detect file end
                            cursorpos = buf.len();
                        }
                        cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    }
                    Rule::escape => (),
                    Rule::gatherone => clear = false,
                    _ => {
                        command.push_str(&format!("no rule for {:?} ", inner_cmd.as_rule()));
                        clear = false;
                    }
                };
            }
            if save {
                if path.exists() {
                    let mut file = match OpenOptions::new()
                        .read(true)
                        .write(true)
                        .create(true)
                        .open(&path) {
                        Err(why) => {
                            panic!(
                                "Could not open {}: {}",
                                path.display(),
                                Error::description(&why)
                            )
                        }
                        Ok(file) => file,
                    };
                    file.seek(SeekFrom::Start(0)).ok().expect(
                        "Filepointer could not be set to 0",
                    );
                    file.write_all(&mut buf).ok().expect(
                        "File could not be written.",
                    );
                    file.set_len(buf.len() as u64).ok().expect(
                        "File could not be set to correct lenght.",
                    );
                    command.push_str("File saved!");
                } else {
                    command.push_str("Careful, file could not be saved!");
                }
                // TODO: define filename during runtime
                save = false;
            }
            if clear {
                command.clear();
            }

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

        }

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
        draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);
    }

    refresh();
    endwin();
}
<commit_msg>Cleanup key/command<commit_after>//! # Hexdino
//!
//! A hex editor with vim like keybindings written in Rust.

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

#![deny(trivial_casts)]

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

mod draw;
use draw::draw;
use draw::get_absolute_draw_indices;
mod find;
use find::FindOptSubset;

extern crate ncurses;
use ncurses::*;

extern crate getopts;
use getopts::Options;

extern crate pest;
#[macro_use]
extern crate pest_derive;

use pest::Parser;

#[derive(Parser)]
#[grammar = "cmd.pest"]
struct IdentParser;

extern crate memmem;
use memmem::{Searcher, TwoWaySearcher};

#[derive(PartialEq, Copy, Clone)]
pub enum Cursorstate {
    Leftnibble,
    Rightnibble,
    Asciichar,
}

fn main() {
    const VERSION: &str = env!("CARGO_PKG_VERSION");
    let mut buf = vec![];
    let mut cursorpos: usize = 0;
    let mut cstate: Cursorstate = Cursorstate::Leftnibble;
    // 0 = display data from first line of file
    let mut screenoffset: usize = 0;
    const SPALTEN: usize = 16;
    let mut command = String::new();
    let mut lastcommand = String::new();
    let mut debug = String::new();

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

    let args: Vec<_> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help menu");
    opts.optflag("v", "version", "print the version");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            endwin();
            println!("{}", f.to_string());
            println!("Usage: {} FILE [options]", program);
            return;
        }
    };
    if matches.opt_present("v") {
        endwin();
        println!("Version: {}", VERSION);
        return;
    }
    if matches.opt_present("h") {
        endwin();
        println!("Usage: {} FILE [options]", program);
        return;
    }

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

    let patharg = match matches.free.is_empty() {
        true => String::new(),
        false => matches.free[0].clone(),
    };
    let path = Path::new(&patharg);

    if patharg.is_empty() {
        endwin();
        println!("Patharg is empty!\n");
        return;
    }

    let mut file = match OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(&path) {
        Err(why) => {
            endwin();
            println!("Could not open {}: {}", path.display(), why.to_string());
            return;
        }
        Ok(file) => file,
    };
    file.read_to_end(&mut buf).ok().expect(
        "File could not be read.",
    );

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
    draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);

    let mut quitnow = false;
    let mut autoparse = false;
    while quitnow == false {
        if !autoparse {
            let key = std::char::from_u32(getch() as u32).unwrap();
            command.push_str(&key.clone().to_string());
        }
        autoparse = false;

        let parsethisstring = command.clone();
        let commands = IdentParser::parse(Rule::cmd_list, &parsethisstring)
            .unwrap_or_else(|e| panic!("{}", e));

        let mut clear = true;
        let mut save = false;
        for cmd in commands {
            match cmd.as_rule() {
                Rule::down => {
                    // debug.push_str(&format!("{:?}", cmd.as_rule()));
                    if cursorpos + SPALTEN < buf.len() {
                        // not at end
                        cursorpos += SPALTEN;
                    } else {
                        // when at end
                        if buf.len() != 0 {
                            // Suppress underflow
                            cursorpos = buf.len() - 1;
                        }
                    }
                }
                Rule::up => {
                    if cursorpos >= SPALTEN {
                        cursorpos -= SPALTEN;
                    }
                }
                Rule::left => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos > 0 {
                            cursorpos -= 1;
                        }
                    } else if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    } else if cstate == Cursorstate::Leftnibble {
                        if cursorpos > 0 {
                            // not at start
                            cstate = Cursorstate::Rightnibble;
                            cursorpos -= 1;
                        }
                    }
                }
                Rule::right => {
                    if cstate == Cursorstate::Asciichar {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cursorpos += 1;
                        }
                    } else if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    } else if cstate == Cursorstate::Rightnibble {
                        if cursorpos + 1 < buf.len() {
                            // not at end
                            cstate = Cursorstate::Leftnibble;
                            cursorpos += 1;
                        }
                    }
                }
                Rule::start => {
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    if cstate == Cursorstate::Rightnibble {
                        cstate = Cursorstate::Leftnibble;
                    }
                }
                Rule::end => {
                    // check if no overflow
                    if cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1) < buf.len() {
                        // jump to end of line
                        cursorpos = cursorpos - (cursorpos % SPALTEN) + (SPALTEN - 1);
                    } else {
                        // jump to end of line
                        cursorpos = buf.len() - 1
                    }
                    if cstate == Cursorstate::Leftnibble {
                        cstate = Cursorstate::Rightnibble;
                    }
                }
                Rule::bottom => {
                    cursorpos = buf.len() - 1;
                    cursorpos -= cursorpos % SPALTEN; // jump to start of line
                }
                Rule::replace => {
                    // debug.push_str("next char will be the replacement!");
                    clear = false;
                }
                Rule::remove => {
                    // check if in valid range
                    if buf.len() > 0 && cursorpos < buf.len() {
                        // remove the current char
                        buf.remove(cursorpos);
                    }
                    // always perform the movement if possible
                    if cursorpos > 0 && cursorpos >= buf.len() {
                        cursorpos -= 1;
                    }
                    lastcommand = command.clone();
                }
                Rule::insert => {
                    // debug.push_str("next chars will be inserted!");
                    clear = false;
                }
                Rule::jumpascii => {
                    if cstate == Cursorstate::Asciichar {
                        cstate = Cursorstate::Leftnibble;
                    } else {
                        cstate = Cursorstate::Asciichar;
                    }
                }
                Rule::helpfile => {
                    command.push_str("No helpfile yet");
                }
                Rule::repeat => {
                    command = lastcommand.clone();
                    clear = false;
                    autoparse = true;
                }
                Rule::backspace => {
                    command.pop();
                    command.pop();
                    clear = false;
                }
                Rule::saveandexit => {
                    save = true;
                    quitnow = true;
                }
                Rule::exit => quitnow = true,
                Rule::save => save = true,

                _ => (),
            }

            for inner_cmd in cmd.into_inner() {
                match inner_cmd.as_rule() {
                    Rule::replacement => {
                        let key = inner_cmd.as_str().chars().nth(0).unwrap_or('x');
                        if cstate == Cursorstate::Asciichar {
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // buf[cursorpos] = inner_cmd.as_str();
                            buf[cursorpos] = key as u8;
                        } else {
                            let mask = if cstate == Cursorstate::Leftnibble {
                                0x0F
                            } else {
                                0xF0
                            };
                            let shift = if cstate == Cursorstate::Leftnibble {
                                4
                            } else {
                                0
                            };
                            if cursorpos >= buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            // Change the selected nibble
                            if let Some(c) = key.to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & mask | (c as u8) << shift;
                            }
                        }
                        lastcommand.clear();
                        lastcommand.push_str(&format!("Command repeation for {:?} not yet implemented.", inner_cmd.as_rule()));
                    }
                    Rule::dd_lines => {
                        let amount: usize = inner_cmd.as_str().parse().unwrap_or(1);
                        // check if in valid range
                        if buf.len() > 0 && cursorpos < buf.len() {
                            let startofline = cursorpos - cursorpos % SPALTEN;
                            let mut endofline = cursorpos - (cursorpos % SPALTEN) + (SPALTEN * amount ) ;
                            endofline = cmp::min( endofline, buf.len() );
                            buf.drain(startofline..endofline);
                        }
                        lastcommand = command.clone();
                    }
                    Rule::insertment => {
                        let key = inner_cmd.as_str().chars().nth(0).unwrap_or('x');
                        lastcommand = command.clone();
                        // debug.push_str(&format!("Inserted: {:?}", inner_cmd.as_str()));
                        command.pop(); // remove the just inserted thing
                        clear = false;

                        if cstate == Cursorstate::Leftnibble {
                            // Left nibble
                            if let Some(c) = key.to_digit(16) {
                                buf.insert(cursorpos, (c as u8) << 4);
                                cstate = Cursorstate::Rightnibble;
                            }
                        } else if cstate == Cursorstate::Rightnibble {
                            // Right nibble
                            if cursorpos == buf.len() {
                                buf.insert(cursorpos, 0);
                            }
                            if let Some(c) = key.to_digit(16) {
                                buf[cursorpos] = buf[cursorpos] & 0xF0 | c as u8;
                                cstate = Cursorstate::Leftnibble;
                                cursorpos += 1;
                            }
                        } else if cstate == Cursorstate::Asciichar {
                            buf.insert(cursorpos, key as u8);
                            cursorpos += 1;
                        }
                        lastcommand.clear();
                        lastcommand.push_str(&format!("Command repeation for {:?} not yet implemented.", inner_cmd.as_rule()));
                    }
                    Rule::searchstr => {
                        let search = inner_cmd.as_str().as_bytes();
                        let foundpos = TwoWaySearcher::new(&search);
                        cursorpos = foundpos.search_in(&buf).unwrap_or(cursorpos);
                    }
                    Rule::searchbytes => {
                        let search = inner_cmd.as_str().as_bytes();
                        let mut needle = vec![];
                        for i in 0..search.len() {
                            let nibble = match search[i] as u8 {
                                c @ 48...57 => c - 48, // Numbers from 0 to 9
                                b'x' => 0x10, // x is the wildcard
                                b'X' => 0x10, // X is the wildcard
                                c @ b'a'...b'f' => c - 87,
                                c @ b'A'...b'F' => c - 55,
                                _ => panic!("Should not get to this position!"),
                            };
                            needle.push(nibble);
                        }
                        cursorpos = buf.find_subset(&needle).unwrap_or(cursorpos);
                        // debug.push_str(&format!("Searching for: {:?}", needle ));
                    }
                    Rule::gg_line => {
                        let linenr: usize = inner_cmd.as_str().parse().unwrap_or(0);
                        cursorpos = linenr * SPALTEN; // jump to the line
                        if cursorpos > buf.len() { // detect file end
                            cursorpos = buf.len();
                        }
                        cursorpos -= cursorpos % SPALTEN; // jump to start of line
                    }
                    Rule::escape => (),
                    Rule::gatherone => clear = false,
                    _ => {
                        command.push_str(&format!("no rule for {:?} ", inner_cmd.as_rule()));
                        clear = false;
                    }
                };
            }
            if save {
                if path.exists() {
                    let mut file = match OpenOptions::new()
                        .read(true)
                        .write(true)
                        .create(true)
                        .open(&path) {
                        Err(why) => {
                            panic!(
                                "Could not open {}: {}",
                                path.display(),
                                Error::description(&why)
                            )
                        }
                        Ok(file) => file,
                    };
                    file.seek(SeekFrom::Start(0)).ok().expect(
                        "Filepointer could not be set to 0",
                    );
                    file.write_all(&mut buf).ok().expect(
                        "File could not be written.",
                    );
                    file.set_len(buf.len() as u64).ok().expect(
                        "File could not be set to correct lenght.",
                    );
                    command.push_str("File saved!");
                } else {
                    command.push_str("Careful, file could not be saved!");
                }
                // TODO: define filename during runtime
                save = false;
            }
            if clear {
                command.clear();
            }

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

        }

    let draw_range = get_absolute_draw_indices(buf.len(), SPALTEN, screenoffset);
        draw(&buf[draw_range.0 .. draw_range.1], cursorpos, SPALTEN, &command, &mut debug, cstate, screenoffset);
    }

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


<commit_before>#[macro_use]
extern crate clap;
#[macro_use]
extern crate error_chain;
extern crate liquid;

#[cfg(feature = "serde_yaml")]
extern crate serde_yaml;
#[cfg(feature = "serde_json")]
extern crate serde_json;

use std::ffi;
use std::fs;
use std::io;
use std::io::Write;
use std::path;
use liquid::Renderable;

error_chain! {
    links {
    }

    foreign_links {
        Clap(clap::Error);
        Io(io::Error);
        Liquid(liquid::Error);
        Yaml(serde_yaml::Error) #[cfg(feature = "serde_yaml")];
        Json(serde_json::Error) #[cfg(feature = "serde_json")];
    }

    errors {
    }
}

fn option<'a>(name: &'a str, value: &'a str) -> clap::Arg<'a, 'a> {
    clap::Arg::with_name(name).long(name).value_name(value)
}

#[cfg(feature = "serde_yaml")]
fn load_yaml(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_yaml::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_yaml"))]
fn load_yaml(_path: &path::Path) -> Result<liquid::Value> {
    bail!("yaml is unsupported");
}

#[cfg(feature = "serde_json")]
fn load_json(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_json::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_json"))]
fn load_json(_path: &path::Path) -> Result<liquid::Value> {
    bail!("json is unsupported");
}

fn build_context(path: &path::Path) -> Result<liquid::Context> {
    let extension = path.extension().unwrap_or_else(|| ffi::OsStr::new(""));
    let value = if extension == ffi::OsStr::new("yaml") {
        load_yaml(path)
    } else if extension == ffi::OsStr::new("yaml") {
        load_json(path)
    } else {
        Err("Unsupported file type".into())
    }?;
    let value = match value {
        liquid::Value::Object(o) => Ok(o),
        _ => Err("File must be an object"),
    }?;
    let data = liquid::Context::with_values(value);

    Ok(data)
}

fn run() -> Result<()> {
    let matches = clap::App::new("liquidate")
        .version(crate_version!())
        .author(crate_authors!())
        .arg(option("input", "LIQUID").required(true))
        .arg(option("output", "TXT"))
        .arg(option("context", "TOML"))
        .arg(option("include-root", "PATH"))
        .get_matches_safe()?;

    let mut options = liquid::LiquidOptions::default();
    options.file_system = matches.value_of("include-root").map(path::PathBuf::from);

    let mut data = matches
        .value_of("context")
        .map(|s| {
                 let p = path::PathBuf::from(s);
                 build_context(p.as_path())
             })
        .map_or(Ok(None), |r| r.map(Some))?
        .unwrap_or_else(liquid::Context::new);

    let template_path = matches
        .value_of("input")
        .map(path::PathBuf::from)
        .expect("Parameter was required");
    let template = liquid::parse_file(template_path, options)?;
    let output = template
        .render(&mut data)?
        .unwrap_or_else(|| "".to_string());
    match matches.value_of("output") {
        Some(path) => {
            let mut out = fs::File::create(path::PathBuf::from(path))?;
            out.write_all(output.as_bytes())?;
        }
        None => {
            println!("{}", output);
        }
    }

    Ok(())
}

quick_main!(run);
<commit_msg>fix(liquid-dbg): Stricter compilation<commit_after>#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

// Deny warnings, except in dev mode
#![deny(warnings)]
// #![deny(missing_docs)]
#![cfg_attr(feature="dev", warn(warnings))]

// Allow zero pointers for lazy_static. Otherwise clippy will complain.
#![allow(unknown_lints)]
#![allow(zero_ptr)]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate error_chain;
extern crate liquid;

#[cfg(feature = "serde_yaml")]
extern crate serde_yaml;
#[cfg(feature = "serde_json")]
extern crate serde_json;

use std::ffi;
use std::fs;
use std::io;
use std::io::Write;
use std::path;
use liquid::Renderable;

error_chain! {
    links {
    }

    foreign_links {
        Clap(clap::Error);
        Io(io::Error);
        Liquid(liquid::Error);
        Yaml(serde_yaml::Error) #[cfg(feature = "serde_yaml")];
        Json(serde_json::Error) #[cfg(feature = "serde_json")];
    }

    errors {
    }
}

fn option<'a>(name: &'a str, value: &'a str) -> clap::Arg<'a, 'a> {
    clap::Arg::with_name(name).long(name).value_name(value)
}

#[cfg(feature = "serde_yaml")]
fn load_yaml(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_yaml::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_yaml"))]
fn load_yaml(_path: &path::Path) -> Result<liquid::Value> {
    bail!("yaml is unsupported");
}

#[cfg(feature = "serde_json")]
fn load_json(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_json::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_json"))]
fn load_json(_path: &path::Path) -> Result<liquid::Value> {
    bail!("json is unsupported");
}

fn build_context(path: &path::Path) -> Result<liquid::Context> {
    let extension = path.extension().unwrap_or_else(|| ffi::OsStr::new(""));
    let value = if extension == ffi::OsStr::new("yaml") {
        load_yaml(path)
    } else if extension == ffi::OsStr::new("yaml") {
        load_json(path)
    } else {
        Err("Unsupported file type".into())
    }?;
    let value = match value {
        liquid::Value::Object(o) => Ok(o),
        _ => Err("File must be an object"),
    }?;
    let data = liquid::Context::with_values(value);

    Ok(data)
}

fn run() -> Result<()> {
    let matches = clap::App::new("liquidate")
        .version(crate_version!())
        .author(crate_authors!())
        .arg(option("input", "LIQUID").required(true))
        .arg(option("output", "TXT"))
        .arg(option("context", "TOML"))
        .arg(option("include-root", "PATH"))
        .get_matches_safe()?;

    let mut options = liquid::LiquidOptions::default();
    options.file_system = matches.value_of("include-root").map(path::PathBuf::from);

    let mut data = matches
        .value_of("context")
        .map(|s| {
                 let p = path::PathBuf::from(s);
                 build_context(p.as_path())
             })
        .map_or(Ok(None), |r| r.map(Some))?
        .unwrap_or_else(liquid::Context::new);

    let template_path = matches
        .value_of("input")
        .map(path::PathBuf::from)
        .expect("Parameter was required");
    let template = liquid::parse_file(template_path, options)?;
    let output = template
        .render(&mut data)?
        .unwrap_or_else(|| "".to_string());
    match matches.value_of("output") {
        Some(path) => {
            let mut out = fs::File::create(path::PathBuf::from(path))?;
            out.write_all(output.as_bytes())?;
        }
        None => {
            println!("{}", output);
        }
    }

    Ok(())
}

quick_main!(run);
<|endoftext|>


<commit_before>extern crate toml;

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::collections::BTreeMap;

fn strip_toolchain(name: &str) -> String {
    name.split('-').nth(0).unwrap().to_string()
}

fn read_settings() -> (String, BTreeMap<String, String>) {
    let mut settings_path = env::home_dir().unwrap();
    settings_path.push(".multirust/settings.toml");

    let mut file = File::open(&settings_path).expect("file open error");

    let mut buffer = String::new();
    file.read_to_string(&mut buffer).expect("read error");

    let value = toml::Parser::new(&buffer).parse().unwrap();
    let default = value.get("default_toolchain").unwrap().as_str().unwrap();
    let overrides = value.get("overrides").unwrap().as_table().unwrap();
    let overrides = overrides.iter()
        .map(|(k, v)| (k.to_string(), strip_toolchain(v.as_str().unwrap())))
        .collect();

    (default.into(), overrides)
}

fn main() {
    let cwd = env::current_dir().unwrap();
    let (default, overrides) = read_settings();

    let toolchain = match overrides.get(cwd.to_str().unwrap()) {
        Some(toolchain) => toolchain,
        None => &default,
    };

    println!("{}", toolchain);
}<commit_msg>rustfmt suggests a trailing newline<commit_after>extern crate toml;

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::collections::BTreeMap;

fn strip_toolchain(name: &str) -> String {
    name.split('-').nth(0).unwrap().to_string()
}

fn read_settings() -> (String, BTreeMap<String, String>) {
    let mut settings_path = env::home_dir().unwrap();
    settings_path.push(".multirust/settings.toml");

    let mut file = File::open(&settings_path).expect("file open error");

    let mut buffer = String::new();
    file.read_to_string(&mut buffer).expect("read error");

    let value = toml::Parser::new(&buffer).parse().unwrap();
    let default = value.get("default_toolchain").unwrap().as_str().unwrap();
    let overrides = value.get("overrides").unwrap().as_table().unwrap();
    let overrides = overrides.iter()
        .map(|(k, v)| (k.to_string(), strip_toolchain(v.as_str().unwrap())))
        .collect();

    (default.into(), overrides)
}

fn main() {
    let cwd = env::current_dir().unwrap();
    let (default, overrides) = read_settings();

    let toolchain = match overrides.get(cwd.to_str().unwrap()) {
        Some(toolchain) => toolchain,
        None => &default,
    };

    println!("{}", toolchain);
}
<|endoftext|>


<commit_before>/*
 * UpdateHub
 * Copyright (C) 2017
 * O.S. Systems Sofware LTDA: contact@ossystems.com.br
 *
 * SPDX-License-Identifier:     GPL-2.0
 */

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

#[macro_use]
extern crate serde_derive;
extern crate serde_ini;
extern crate serde;

extern crate parse_duration;

mod de_helpers;

mod settings;
mod runtime_settings;
mod cmdline;

use cmdline::CmdLine;
use settings::Settings;
use runtime_settings::RuntimeSettings;

fn main() {
    let cmdline = CmdLine::parse_args();

    stderrlog::new()
        .quiet(cmdline.quiet)
        .verbosity(if cmdline.debug { 3 } else { 1 })
        .verbosity(4)
        .init()
        .expect("Failed to initialize the logger.");

    let settings = Settings::new().load().expect("Failed to load settings.");
    let _runtime_settings = RuntimeSettings::new()
        .load(&settings.storage.runtime_settings)
        .expect("Failed to load runtime settings.");
}
<commit_msg>main: Fix default verbosity level<commit_after>/*
 * UpdateHub
 * Copyright (C) 2017
 * O.S. Systems Sofware LTDA: contact@ossystems.com.br
 *
 * SPDX-License-Identifier:     GPL-2.0
 */

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

#[macro_use]
extern crate serde_derive;
extern crate serde_ini;
extern crate serde;

extern crate parse_duration;

mod de_helpers;

mod settings;
mod runtime_settings;
mod cmdline;

use cmdline::CmdLine;
use settings::Settings;
use runtime_settings::RuntimeSettings;

fn main() {
    let cmdline = CmdLine::parse_args();

    stderrlog::new()
        .quiet(cmdline.quiet)
        .verbosity(if cmdline.debug { 3 } else { 2 })
        .init()
        .expect("Failed to initialize the logger.");

    let settings = Settings::new().load().expect("Failed to load settings.");
    let _runtime_settings = RuntimeSettings::new()
        .load(&settings.storage.runtime_settings)
        .expect("Failed to load runtime settings.");
}
<|endoftext|>


<commit_before>use async_std::io;
use async_std::prelude::*;
use async_std::task;
use async_std::fs;
use async_std::os::unix::io::AsRawFd;

use termios::{self, Termios};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

enum Packet {
    Inbound(String),
    Char(char), // TODO: Create Key enum
    Ignore,
}

fn main() -> Result<()> {
    task::block_on(async {
        // Get all inputs
        let stdin = io::stdin();
        let tty_in = get_tty().await?;

        // Get all outputs
        let mut tty_out = get_tty().await?;

        // TODO: This raw mode may need to be different than tty_out
        // BEGIN: RAW MODE
        let fd = tty_in.as_raw_fd();
        let tty = Termios::from_fd(fd)?;
        let mut raw_tty = tty;
        raw_tty.c_lflag &= !(termios::ICANON | termios::ECHO);
        termios::tcsetattr(fd, termios::TCSANOW, &raw_tty)?;
        // END:   RAW MODE

        // BEGIN: RAW MODE
        let fd = tty_out.as_raw_fd();
        let tty = Termios::from_fd(fd)?;
        let mut raw_tty = tty;
        raw_tty.c_lflag &= !(termios::ICANON | termios::ECHO);
        termios::tcsetattr(fd, termios::TCSANOW, &raw_tty)?;
        // END:   RAW MODE

        let std_reader = io::BufReader::new(stdin);
        let tty_reader = io::BufReader::new(tty_in);

        let std_lines = std_reader.lines()
            .map(|res| {
                let line = res.expect("Error reading from STDIN");

                Packet::Inbound(line)
            });

        // TODO: Transform sequence of bytes into Keys (arrow keys, Ctrl, chars, etc)
        let tty_lines = tty_reader.bytes()
            .map(|res| res.expect("Error reading from PTTY"))
            .scan(Vec::new(), |state, byte| {
                state.push(byte);

                let packet = match String::from_utf8(state.clone()) {
                    Ok(s) => {
                        state.clear();
                        if let Some(ch) = s.chars().next() {
                            Some(Packet::Char(ch))
                        } else {
                            Some(Packet::Ignore)
                        }
                    },
                    Err(_) => {
                        // probably the program needs the next byte to make sense of it
                        Some(Packet::Ignore)
                    }
                };

                packet
            });

        // This select works in a round robin fashion
        let mut all = futures::stream::select(tty_lines, std_lines);

        while let Some(packet) = all.next().await {
            let line = match packet {
                Packet::Inbound(s) => {
                    let l = format!("STDIN: {}", s);
                    Some(l)
                },
                Packet::Char(ch) => {
                    let l = format!("TTYIN: {:?}", ch);
                    Some(l)
                }
                Packet::Ignore => None,
            };

            if let Some(l) = line {
                let l = format!("{}\n", l);
                tty_out.write_all(l.as_bytes()).await?;
                tty_out.flush().await?;
            }
        }

        Ok(())
    })
}

async fn get_tty() -> Result<fs::File> {
    let tty = fs::OpenOptions::new()
        .read(true)
        .write(true)
        .open("/dev/tty")
        .await?;

    Ok(tty)
}
<commit_msg>Add channel to trigger program shutdown<commit_after>use async_std::io;
use async_std::prelude::*;
use async_std::task;
use async_std::fs;
use async_std::os::unix::io::AsRawFd;

use futures::{channel, FutureExt, SinkExt};

use termios::{self, Termios};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
type Sender<T> = channel::mpsc::UnboundedSender<T>;
type Receiver<T> = channel::mpsc::UnboundedReceiver<T>;

enum Packet {
    Inbound(String),
    Char(char), // TODO: Create Key enum
    Ignore,
    Done,
}

fn main() -> Result<()> {
    task::block_on(async {
        // Get all inputs
        let stdin = io::stdin();
        let tty_in = get_tty().await?;

        // Get all outputs
        let mut tty_out = get_tty().await?;

        // TODO: This raw mode may need to be different than tty_out
        // BEGIN: RAW MODE
        let fd = tty_in.as_raw_fd();
        let tty = Termios::from_fd(fd)?;
        let mut raw_tty = tty;
        raw_tty.c_lflag &= !(termios::ICANON | termios::ECHO);
        termios::tcsetattr(fd, termios::TCSANOW, &raw_tty)?;
        // END:   RAW MODE

        // BEGIN: RAW MODE
        let fd = tty_out.as_raw_fd();
        let tty = Termios::from_fd(fd)?;
        let mut raw_tty = tty;
        raw_tty.c_lflag &= !(termios::ICANON | termios::ECHO);
        termios::tcsetattr(fd, termios::TCSANOW, &raw_tty)?;
        // END:   RAW MODE

        let std_reader = io::BufReader::new(stdin);
        let tty_reader = io::BufReader::new(tty_in);

        let std_lines = std_reader.lines()
            .map(|res| {
                let line = res.expect("Error reading from STDIN");

                Packet::Inbound(line)
            });

        // TODO: Transform sequence of bytes into Keys (arrow keys, Ctrl, chars, etc)
        let tty_lines = tty_reader.bytes()
            .map(|res| res.expect("Error reading from PTTY"))
            .scan(Vec::new(), |state, byte| {
                state.push(byte);

                let packet = match String::from_utf8(state.clone()) {
                    Ok(s) => {
                        state.clear();
                        if let Some(ch) = s.chars().next() {
                            Some(Packet::Char(ch))
                        } else {
                            Some(Packet::Ignore)
                        }
                    },
                    Err(_) => {
                        // probably the program needs the next byte to make sense of it
                        Some(Packet::Ignore)
                    }
                };

                packet
            });

        // Let's add a shutdown channel so we can move logic to other futures/tasks later
        let (mut shutdown_sender, shutdown_receiver) = channel::mpsc::channel::<Packet>(1);

        // This select works in a round robin fashion
        let ins = futures::stream::select(tty_lines, std_lines);
        let mut all = futures::stream::select(shutdown_receiver, ins);

        while let Some(packet) = all.next().await {
            let line = match packet {
                Packet::Inbound(s) => {
                    let l = format!("STDIN: {}", s);
                    Some(l)
                },
                Packet::Char(ch) => {
                    match ch {
                        '\n' | '\u{1b}' => {
                            shutdown_sender
                                .try_send(Packet::Done)
                                .expect("Error shutting down");

                            None
                        },
                        _  => {
                            let l = format!("TTYIN: {:?}", ch);
                            Some(l)
                        }
                    }
                },
                Packet::Ignore => None,
                Packet::Done => break,
            };

            if let Some(l) = line {
                let l = format!("{}\n", l);
                tty_out.write_all(l.as_bytes()).await?;
                tty_out.flush().await?;
            }
        }

        drop(shutdown_sender);
        println!("All done!");

        Ok(())
    })
}

async fn get_tty() -> Result<fs::File> {
    let tty = fs::OpenOptions::new()
        .read(true)
        .write(true)
        .open("/dev/tty")
        .await?;

    Ok(tty)
}
<|endoftext|>


<commit_before>use std::fs;
use std::env;
use std::fs::File;
use std::io::Read;
use std::hash::Hasher;
use std::collections::HashMap;
use std::os::unix::fs::MetadataExt;
use std::collections::hash_map::DefaultHasher;

#[derive(Debug)]
struct FileEntry {
    inode: u64,
    dev:  u64,
    path : String,
}

fn collect_files(dir: &String, h: &mut HashMap<u64, Vec<FileEntry>>) {
    if let Ok(entries) = fs::read_dir(dir) {
        for entry in entries {
            if let Ok(entry) = entry {
                let path = entry.path();
                if let Some(path_str) = path.to_str() {
                    if let Ok(metadata) = path.symlink_metadata() {
                        let ft = metadata.file_type();
                        if ft.is_symlink() {
                            continue;
                        } else if ft.is_file() {
                            match metadata.len() {
                                0 => continue,
                                i => h.entry(i).or_insert_with(Vec::new)
                                      .push(
                                       FileEntry{ inode : metadata.ino(),
                                           dev   : metadata.dev(),
                                           path  : String::from(path_str),
                                       }),
                            };
                        } else if ft.is_dir() {
                            collect_files(&(String::from(path_str)), h);
                        }
                    }
                }
            }
        }
    } else {
        println!("{}: invalid directory", dir);
    }
}

fn find_duplicates(duplicates: &mut HashMap<u64, Vec<FileEntry>>,
                   vec: &Vec<FileEntry> ) {
    for file_entry in vec {
        if let Ok(mut file) = File::open(&file_entry.path) {
            let mut buf: [u8; 1024] = [0; 1024];
            if let Ok(nbytes) = file.read(&mut buf) {
                let mut hasher = DefaultHasher::new();
                hasher.write(&buf[..nbytes as usize]);
                let k = hasher.finish();
                duplicates.entry(k).or_insert_with(Vec::new)
                    .push(
                        FileEntry{ inode : file_entry.inode,
                            dev  : file_entry.dev,
                            path : file_entry.path.to_string(),
                        });
            }
        }
    }
}

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

    // Print out usage if no directories are given.
    if args.len() == 1 {
        println!("Usage: {} <dir1> [dir2 [dir3 ...]]", args[0]);
        ::std::process::exit(0);
    }

    let mut hmap: HashMap<u64, Vec<FileEntry> > = HashMap::new();

    for dir in &args[1..] {
        collect_files(dir, &mut hmap);
    }

    // Get rid of all the single entries.
    hmap.retain(|_, v| v.len() >= 2);

    let mut cluster = 1;

    for (key, val) in hmap.iter() {
        let mut duplicates: HashMap<u64, Vec<FileEntry> > = HashMap::new();
        find_duplicates(&mut duplicates, &val);

        for (hash, vec) in duplicates {
            if vec.len() >= 2 {
                println!("{} files in cluster {} (size: {}, digest: {})",
                         vec.len(), cluster, key, hash);
                for file_entry in vec {
                    println!("{}", file_entry.path);
                }
                cluster += 1;
            }
        }
    }
}
<commit_msg>More idiomatic changes<commit_after>use std::fs;
use std::env;
use std::fs::File;
use std::io::Read;
use std::hash::Hasher;
use std::collections::HashMap;
use std::os::unix::fs::MetadataExt;
use std::collections::hash_map::DefaultHasher;

#[derive(Debug)]
struct FileEntry {
    inode: u64,
    dev:  u64,
    path : String,
}

fn collect_files(dir: &String, h: &mut HashMap<u64, Vec<FileEntry>>) {
    let entries = match fs::read_dir(dir) {
        Ok(x) => x,
        _ => {
            println!("{}: invalid directory", dir);
            return
        },
    };

    for entry in entries {
        if let Ok(entry) = entry {
            let path = entry.path();
            if let Some(path_str) = path.to_str() {
                if let Ok(metadata) = path.symlink_metadata() {
                    let ft = metadata.file_type();
                    if ft.is_symlink() {
                        continue;
                    } else if ft.is_file() {
                        match metadata.len() {
                            0 => continue,
                            i => h.entry(i).or_insert_with(Vec::new)
                                  .push(
                                   FileEntry{ inode : metadata.ino(),
                                       dev   : metadata.dev(),
                                       path  : String::from(path_str),
                                   }),
                        };
                    } else if ft.is_dir() {
                        collect_files(&(String::from(path_str)), h);
                    }
                }
            }
        }
    }
}

fn find_duplicates(duplicates: &mut HashMap<u64, Vec<FileEntry>>,
                   vec: &Vec<FileEntry> ) {
    for file_entry in vec {
        if let Ok(mut file) = File::open(&file_entry.path) {
            let mut buf: [u8; 1024] = [0; 1024];
            if let Ok(nbytes) = file.read(&mut buf) {
                let mut hasher = DefaultHasher::new();
                hasher.write(&buf[..nbytes as usize]);
                let k = hasher.finish();
                duplicates.entry(k).or_insert_with(Vec::new)
                    .push(
                        FileEntry{ inode : file_entry.inode,
                            dev  : file_entry.dev,
                            path : file_entry.path.to_string(),
                        });
            }
        }
    }
}

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

    // Print out usage if no directories are given.
    if args.len() == 1 {
        println!("Usage: {} <dir1> [dir2 [dir3 ...]]", args[0]);
        ::std::process::exit(0);
    }

    let mut hmap: HashMap<u64, Vec<FileEntry> > = HashMap::new();

    for dir in &args[1..] {
        collect_files(dir, &mut hmap);
    }

    // Get rid of all the single entries.
    hmap.retain(|_, v| v.len() >= 2);

    let mut cluster = 1;

    for (key, val) in hmap.iter() {
        let mut duplicates: HashMap<u64, Vec<FileEntry> > = HashMap::new();
        find_duplicates(&mut duplicates, &val);

        for (hash, vec) in duplicates {
            if vec.len() >= 2 {
                println!("{} files in cluster {} (size: {}, digest: {})",
                         vec.len(), cluster, key, hash);
                for file_entry in vec {
                    println!("{}", file_entry.path);
                }
                cluster += 1;
            }
        }
    }
}
<|endoftext|>


<commit_before>use glium;
use glutin;
use rand;
use std;
use time;

use prelude::*;
use raytrace;
use scene;

fn solid_color(r: f32, g: f32, b: f32) -> scene::Texture {
  scene::Texture::SolidColor(RGB { r: r, g: g, b: b })
}

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

pub fn main() {
  use glium::DisplayBuild;

  let window =
    glutin::WindowBuilder::new()
    .with_dimensions(WINDOW_WIDTH, WINDOW_HEIGHT)
    .build_glium()
    .unwrap();

  let mut scene =
    scene::T {
      objects       :
        vec!(
          // red ball
          scene::Object { center: Point::new(-4.0,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.0 , texture: solid_color(1.0, 0.0, 0.0) },
          // blue ball
          scene::Object { center: Point::new(-0.5,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 0.5, texture: solid_color(0.0, 0.6, 1.0) },
          // frosted glass ball
          scene::Object { center: Point::new(-0.7,   -0.5,  -1.5), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.8, shininess: 0.8, texture: solid_color(0.9, 0.9, 1.0) },
          // glass ball
          scene::Object { center: Point::new( 0.2,   -0.5,  -1.0), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 2.0 , texture: solid_color(0.9, 0.9, 1.0) },
          // brass ball
          scene::Object { center: Point::new( 3.0,    1.5, -10.0), radius:   4.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.1 , texture: solid_color(1.0, 0.4, 0.1) },
          // small mirror ball
          scene::Object { center: Point::new( 3.0,   -1.0,  -3.5), radius:   1.0, emittance:  0.0, reflectance: 0.9, transmittance: 0.0, shininess: 2.0 , texture: solid_color(1.0, 1.0, 1.0) },
          // light
          scene::Object { center: Point::new(-9.0,   10.0,   0.0), radius:   1.0, emittance:  1.0, reflectance: 0.0, transmittance: 1.0, shininess: 2.0 , texture: solid_color(0.9, 0.9, 1.0) },
          // walls
          scene::Object { center: Point::new( 0.0,    0.0,   0.0), radius:  20.0, emittance:  0.2, reflectance: 0.0, transmittance: 0.0, shininess: 2.0 , texture: solid_color(1.0, 1.0, 1.0) },
          // floor
          scene::Object { center: Point::new( 0.0, -102.0,   0.0), radius: 100.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.5, texture: solid_color(0.4, 0.2, 0.0) },
        ),
      fovy          : std::f32::consts::FRAC_PI_2,
      eye           : Point::new(0.0, 0.0,  0.0),
      look          : Vector::new(0.0, 0.0, -1.0),
      up            : Vector::new(0.0, 1.0,  0.0),
    };

  let inv_min_scale = 1 << 5;
  let w = WINDOW_WIDTH / inv_min_scale;
  let h = WINDOW_HEIGHT / inv_min_scale;
  let max_scale = inv_min_scale << 1;

  let framebuffer_texture = {
    let w = w * max_scale;
    let h = h * max_scale;
    glium::texture::Texture2d::new(
      &window,
      glium::texture::RawImage2d {
        width  : w,
        height : h,
        format : glium::texture::ClientFormat::F32F32F32,
        data   : std::borrow::Cow::Owned(std::iter::repeat((0.0, 0.0, 0.0)).take((w*h) as usize).collect()),
      },
    ).unwrap()
  };

  let mut framebuffer = glium::framebuffer::SimpleFrameBuffer::new(&window, &framebuffer_texture).unwrap();

  let mut rng: rand::XorShiftRng = rand::SeedableRng::from_seed([0x12345678, 0x9abcdef0, 0x13371337, 0x98765432]);

  let mut stationary_frames_drawn = 0;
  loop {
    let scale = std::cmp::min(max_scale, 1 << stationary_frames_drawn);
    let w = w * scale;
    let h = h * scale;

    let before = time::precise_time_ns();
    let rendered = raytrace::scene(&scene, w, h, &mut rng);
    let after = time::precise_time_ns();
    println!("Render took {:?}ms", (after - before) as f32 / 1_000_000.0);

    let rendered =
      glium::texture::Texture2d::with_format(
        &window,
        glium::texture::RawImage2d {
          data: std::borrow::Cow::Owned(rendered.to_vec()),
          width: w,
          height: h,
          format: glium::texture::ClientFormat::F32F32F32,
        },
        glium::texture::UncompressedFloatFormat::F32F32F32,
        glium::texture::MipmapsOption::NoMipmap,
      )
      .unwrap();

    let draw_parameters =
      glium::DrawParameters {
        depth:
          glium::Depth {
            test: glium::DepthTest::Overwrite,
            write: false,
            .. Default::default()
          },
        blend:
          glium::Blend {
            color: glium::BlendingFunction::AlwaysReplace,
            alpha: glium::BlendingFunction::AlwaysReplace,
            constant_value: (0.0, 0.0, 0.0, 0.0),
          },
        .. Default::default()
      };

    let source =
      glium::uniforms::Sampler::new(&rendered)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear);

    draw(&window, source, &mut framebuffer, &draw_parameters);

    let source =
      glium::uniforms::Sampler::new(&framebuffer_texture)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::Linear);

    let mut target = window.draw();
    glium::Surface::clear(&mut target, None, Some((0.0, 0.0, 0.0, 1.0)), false, None, None);
    draw(&window, source, &mut target, &draw_parameters);
    target.finish().unwrap();

    stationary_frames_drawn += 1;

    for event in window.poll_events() {
      // because closures get belligerent about borrowing. Yes, really.
      // I don't make the rules, I just do what makes me hate myself the least.
      macro_rules! move_camera {
        ( $v:expr ) => {
          let v = $v;
          scene.move_camera(&v);
          stationary_frames_drawn = 0;
        };
      }

      match event {
        glutin::Event::Closed => return,
        glutin::Event::KeyboardInput(glium::glutin::ElementState::Pressed, _, Some(key)) => {
          match key {
            glutin::VirtualKeyCode::W => {
              move_camera!(scene.z());
            },
            glutin::VirtualKeyCode::S => {
              move_camera!(-scene.z());
            },
            glutin::VirtualKeyCode::D => {
              move_camera!(scene.x());
            },
            glutin::VirtualKeyCode::A => {
              move_camera!(-scene.x());
            },
            _ => {},
          }
        },
        _ => {},
      }
    }
  }
}

fn draw<'a, Dest: glium::Surface>(
  window: &glium::backend::glutin_backend::GlutinFacade,
  source: glium::uniforms::Sampler<'a, glium::Texture2d>,
  destination: &mut Dest,
  draw_parameters: &glium::DrawParameters,
) {
  // building the vertex buffer, which contains all the vertices that we will draw
  let vertex_buffer = {
    #[derive(Copy, Clone)]
    struct Vertex {
      position: [f32; 2],
      tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    glium::VertexBuffer::new(
      window,
      &[
      Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
      Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
      Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
      Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
      ]
    ).unwrap()
  };

  // building the index buffer
  let index_buffer =
    glium::IndexBuffer::new(
      window,
      glium::index::PrimitiveType::TriangleStrip,
      &[1 as u16, 2, 0, 3],
    ).unwrap();

  // compiling shaders and linking them together
  let program =
    program!(
      window,
      330 => {
        vertex: "
          #version 330

          uniform mat4 matrix;

          in vec2 position;
          in vec2 tex_coords;

          out vec2 v_tex_coords;

          void main() {
            gl_Position = matrix * vec4(position, 0.0, 1.0);
            v_tex_coords = tex_coords;
          }
        ",

        fragment: "
          #version 330
          uniform sampler2D tex;
          in vec2 v_tex_coords;
          out vec4 f_color;

          void main() {
            f_color = texture(tex, v_tex_coords);
          }
        "
      },
    ).unwrap();

  // building the uniforms
  let uniforms = uniform! {
    matrix: [
      [1.0, 0.0, 0.0, 0.0],
      [0.0, 1.0, 0.0, 0.0],
      [0.0, 0.0, 1.0, 0.0],
      [0.0, 0.0, 0.0, 1.0f32]
    ],
    tex: source,
  };

  destination.draw(
    &vertex_buffer,
    &index_buffer,
    &program,
    &uniforms,
    &draw_parameters,
  ).unwrap();
}
<commit_msg>whitespace<commit_after>use glium;
use glutin;
use rand;
use std;
use time;

use prelude::*;
use raytrace;
use scene;

fn solid_color(r: f32, g: f32, b: f32) -> scene::Texture {
  scene::Texture::SolidColor(RGB { r: r, g: g, b: b })
}

pub const WINDOW_WIDTH: u32 = 800;
pub const WINDOW_HEIGHT: u32 = 600;

pub fn main() {
  use glium::DisplayBuild;

  let window =
    glutin::WindowBuilder::new()
    .with_dimensions(WINDOW_WIDTH, WINDOW_HEIGHT)
    .build_glium()
    .unwrap();

  let mut scene =
    scene::T {
      objects       :
        vec!(
          // red ball
          scene::Object { center: Point::new(-4.0,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.0, texture: solid_color(1.0, 0.0, 0.0) },
          // blue ball
          scene::Object { center: Point::new(-0.5,   -1.0,  -5.0), radius:   1.0, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 0.5, texture: solid_color(0.0, 0.6, 1.0) },
          // frosted glass ball
          scene::Object { center: Point::new(-0.7,   -0.5,  -1.5), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.8, shininess: 0.8, texture: solid_color(0.9, 0.9, 1.0) },
          // glass ball
          scene::Object { center: Point::new( 0.2,   -0.5,  -1.0), radius:   0.5, emittance:  0.0, reflectance: 0.1, transmittance: 0.9, shininess: 2.0, texture: solid_color(0.9, 0.9, 1.0) },
          // brass ball
          scene::Object { center: Point::new( 3.0,    1.5, -10.0), radius:   4.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.1, texture: solid_color(1.0, 0.4, 0.1) },
          // small mirror ball
          scene::Object { center: Point::new( 3.0,   -1.0,  -3.5), radius:   1.0, emittance:  0.0, reflectance: 0.9, transmittance: 0.0, shininess: 2.0, texture: solid_color(1.0, 1.0, 1.0) },
          // light
          scene::Object { center: Point::new(-9.0,   10.0,   0.0), radius:   1.0, emittance:  1.0, reflectance: 0.0, transmittance: 1.0, shininess: 2.0, texture: solid_color(0.9, 0.9, 1.0) },
          // walls
          scene::Object { center: Point::new( 0.0,    0.0,   0.0), radius:  20.0, emittance:  0.2, reflectance: 0.0, transmittance: 0.0, shininess: 2.0, texture: solid_color(1.0, 1.0, 1.0) },
          // floor
          scene::Object { center: Point::new( 0.0, -102.0,   0.0), radius: 100.0, emittance:  0.0, reflectance: 1.0, transmittance: 0.0, shininess: 0.5, texture: solid_color(0.4, 0.2, 0.0) },
        ),
      fovy          : std::f32::consts::FRAC_PI_2,
      eye           : Point::new(0.0, 0.0,  0.0),
      look          : Vector::new(0.0, 0.0, -1.0),
      up            : Vector::new(0.0, 1.0,  0.0),
    };

  let inv_min_scale = 1 << 5;
  let w = WINDOW_WIDTH / inv_min_scale;
  let h = WINDOW_HEIGHT / inv_min_scale;
  let max_scale = inv_min_scale << 1;

  let framebuffer_texture = {
    let w = w * max_scale;
    let h = h * max_scale;
    glium::texture::Texture2d::new(
      &window,
      glium::texture::RawImage2d {
        width  : w,
        height : h,
        format : glium::texture::ClientFormat::F32F32F32,
        data   : std::borrow::Cow::Owned(std::iter::repeat((0.0, 0.0, 0.0)).take((w*h) as usize).collect()),
      },
    ).unwrap()
  };

  let mut framebuffer = glium::framebuffer::SimpleFrameBuffer::new(&window, &framebuffer_texture).unwrap();

  let mut rng: rand::XorShiftRng = rand::SeedableRng::from_seed([0x12345678, 0x9abcdef0, 0x13371337, 0x98765432]);

  let mut stationary_frames_drawn = 0;
  loop {
    let scale = std::cmp::min(max_scale, 1 << stationary_frames_drawn);
    let w = w * scale;
    let h = h * scale;

    let before = time::precise_time_ns();
    let rendered = raytrace::scene(&scene, w, h, &mut rng);
    let after = time::precise_time_ns();
    println!("Render took {:?}ms", (after - before) as f32 / 1_000_000.0);

    let rendered =
      glium::texture::Texture2d::with_format(
        &window,
        glium::texture::RawImage2d {
          data: std::borrow::Cow::Owned(rendered.to_vec()),
          width: w,
          height: h,
          format: glium::texture::ClientFormat::F32F32F32,
        },
        glium::texture::UncompressedFloatFormat::F32F32F32,
        glium::texture::MipmapsOption::NoMipmap,
      )
      .unwrap();

    let draw_parameters =
      glium::DrawParameters {
        depth:
          glium::Depth {
            test: glium::DepthTest::Overwrite,
            write: false,
            .. Default::default()
          },
        blend:
          glium::Blend {
            color: glium::BlendingFunction::AlwaysReplace,
            alpha: glium::BlendingFunction::AlwaysReplace,
            constant_value: (0.0, 0.0, 0.0, 0.0),
          },
        .. Default::default()
      };

    let source =
      glium::uniforms::Sampler::new(&rendered)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::LinearMipmapLinear);

    draw(&window, source, &mut framebuffer, &draw_parameters);

    let source =
      glium::uniforms::Sampler::new(&framebuffer_texture)
      .magnify_filter(glium::uniforms::MagnifySamplerFilter::Linear)
      .minify_filter(glium::uniforms::MinifySamplerFilter::Linear);

    let mut target = window.draw();
    glium::Surface::clear(&mut target, None, Some((0.0, 0.0, 0.0, 1.0)), false, None, None);
    draw(&window, source, &mut target, &draw_parameters);
    target.finish().unwrap();

    stationary_frames_drawn += 1;

    for event in window.poll_events() {
      // because closures get belligerent about borrowing. Yes, really.
      // I don't make the rules, I just do what makes me hate myself the least.
      macro_rules! move_camera {
        ( $v:expr ) => {
          let v = $v;
          scene.move_camera(&v);
          stationary_frames_drawn = 0;
        };
      }

      match event {
        glutin::Event::Closed => return,
        glutin::Event::KeyboardInput(glium::glutin::ElementState::Pressed, _, Some(key)) => {
          match key {
            glutin::VirtualKeyCode::W => {
              move_camera!(scene.z());
            },
            glutin::VirtualKeyCode::S => {
              move_camera!(-scene.z());
            },
            glutin::VirtualKeyCode::D => {
              move_camera!(scene.x());
            },
            glutin::VirtualKeyCode::A => {
              move_camera!(-scene.x());
            },
            _ => {},
          }
        },
        _ => {},
      }
    }
  }
}

fn draw<'a, Dest: glium::Surface>(
  window: &glium::backend::glutin_backend::GlutinFacade,
  source: glium::uniforms::Sampler<'a, glium::Texture2d>,
  destination: &mut Dest,
  draw_parameters: &glium::DrawParameters,
) {
  // building the vertex buffer, which contains all the vertices that we will draw
  let vertex_buffer = {
    #[derive(Copy, Clone)]
    struct Vertex {
      position: [f32; 2],
      tex_coords: [f32; 2],
    }

    implement_vertex!(Vertex, position, tex_coords);

    glium::VertexBuffer::new(
      window,
      &[
      Vertex { position: [-1.0, -1.0], tex_coords: [0.0, 0.0] },
      Vertex { position: [-1.0,  1.0], tex_coords: [0.0, 1.0] },
      Vertex { position: [ 1.0,  1.0], tex_coords: [1.0, 1.0] },
      Vertex { position: [ 1.0, -1.0], tex_coords: [1.0, 0.0] }
      ]
    ).unwrap()
  };

  // building the index buffer
  let index_buffer =
    glium::IndexBuffer::new(
      window,
      glium::index::PrimitiveType::TriangleStrip,
      &[1 as u16, 2, 0, 3],
    ).unwrap();

  // compiling shaders and linking them together
  let program =
    program!(
      window,
      330 => {
        vertex: "
          #version 330

          uniform mat4 matrix;

          in vec2 position;
          in vec2 tex_coords;

          out vec2 v_tex_coords;

          void main() {
            gl_Position = matrix * vec4(position, 0.0, 1.0);
            v_tex_coords = tex_coords;
          }
        ",

        fragment: "
          #version 330
          uniform sampler2D tex;
          in vec2 v_tex_coords;
          out vec4 f_color;

          void main() {
            f_color = texture(tex, v_tex_coords);
          }
        "
      },
    ).unwrap();

  // building the uniforms
  let uniforms = uniform! {
    matrix: [
      [1.0, 0.0, 0.0, 0.0],
      [0.0, 1.0, 0.0, 0.0],
      [0.0, 0.0, 1.0, 0.0],
      [0.0, 0.0, 0.0, 1.0f32]
    ],
    tex: source,
  };

  destination.draw(
    &vertex_buffer,
    &index_buffer,
    &program,
    &uniforms,
    &draw_parameters,
  ).unwrap();
}
<|endoftext|>


<commit_before>use clap::{FromArgMatches, IntoApp};

use casile::cli::{Cli, Subcommand};
use casile::config::CONF;
use casile::{make, setup, status};
use casile::{Result, VERSION};

fn main() -> Result<()> {
    CONF.defaults()?;
    CONF.merge_env()?;
    CONF.merge_files()?;
    let app = Cli::into_app().version(VERSION);
    let matches = app.get_matches();
    let args = Cli::from_arg_matches(&matches);
    CONF.merge_args(&args)?;
    casile::show_welcome();
    let ret = match args.subcommand {
        Subcommand::Make { target } => make::run(target),
        Subcommand::Setup {} => setup::run(),
        Subcommand::Status {} => status::run(),
    };
    casile::show_outro();
    ret
}
<commit_msg>refactor(build): Update clap usage for new crate requirements<commit_after>use clap::{FromArgMatches, IntoApp};

use casile::cli::{Cli, Subcommand};
use casile::config::CONF;
use casile::{make, setup, status};
use casile::{Result, VERSION};

fn main() -> Result<()> {
    CONF.defaults()?;
    CONF.merge_env()?;
    CONF.merge_files()?;
    let app = Cli::into_app().version(VERSION);
    let matches = app.get_matches();
    let args = Cli::from_arg_matches(&matches).expect("Unable to parse arguments");
    CONF.merge_args(&args)?;
    casile::show_welcome();
    let ret = match args.subcommand {
        Subcommand::Make { target } => make::run(target),
        Subcommand::Setup {} => setup::run(),
        Subcommand::Status {} => status::run(),
    };
    casile::show_outro();
    ret
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate futures;
extern crate tokio_core;
extern crate clap;

use std::process::Child;
use std::thread::sleep;
use std::time::Duration;
use std::process::{Command, Stdio};
use futures::{Stream, Future};
use hyper::server::Http;

use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;
use clap::{App, Arg};

mod proxy;

const BASE_PORT: i32 = 60000;
const APP_NAME: &'static str = "boostphpserver";
const VERSION: &'static str = "0.1";

struct PHPSpawnOption {
    host: String,
    docroot: String,
    phpini: String,
}

fn spawn_php_server_process(opts: &PHPSpawnOption, n: usize, procs: &mut Vec<(Child, String)>) {
    for port_offset in 0..n {
        let port = BASE_PORT + port_offset as i32;
        let backend_addr = format!("{}:{}", opts.host, port);
        let ret = Command::new("php")
            .arg("-S").arg(backend_addr.clone())
            .arg("-t").arg(opts.docroot.as_str())
            .arg("-c").arg(opts.phpini.as_str())
            .stdout(Stdio::null())
            .spawn()
            .expect("php command not execution");
        procs.push((ret, backend_addr));
    }
}

fn main() {
    let app = App::new(APP_NAME)
        .version(VERSION)
        .arg(Arg::with_name("server")
             .short("S")
             .takes_value(true)
             .value_name("ADDR")
             .help("Run with web server"))
        .arg(Arg::with_name("procs")
             .short("n")
             .takes_value(true)
             .value_name("PROCS")
             .help("Spawn N php procs"))
        .arg(Arg::with_name("phpini")
             .short("c")
             .takes_value(true)
             .value_name("FILE_OR_DIR")
             .help("Specify php.ini file or in this directory"))
        .arg(Arg::with_name("docroot")
             .short("t")
             .takes_value(true)
             .value_name("DIR")
             .help("Specify document root <docroot>"));

    let matches = app.get_matches();

    // bind address
    let addr_str = match matches.value_of("server") {
        Some(v) => v,
        None => "127.0.0.1:8000",
    };

    // PHP docroot
    let docroot = match matches.value_of("docroot") {
        Some(v) => v,
        None => "./",
    };

    // php.ini path or directory
    let phpini = match matches.value_of("phpini") {
        Some(v) => v,
        None => "./",
    };

    // N procs
    let proc_num: usize = match matches.value_of("procs") {
        Some(v) => {
            match v.parse::<usize>() {
                Ok(i) => i,
                Err(_) => 1,
            }
        },
        None => 10,
    };

    let mut procs = vec![];
    let mut core = Core::new().unwrap();
    let http = Http::new();
    let handle = core.handle();
    let backend_client = hyper::Client::new(&handle);

    let addr = addr_str.parse().unwrap();
    let sock = TcpListener::bind(&addr, &handle)
        .expect(format!("bind error. addr={}", addr).as_str());
    let host = format!("{}", sock.local_addr().unwrap().ip());
    let port = sock.local_addr().unwrap().port();

    println!("Listening on {}:{}", host, port);

    let phpopts = PHPSpawnOption {
        host: host,
        phpini: phpini.to_string(),
        docroot: docroot.to_string(),
    };

    spawn_php_server_process(&phpopts, proc_num, &mut procs);

    let routes: Vec<String> = procs.iter().map(|p| p.1.clone()).collect();
    let server = sock.incoming().for_each(|(client, client_addr)| {
        let service = proxy::Proxy {
            routes: routes.clone(),
            client: backend_client.clone()
        };
        futures::future::ok(client_addr).and_then(|client_addr| {
            http.bind_connection(&handle, client, client_addr, service);
            Ok(())
        })
    });

    core.run(server).unwrap();

    loop {
        for p in procs.iter_mut() {
            match p.0.try_wait() {
                Ok(Some(status)) => {
                    println!("pid={}, exited with: {}", p.0.id(), status);
                },
                Ok(None) => {},
                Err(e) => println!("error occured: {}", e),
            }
        }
        sleep(Duration::from_millis(1_000));
    }
}
<commit_msg>fix app name and version string<commit_after>extern crate hyper;
extern crate futures;
extern crate tokio_core;
extern crate clap;

use std::process::Child;
use std::thread::sleep;
use std::time::Duration;
use std::process::{Command, Stdio};
use futures::{Stream, Future};
use hyper::server::Http;

use tokio_core::reactor::Core;
use tokio_core::net::TcpListener;
use clap::{App, Arg};

mod proxy;

const BASE_PORT: i32 = 60000;
const APP_NAME: &'static str = "kamasu";
const VERSION: &'static str = "0.1.1";

struct PHPSpawnOption {
    host: String,
    docroot: String,
    phpini: String,
}

fn spawn_php_server_process(opts: &PHPSpawnOption, n: usize, procs: &mut Vec<(Child, String)>) {
    for port_offset in 0..n {
        let port = BASE_PORT + port_offset as i32;
        let backend_addr = format!("{}:{}", opts.host, port);
        let ret = Command::new("php")
            .arg("-S").arg(backend_addr.clone())
            .arg("-t").arg(opts.docroot.as_str())
            .arg("-c").arg(opts.phpini.as_str())
            .stdout(Stdio::null())
            .spawn()
            .expect("php command not execution");
        procs.push((ret, backend_addr));
    }
}

fn main() {
    let app = App::new(APP_NAME)
        .version(VERSION)
        .arg(Arg::with_name("server")
             .short("S")
             .takes_value(true)
             .value_name("ADDR")
             .help("Run with web server"))
        .arg(Arg::with_name("procs")
             .short("n")
             .takes_value(true)
             .value_name("PROCS")
             .help("Spawn N php procs"))
        .arg(Arg::with_name("phpini")
             .short("c")
             .takes_value(true)
             .value_name("FILE_OR_DIR")
             .help("Specify php.ini file or in this directory"))
        .arg(Arg::with_name("docroot")
             .short("t")
             .takes_value(true)
             .value_name("DIR")
             .help("Specify document root <docroot>"));

    let matches = app.get_matches();

    // bind address
    let addr_str = match matches.value_of("server") {
        Some(v) => v,
        None => "127.0.0.1:8000",
    };

    // PHP docroot
    let docroot = match matches.value_of("docroot") {
        Some(v) => v,
        None => "./",
    };

    // php.ini path or directory
    let phpini = match matches.value_of("phpini") {
        Some(v) => v,
        None => "./",
    };

    // N procs
    let proc_num: usize = match matches.value_of("procs") {
        Some(v) => {
            match v.parse::<usize>() {
                Ok(i) => i,
                Err(_) => 1,
            }
        },
        None => 10,
    };

    let mut procs = vec![];
    let mut core = Core::new().unwrap();
    let http = Http::new();
    let handle = core.handle();
    let backend_client = hyper::Client::new(&handle);

    let addr = addr_str.parse().unwrap();
    let sock = TcpListener::bind(&addr, &handle)
        .expect(format!("bind error. addr={}", addr).as_str());
    let host = format!("{}", sock.local_addr().unwrap().ip());
    let port = sock.local_addr().unwrap().port();

    println!("Listening on {}:{}", host, port);

    let phpopts = PHPSpawnOption {
        host: host,
        phpini: phpini.to_string(),
        docroot: docroot.to_string(),
    };

    spawn_php_server_process(&phpopts, proc_num, &mut procs);

    let routes: Vec<String> = procs.iter().map(|p| p.1.clone()).collect();
    let server = sock.incoming().for_each(|(client, client_addr)| {
        let service = proxy::Proxy {
            routes: routes.clone(),
            client: backend_client.clone()
        };
        futures::future::ok(client_addr).and_then(|client_addr| {
            http.bind_connection(&handle, client, client_addr, service);
            Ok(())
        })
    });

    core.run(server).unwrap();

    loop {
        for p in procs.iter_mut() {
            match p.0.try_wait() {
                Ok(Some(status)) => {
                    println!("pid={}, exited with: {}", p.0.id(), status);
                },
                Ok(None) => {},
                Err(e) => println!("error occured: {}", e),
            }
        }
        sleep(Duration::from_millis(1_000));
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]

extern crate rand;

pub mod board;
mod zobrist;
mod fen;

fn main(){
    use board::chessboard;

    // init order is important
    zobrist::init();
    let mut main_board : chessboard = board::init();

    fen::parse("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", &mut main_board);
}
<commit_msg>added branding<commit_after>#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]

extern crate rand;

pub mod board;
mod zobrist;
mod fen;

fn main(){
    use board::chessboard;

    println!{"
                `-.  \\    .-'              ██████╗██╗ ██████╗ █████╗ ██████╗  █████╗
        ,-`````\"\"-\\__ |  /                ██╔════╝██║██╔════╝██╔══██╗██╔══██╗██╔══██╗
         '-.._    _.-'` '-o,              ██║     ██║██║     ███████║██║  ██║███████║
             _>--:{{<   ) |)               ██║     ██║██║     ██╔══██║██║  ██║██╔══██║
         .-''      '-.__.-o`              ╚██████╗██║╚██████╗██║  ██║██████╔╝██║  ██║
        '-._____..-/`  |  \\                ╚═════╝╚═╝ ╚═════╝╚═╝  ╚═╝╚═════╝ ╚═╝  ╚═╝
                ,-'   /    `-.                                     \"Numbers Matter\""};

    // init order is important
    println!("\n Startup Sequence:");

    println!(" [i] Initializing Zobrist Hash Tables");
    zobrist::init();

    println!(" [i] Initializing Chessboard");
    let mut main_board : chessboard = board::init();

    fen::parse("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", &mut main_board);
}
<|endoftext|>


<commit_before>extern crate crossterm;
#[macro_use]
extern crate downcast;
extern crate git_version;
extern crate indexmap;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate nix;
#[macro_use]
extern crate prolog_parser;
#[macro_use]
extern crate ref_thread_local;

use git_version::git_version;
use nix::sys::signal;

mod prolog;

use crate::prolog::machine::*;
use crate::prolog::machine::streams::*;
use crate::prolog::read::*;

use std::env;
use std::sync::atomic::Ordering;

extern fn handle_sigint(signal: libc::c_int) {
    let signal = signal::Signal::from_c_int(signal).unwrap();
    if signal == signal::Signal::SIGINT {
	INTERRUPT.store(true, Ordering::Relaxed);
    }
}

fn main() {
    let handler = signal::SigHandler::Handler(handle_sigint);
    unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap();

    if env::args().any(|a| a == "-v" || a == "--version") {
        println!("{:}", git_version!());
        return;
    }

    let mut wam = Machine::new(readline::input_stream(), Stream::stdout());
    wam.run_top_level();
}
<commit_msg>main: skip args[0]<commit_after>extern crate crossterm;
#[macro_use]
extern crate downcast;
extern crate git_version;
extern crate indexmap;
#[macro_use]
extern crate lazy_static;
extern crate libc;
extern crate nix;
#[macro_use]
extern crate prolog_parser;
#[macro_use]
extern crate ref_thread_local;

use git_version::git_version;
use nix::sys::signal;

mod prolog;

use crate::prolog::machine::*;
use crate::prolog::machine::streams::*;
use crate::prolog::read::*;

use std::env;
use std::sync::atomic::Ordering;

extern fn handle_sigint(signal: libc::c_int) {
    let signal = signal::Signal::from_c_int(signal).unwrap();
    if signal == signal::Signal::SIGINT {
	INTERRUPT.store(true, Ordering::Relaxed);
    }
}

fn main() {
    let handler = signal::SigHandler::Handler(handle_sigint);
    unsafe { signal::signal(signal::Signal::SIGINT, handler) }.unwrap();

    if env::args().skip(1).any(|a| a == "-v" || a == "--version") {
        println!("{:}", git_version!());
        return;
    }

    let mut wam = Machine::new(readline::input_stream(), Stream::stdout());
    wam.run_top_level();
}
<|endoftext|>


<commit_before>extern crate lz4;

use std::env;
use std::fs::File;
use std::io;
use std::io::Result;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use lz4::Encoder;

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

    let mut width: u32 = 0;
    let mut height: u32 = 0;
    let mut frame: u32 = 0;
    let mut out_file: &str = "";

    let mut index: usize = 0;
    for argument in args {
        let arg: &str = &argument;
        let args_len: usize = *(&args.len());

        match arg {
            "-w" => {
                if index < (args_len - 1) {
                    width = args[index + 1].parse::<u32>().unwrap();;
                }
            }
            "-h" => {
                if index < (args_len - 1) {
                    height = args[index + 1].parse::<u32>().unwrap();;
                }
            }
            "-frame" => {
                if index < (args_len - 1) {
                    frame = args[index + 1].parse::<u32>().unwrap();
                }
            }
            "-o" => {
                if index < (args_len - 1) {
                    out_file = &args[index + 1];
                }
            }
            _ => {}
        }
        index += 1;
    }

    if width == 0 || height == 0 || frame == 0 || out_file == "" {
        println!("Usage of : splityv12pipe -w <width> -h <height> -frame <number> -o <filename>");
        return;
    }

    let max_bytes_len: usize = (frame * (width * height + width * height / 2)) as usize;
    compress(out_file.to_string(), max_bytes_len).unwrap();
}

fn compress(dst: String, maxlen: usize) -> Result<()> {
    let count: i32 = 0;
    let file_name: String = format!("{}_{}", dst, count.to_string());
    let path: &Path = Path::new(&file_name);

    let mut fi = io::stdin();
    let mut fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));

    copy(&mut fi,
         &mut fo,
         &dst,
         maxlen,
         count + 1,
         &move || {
             println!("{}", path.display());
             return Ok(());
         })
        .unwrap();
    fo.finish();

    Ok(())
}

fn copy(fi: &mut Read,
        fo: &mut Encoder<std::fs::File>,
        dst: &str,
        maxlen: usize,
        count: i32,
        done: &Fn() -> Result<()>)
        -> Result<()> {
    let mut buffer: [u8; 1024] = [0; 1024];
    let mut write_len: usize = 0;

    loop {
        let len = try!(fi.read(&mut buffer));
        if len == 0 {
            done().unwrap();
            break;
        }
        if write_len + len >= maxlen {
            let mut l = 0;
            if (write_len + len) - maxlen > 0 {
                l = maxlen - write_len;
                try!(fo.write_all(&buffer[0..l]));
            }
            done().unwrap();

            let file_name: &str = &format!("{}_{}", dst, count.to_string());
            let path = Path::new(file_name);
            let mut new_fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));
            try!(new_fo.write_all(&buffer[l..len]));

            copy(fi,
                 &mut new_fo,
                 dst,
                 maxlen,
                 count + 1,
                 &move || {
                     println!("{}", path.display());
                     return Ok(());
                 })
                .unwrap();

            new_fo.finish();

            break;
        }
        try!(fo.write_all(&buffer[0..len]));
        write_len += len;
    }
    Ok(())
}
<commit_msg>fix length overflow<commit_after>extern crate lz4;

use std::env;
use std::fs::File;
use std::io;
use std::io::Result;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use lz4::Encoder;

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

    let mut width: u64 = 0;
    let mut height: u64 = 0;
    let mut frame: u64 = 0;
    let mut out_file: &str = "";

    let mut index: usize = 0;
    for argument in args {
        let arg: &str = &argument;
        let args_len: usize = *(&args.len());

        match arg {
            "-w" => {
                if index < (args_len - 1) {
                    width = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-h" => {
                if index < (args_len - 1) {
                    height = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-frame" => {
                if index < (args_len - 1) {
                    frame = args[index + 1].parse::<u32>().unwrap() as u64;
                }
            }
            "-o" => {
                if index < (args_len - 1) {
                    out_file = &args[index + 1];
                }
            }
            _ => {}
        }
        index += 1;
    }

    if width == 0 || height == 0 || frame == 0 || out_file == "" {
        println!("Usage of : splityv12pipe -w <width> -h <height> -frame <number> -o <filename>");
        return;
    }

    let max_bytes_len: u64 = frame * (((width * height) + ((width * height) / 2)));
    compress(out_file.to_string(), max_bytes_len).unwrap();
}

fn compress(dst: String, maxlen: u64) -> Result<()> {
    let count: i32 = 0;
    let file_name: String = format!("{}_{}", dst, count.to_string());
    let path: &Path = Path::new(&file_name);

    let mut fi = io::stdin();
    let mut fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));

    copy(&mut fi,
         &mut fo,
         &dst,
         maxlen,
         count + 1,
         &move || {
             println!("{}", path.display());
             return Ok(());
         })
        .unwrap();
    fo.finish();

    Ok(())
}

fn copy(fi: &mut Read,
        fo: &mut Encoder<std::fs::File>,
        dst: &str,
        maxlen: u64,
        count: i32,
        done: &Fn() -> Result<()>)
        -> Result<()> {
    let mut buffer: [u8; 1024] = [0; 1024];
    let mut write_len: u64 = 0;

    loop {
        let len = try!(fi.read(&mut buffer));
        let len_u64 = len as u64;
        if len == 0 {
            done().unwrap();
            break;
        }

        if write_len + len_u64 >= maxlen {
            let mut l = 0;
            if (write_len + len_u64) - maxlen > 0 {
                l = (maxlen - write_len) as usize;
                try!(fo.write_all(&buffer[0..l]));
            }
            done().unwrap();

            let file_name: &str = &format!("{}_{}", dst, count.to_string());
            let path = Path::new(file_name);
            let mut new_fo = try!(lz4::EncoderBuilder::new().build(try!(File::create(path))));
            try!(new_fo.write_all(&buffer[l..len]));

            copy(fi,
                 &mut new_fo,
                 dst,
                 maxlen,
                 count + 1,
                 &move || {
                     println!("{}", path.display());
                     return Ok(());
                 })
                .unwrap();

            new_fo.finish();

            break;
        }
        try!(fo.write_all(&buffer[0..len]));
        write_len += len_u64;
    }
    Ok(())
}
<|endoftext|>