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

use std;
use rustc_front::hir::*;
use syntax::ast::Lit_::*;
use syntax::ast::{FloatTy, Name};
use rustc_front::util::{binop_to_string, unop_to_string};
use std::collections::HashMap;
use std::collections::hash_map::Entry;

pub enum LispExpr {
    Binary(BinOp_, Box<LispExpr>, Box<LispExpr>),
    Fun(String, Vec<LispExpr>),
    Ident(u64),
    Lit(f64),
    Unary(UnOp, Box<LispExpr>),
}

#[derive(Debug)]
pub enum LispExprError {
    UnknownType,
    UnknownKind,
    WrongFloat,
}

impl std::fmt::Debug for LispExpr {

    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        f.pad(&self.to_lisp())
    }

}

/// List (herbie_name, rust_name).
/// Warning: *MUST* be alphabetized on Herbie name.
/// Herbie also supports the following:
///   * cot (cotangent),
///   * expt (expi, expf),
///   * mod
///   * sqt (square),
const KNOW_FUNS : &'static [(&'static str, &'static str, usize)] = &[
    ("abs",   "abs",    1),
    ("acos",  "acos",   1),
    ("asin",  "asin",   1),
    ("atan",  "atan",   1),
    ("atan2", "atan2",  2),
    ("cos",   "cos",    1),
    ("cosh",  "cosh",   1),
    ("exp",   "exp",    1),
    ("expm1", "exp_m1", 1),
    ("hypot", "hypot",  2),
    ("log",   "ln",     1),
    ("log1p", "ln_1p",  1),
    ("sin",   "sin",    1),
    ("sinh",  "sinh",   1),
    ("sqrt",  "sqrt",   1),
    ("tan",   "tan",    1),
    ("tanh",  "tanh",   1),
];

impl LispExpr {

    pub fn is_form_of(&self, other: &LispExpr) -> bool {
        #[derive(PartialEq)]
        enum Binded {
            Ident(u64),
            Lit(f64),
        }

        fn is_form_of_impl(lhs: &LispExpr, rhs: &LispExpr, ids: &mut HashMap<u64, Binded>) -> bool {
            match (lhs, rhs) {
                (&LispExpr::Binary(lop, ref lp1, ref lp2), &LispExpr::Binary(rop, ref rp1, ref rp2)) => {
                    lop == rop && is_form_of_impl(lp1, rp1, ids) && is_form_of_impl(lp2, rp2, ids)
                },
                (&LispExpr::Fun(ref lfun, ref lp), &LispExpr::Fun(ref rfun, ref rp)) => {
                    lfun == rfun && lp.len() == rp.len() && lp.iter().zip(rp).all(|(lp, rp)| is_form_of_impl(lp, rp, ids))
                },
                (&LispExpr::Ident(lid), &LispExpr::Ident(rid)) => {
                    match ids.entry(rid) {
                        Entry::Occupied(entry) => {
                            if let Binded::Ident(binded) = *entry.get() {
                                binded == lid
                            }
                            else {
                                false
                            }
                        },
                        Entry::Vacant(vacant) => {
                            vacant.insert(Binded::Ident(lid));
                            true
                        }
                    }
                },
                (&LispExpr::Lit(l), &LispExpr::Lit(r)) => {
                    l == r
                },
                (&LispExpr::Lit(l), &LispExpr::Ident(rid)) => {
                    match ids.entry(rid) {
                        Entry::Occupied(entry) => {
                            if let Binded::Lit(binded) = *entry.get() {
                                binded == l
                            }
                            else {
                                false
                            }
                        },
                        Entry::Vacant(vacant) => {
                            vacant.insert(Binded::Lit(l));
                            true
                        }
                    }
                },
                (&LispExpr::Unary(lop, ref lp), &LispExpr::Unary(rop, ref rp)) => {
                    lop == rop && is_form_of_impl(lp, rp, ids)
                },
                _ => false,
            }
        }

        let mut ids = HashMap::new();
        is_form_of_impl(self, other, &mut ids)
    }

    pub fn from_expr(expr: &Expr) -> Result<LispExpr, LispExprError> {
        #[derive(PartialEq, Eq, Hash)]
        enum Binded {
            Field(Option<QSelf>, bool, HirVec<PathSegment>, Name),
            Path(Option<QSelf>, bool, HirVec<PathSegment>),
            TupField(Option<QSelf>, bool, HirVec<PathSegment>, usize),
        }

        fn from_expr_impl(expr: &Expr, curr_id: &mut u64, ids: &mut HashMap<Binded, u64>) -> Result<LispExpr, LispExprError> {
            let unknown = |curr_id: &mut u64| {
                let id = *curr_id;
                *curr_id += 1;
                Ok(LispExpr::Ident(id))
            };

            match expr.node {
                ExprBinary(op, ref lhs, ref rhs) => {
                    Ok(LispExpr::Binary(op.node, box try!(from_expr_impl(lhs, curr_id, ids)), box try!(from_expr_impl(rhs, curr_id, ids))))
                },
                ExprLit(ref lit) => {
                    match lit.node {
                        LitFloat(ref f, FloatTy::TyF64) => LispExpr::from_lit_float(&f),
                        LitFloatUnsuffixed(ref f) => LispExpr::from_lit_float(&f),
                        _ => Err(LispExprError::UnknownType)
                    }
                },
                ExprUnary(op, ref expr) => {
                    Ok(LispExpr::Unary(op, box try!(from_expr_impl(&expr, curr_id, ids))))
                },
                ExprPath(ref qualif, ref path) => {
                    match ids.entry(Binded::Path(qualif.clone(), path.global, path.segments.clone())) {
                        Entry::Occupied(entry) => {
                            Ok(LispExpr::Ident(*entry.get()))
                        },
                        Entry::Vacant(vacant) => {
                            let id = *curr_id;
                            *curr_id += 1;
                            vacant.insert(id);
                            Ok(LispExpr::Ident(id))
                        }
                    }
                },
                ExprCall(..) | ExprCast(..) | ExprBlock(..) => {
                    unknown(curr_id)
                },
                ExprMethodCall(ref name, ref ascripted_type, ref params) => {
                    if ascripted_type.is_empty() {
                        let name = name.node.as_str();

                        if let Some(&(herbie_name, _, _)) = KNOW_FUNS.iter().find(
                            |&&(_, rust_name, num_params)| {
                                rust_name == name && params.len() == num_params
                            }
                        ) {
                            let mut conv_params = vec![];
                            for p in params {
                                let p = from_expr_impl(p, curr_id, ids);
                                if let Ok(p) = p {
                                    conv_params.push(p);
                                }
                                else {
                                    return p;
                                }
                            }
                            return Ok(LispExpr::Fun(herbie_name.into(), conv_params))
                        }
                    }

                    unknown(curr_id)
                },
                ExprTupField(ref tup, idx) => {
                    if let ExprPath(ref qualif, ref path) = tup.node {
                        return match ids.entry(Binded::TupField(qualif.clone(), path.global, path.segments.clone(), idx.node)) {
                            Entry::Occupied(entry) => {
                                Ok(LispExpr::Ident(*entry.get()))
                            },
                            Entry::Vacant(vacant) => {
                                let id = *curr_id;
                                *curr_id += 1;
                                vacant.insert(id);
                                Ok(LispExpr::Ident(id))
                            }
                        }
                    }

                    unknown(curr_id)
                },
                ExprField(ref expr, ref name) => {
                    if let ExprPath(ref qualif, ref path) = expr.node {
                        return match ids.entry(Binded::Field(qualif.clone(), path.global, path.segments.clone(), name.node)) {
                            Entry::Occupied(entry) => {
                                Ok(LispExpr::Ident(*entry.get()))
                            },
                            Entry::Vacant(vacant) => {
                                let id = *curr_id;
                                *curr_id += 1;
                                vacant.insert(id);
                                Ok(LispExpr::Ident(id))
                            }
                        }
                    }

                    unknown(curr_id)
                },
                // TODO:
                // ExprAssignOp,
                // ExprIndex,
                _ => Err(LispExprError::UnknownKind)
            }
        }

        let mut ids = HashMap::new();
        from_expr_impl(expr, &mut 0, &mut ids)
    }

    fn from_lit_float(f: &str) -> Result<LispExpr, LispExprError> {
        if let Ok(f) = f.parse() {
            Ok(LispExpr::Lit(f))
        }
        else {
            Err(LispExprError::WrongFloat)
        }
    }

    // TODO: should probably not be pub
    pub fn to_lisp(&self) -> String {
        match *self {
            LispExpr::Binary(op, ref lhs, ref rhs) => {
                format!("({} {} {})", binop_to_string(op), lhs.to_lisp(), rhs.to_lisp())
            },
            LispExpr::Fun(ref name, ref params) => {
                let mut buf = String::new();
                buf.push('(');
                buf.push_str(name);

                for p in params {
                    buf.push(' ');
                    buf.push_str(&p.to_lisp());
                }

                buf.push(')');
                buf
            }
            LispExpr::Lit(f) => {
                format!("{}", f)
            },
            LispExpr::Unary(op, ref expr) => {
                format!("({} {})", unop_to_string(op), expr.to_lisp())
            },
            LispExpr::Ident(id) => {
                format!("${}", id)
            }
        }
    }

}

#[derive(Debug)]
pub enum ParseError {
    Arity,
    Expected(char),
    Ident,
    Float,
    Unexpected(char),
    EOE,
}

struct Parser {
    stack: Vec<char>,
}

pub fn parse(s: &str) -> Result<LispExpr, ParseError> {
    let mut parser = Parser { stack: Vec::new() };
    let mut it = s.chars();

    match parser.parse_impl(&mut it) {
        Ok(result) => {
            if it.next().is_some() {
                Err(ParseError::EOE)
            }
            else  {
                Ok(result)
            }
        },
        err @ Err(..) => err,
    }
}

impl Parser {

    fn parse_impl<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        match self.get_char(it, true) {
            Some('(') => {
                match self.get_char(it, true) {
                    Some('+') => self.parse_op(it, BinOp_::BiAdd),
                    Some('-') => self.parse_op(it, BinOp_::BiSub),
                    Some('*') => self.parse_op(it, BinOp_::BiMul),
                    Some('/') => self.parse_op(it, BinOp_::BiDiv),
                    Some(c) if c.is_digit(10) => {
                        self.put_back(c);
                        let r = self.parse_float(it);
                        try!(self.expect(it, ')', true));
                        r
                    },
                    Some(c) => {
                        self.put_back(c);
                        self.parse_fun(it)
                    },
                    None => Err(ParseError::EOE),
                }
            },
            Some(c) if c.is_digit(10) => {
                self.put_back(c);
                self.parse_float(it)
            },
            Some('h') => self.parse_ident(it),
            Some(c) => {
                self.put_back(c);
                Err(ParseError::Unexpected(c))
            }
            None => Err(ParseError::EOE),
        }
    }

    fn expect<It: Iterator<Item=char>>(&mut self, it: &mut It, c: char, skip_whitespace: bool) -> Result<(), ParseError> {
        if self.get_char(it, skip_whitespace) == Some(c) {
            Ok(())
        }
        else {
            Err(ParseError::Expected(c))
        }
    }

    fn parse_float<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        let mut buf = String::new();
        loop {
            let c = self.get_char(it, false);
            if let Some(c) = c {
                if c.is_digit(10) || ['.', 'e', '+', '-'].contains(&c) {
                    buf.push(c);
                    continue;
                }

                self.put_back(c);
            }

            break;
        }

        match buf.parse() {
            Ok(f) => Ok(LispExpr::Lit(f)),
            Err(..) => Err(ParseError::Float),
        }
    }

    fn parse_ident<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        // TODO: Herbie also supports ‘pi’ and ‘e’ as native constants.
        let mut buf = String::new();
        loop {
            let c = self.get_char(it, false);
            if let Some(c) = c {
                if buf.is_empty() && 'a' <= c && c <= 'z' {
                    continue;
                }
                else if c.is_digit(10)  {
                    buf.push(c);
                    continue;
                }
                else {
                    self.put_back(c);
                }
            }

            break;
        }

        match buf.parse() {
            Ok(id) => Ok(LispExpr::Ident(id)),
            Err(..) => Err(ParseError::Ident),
        }
    }

    fn parse_fun<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        let mut buf = String::new();
        loop {
            let c = self.get_char(it, false);
            if let Some(c) = c {
                if 'a' <= c && c <= 'z' {
                    buf.push(c);
                    continue;
                }
                else {
                    self.put_back(c);
                }
            }

            break;
        }

        if !buf.is_empty() {
            let mut params = vec![];

            while let Ok(param) = self.parse_impl(it) {
                params.push(param);
            }

            try!(self.expect(it, ')', true));
            Ok(LispExpr::Fun(buf, params))
        }
        else {
            Err(ParseError::Ident)
        }
    }

    fn parse_op<It: Iterator<Item=char>>(&mut self, it: &mut It, op: BinOp_) -> Result<LispExpr, ParseError> {
        // TODO: Herbie seems to also support the following for the repip of a float: (/ 42) and
        // rust has a function recip for that
        let lhs = try!(self.parse_impl(it));
        let r = if let Ok(rhs) = self.parse_impl(it) {
            Ok(LispExpr::Binary(op, box lhs, box rhs))
        }
        else if op == BinOp_::BiSub {
            Ok(LispExpr::Unary(UnOp::UnNeg, box lhs))
        }
        else {
            return Err(ParseError::Arity);
        };
        try!(self.expect(it, ')', true));
        r
    }

    fn get_char<It: Iterator<Item=char>>(&mut self, it: &mut It, skip_whitespace: bool) -> Option<char> {
        loop {
            match self.stack.pop() {
                Some(e) if skip_whitespace && e.is_whitespace() => continue,
                Some(e) => return Some(e),
                None => break,
            }
        }

        loop {
            match it.next() {
                Some(e) if skip_whitespace && e.is_whitespace() => continue,
                Some(e) => return Some(e),
                None => return None,
            }
        }
    }

    fn put_back(&mut self, c: char) {
        self.stack.push(c);
    }
}
<commit_msg>Remove useless case in lisp parser<commit_after>#![cfg_attr(feature="clippy", allow(float_cmp))]

use std;
use rustc_front::hir::*;
use syntax::ast::Lit_::*;
use syntax::ast::{FloatTy, Name};
use rustc_front::util::{binop_to_string, unop_to_string};
use std::collections::HashMap;
use std::collections::hash_map::Entry;

pub enum LispExpr {
    Binary(BinOp_, Box<LispExpr>, Box<LispExpr>),
    Fun(String, Vec<LispExpr>),
    Ident(u64),
    Lit(f64),
    Unary(UnOp, Box<LispExpr>),
}

#[derive(Debug)]
pub enum LispExprError {
    UnknownType,
    UnknownKind,
    WrongFloat,
}

impl std::fmt::Debug for LispExpr {

    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        f.pad(&self.to_lisp())
    }

}

/// List (herbie_name, rust_name).
/// Warning: *MUST* be alphabetized on Herbie name.
/// Herbie also supports the following:
///   * cot (cotangent),
///   * expt (expi, expf),
///   * mod
///   * sqt (square),
const KNOW_FUNS : &'static [(&'static str, &'static str, usize)] = &[
    ("abs",   "abs",    1),
    ("acos",  "acos",   1),
    ("asin",  "asin",   1),
    ("atan",  "atan",   1),
    ("atan2", "atan2",  2),
    ("cos",   "cos",    1),
    ("cosh",  "cosh",   1),
    ("exp",   "exp",    1),
    ("expm1", "exp_m1", 1),
    ("hypot", "hypot",  2),
    ("log",   "ln",     1),
    ("log1p", "ln_1p",  1),
    ("sin",   "sin",    1),
    ("sinh",  "sinh",   1),
    ("sqrt",  "sqrt",   1),
    ("tan",   "tan",    1),
    ("tanh",  "tanh",   1),
];

impl LispExpr {

    pub fn is_form_of(&self, other: &LispExpr) -> bool {
        #[derive(PartialEq)]
        enum Binded {
            Ident(u64),
            Lit(f64),
        }

        fn is_form_of_impl(lhs: &LispExpr, rhs: &LispExpr, ids: &mut HashMap<u64, Binded>) -> bool {
            match (lhs, rhs) {
                (&LispExpr::Binary(lop, ref lp1, ref lp2), &LispExpr::Binary(rop, ref rp1, ref rp2)) => {
                    lop == rop && is_form_of_impl(lp1, rp1, ids) && is_form_of_impl(lp2, rp2, ids)
                },
                (&LispExpr::Fun(ref lfun, ref lp), &LispExpr::Fun(ref rfun, ref rp)) => {
                    lfun == rfun && lp.len() == rp.len() && lp.iter().zip(rp).all(|(lp, rp)| is_form_of_impl(lp, rp, ids))
                },
                (&LispExpr::Ident(lid), &LispExpr::Ident(rid)) => {
                    match ids.entry(rid) {
                        Entry::Occupied(entry) => {
                            if let Binded::Ident(binded) = *entry.get() {
                                binded == lid
                            }
                            else {
                                false
                            }
                        },
                        Entry::Vacant(vacant) => {
                            vacant.insert(Binded::Ident(lid));
                            true
                        }
                    }
                },
                (&LispExpr::Lit(l), &LispExpr::Lit(r)) => {
                    l == r
                },
                (&LispExpr::Lit(l), &LispExpr::Ident(rid)) => {
                    match ids.entry(rid) {
                        Entry::Occupied(entry) => {
                            if let Binded::Lit(binded) = *entry.get() {
                                binded == l
                            }
                            else {
                                false
                            }
                        },
                        Entry::Vacant(vacant) => {
                            vacant.insert(Binded::Lit(l));
                            true
                        }
                    }
                },
                (&LispExpr::Unary(lop, ref lp), &LispExpr::Unary(rop, ref rp)) => {
                    lop == rop && is_form_of_impl(lp, rp, ids)
                },
                _ => false,
            }
        }

        let mut ids = HashMap::new();
        is_form_of_impl(self, other, &mut ids)
    }

    pub fn from_expr(expr: &Expr) -> Result<LispExpr, LispExprError> {
        #[derive(PartialEq, Eq, Hash)]
        enum Binded {
            Field(Option<QSelf>, bool, HirVec<PathSegment>, Name),
            Path(Option<QSelf>, bool, HirVec<PathSegment>),
            TupField(Option<QSelf>, bool, HirVec<PathSegment>, usize),
        }

        fn from_expr_impl(expr: &Expr, curr_id: &mut u64, ids: &mut HashMap<Binded, u64>) -> Result<LispExpr, LispExprError> {
            let unknown = |curr_id: &mut u64| {
                let id = *curr_id;
                *curr_id += 1;
                Ok(LispExpr::Ident(id))
            };

            match expr.node {
                ExprBinary(op, ref lhs, ref rhs) => {
                    Ok(LispExpr::Binary(op.node, box try!(from_expr_impl(lhs, curr_id, ids)), box try!(from_expr_impl(rhs, curr_id, ids))))
                },
                ExprLit(ref lit) => {
                    match lit.node {
                        LitFloat(ref f, FloatTy::TyF64) => LispExpr::from_lit_float(&f),
                        LitFloatUnsuffixed(ref f) => LispExpr::from_lit_float(&f),
                        _ => Err(LispExprError::UnknownType)
                    }
                },
                ExprUnary(op, ref expr) => {
                    Ok(LispExpr::Unary(op, box try!(from_expr_impl(&expr, curr_id, ids))))
                },
                ExprPath(ref qualif, ref path) => {
                    match ids.entry(Binded::Path(qualif.clone(), path.global, path.segments.clone())) {
                        Entry::Occupied(entry) => {
                            Ok(LispExpr::Ident(*entry.get()))
                        },
                        Entry::Vacant(vacant) => {
                            let id = *curr_id;
                            *curr_id += 1;
                            vacant.insert(id);
                            Ok(LispExpr::Ident(id))
                        }
                    }
                },
                ExprCall(..) | ExprCast(..) | ExprBlock(..) => {
                    unknown(curr_id)
                },
                ExprMethodCall(ref name, ref ascripted_type, ref params) => {
                    if ascripted_type.is_empty() {
                        let name = name.node.as_str();

                        if let Some(&(herbie_name, _, _)) = KNOW_FUNS.iter().find(
                            |&&(_, rust_name, num_params)| {
                                rust_name == name && params.len() == num_params
                            }
                        ) {
                            let mut conv_params = vec![];
                            for p in params {
                                let p = from_expr_impl(p, curr_id, ids);
                                if let Ok(p) = p {
                                    conv_params.push(p);
                                }
                                else {
                                    return p;
                                }
                            }
                            return Ok(LispExpr::Fun(herbie_name.into(), conv_params))
                        }
                    }

                    unknown(curr_id)
                },
                ExprTupField(ref tup, idx) => {
                    if let ExprPath(ref qualif, ref path) = tup.node {
                        return match ids.entry(Binded::TupField(qualif.clone(), path.global, path.segments.clone(), idx.node)) {
                            Entry::Occupied(entry) => {
                                Ok(LispExpr::Ident(*entry.get()))
                            },
                            Entry::Vacant(vacant) => {
                                let id = *curr_id;
                                *curr_id += 1;
                                vacant.insert(id);
                                Ok(LispExpr::Ident(id))
                            }
                        }
                    }

                    unknown(curr_id)
                },
                ExprField(ref expr, ref name) => {
                    if let ExprPath(ref qualif, ref path) = expr.node {
                        return match ids.entry(Binded::Field(qualif.clone(), path.global, path.segments.clone(), name.node)) {
                            Entry::Occupied(entry) => {
                                Ok(LispExpr::Ident(*entry.get()))
                            },
                            Entry::Vacant(vacant) => {
                                let id = *curr_id;
                                *curr_id += 1;
                                vacant.insert(id);
                                Ok(LispExpr::Ident(id))
                            }
                        }
                    }

                    unknown(curr_id)
                },
                // TODO:
                // ExprAssignOp,
                // ExprIndex,
                _ => Err(LispExprError::UnknownKind)
            }
        }

        let mut ids = HashMap::new();
        from_expr_impl(expr, &mut 0, &mut ids)
    }

    fn from_lit_float(f: &str) -> Result<LispExpr, LispExprError> {
        if let Ok(f) = f.parse() {
            Ok(LispExpr::Lit(f))
        }
        else {
            Err(LispExprError::WrongFloat)
        }
    }

    // TODO: should probably not be pub
    pub fn to_lisp(&self) -> String {
        match *self {
            LispExpr::Binary(op, ref lhs, ref rhs) => {
                format!("({} {} {})", binop_to_string(op), lhs.to_lisp(), rhs.to_lisp())
            },
            LispExpr::Fun(ref name, ref params) => {
                let mut buf = String::new();
                buf.push('(');
                buf.push_str(name);

                for p in params {
                    buf.push(' ');
                    buf.push_str(&p.to_lisp());
                }

                buf.push(')');
                buf
            }
            LispExpr::Lit(f) => {
                format!("{}", f)
            },
            LispExpr::Unary(op, ref expr) => {
                format!("({} {})", unop_to_string(op), expr.to_lisp())
            },
            LispExpr::Ident(id) => {
                format!("${}", id)
            }
        }
    }

}

#[derive(Debug)]
pub enum ParseError {
    Arity,
    Expected(char),
    Ident,
    Float,
    Unexpected(char),
    EOE,
}

struct Parser {
    stack: Vec<char>,
}

pub fn parse(s: &str) -> Result<LispExpr, ParseError> {
    let mut parser = Parser { stack: Vec::new() };
    let mut it = s.chars();

    match parser.parse_impl(&mut it) {
        Ok(result) => {
            if it.next().is_some() {
                Err(ParseError::EOE)
            }
            else  {
                Ok(result)
            }
        },
        err @ Err(..) => err,
    }
}

impl Parser {

    fn parse_impl<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        match self.get_char(it, true) {
            Some('(') => {
                match self.get_char(it, true) {
                    Some('+') => self.parse_op(it, BinOp_::BiAdd),
                    Some('-') => self.parse_op(it, BinOp_::BiSub),
                    Some('*') => self.parse_op(it, BinOp_::BiMul),
                    Some('/') => self.parse_op(it, BinOp_::BiDiv),
                    Some(c) => {
                        self.put_back(c);
                        self.parse_fun(it)
                    },
                    None => Err(ParseError::EOE),
                }
            },
            Some(c) if c.is_digit(10) => {
                self.put_back(c);
                self.parse_float(it)
            },
            Some('h') => self.parse_ident(it),
            Some(c) => {
                self.put_back(c);
                Err(ParseError::Unexpected(c))
            }
            None => Err(ParseError::EOE),
        }
    }

    fn expect<It: Iterator<Item=char>>(&mut self, it: &mut It, c: char, skip_whitespace: bool) -> Result<(), ParseError> {
        if self.get_char(it, skip_whitespace) == Some(c) {
            Ok(())
        }
        else {
            Err(ParseError::Expected(c))
        }
    }

    fn parse_float<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        let mut buf = String::new();
        loop {
            let c = self.get_char(it, false);
            if let Some(c) = c {
                if c.is_digit(10) || ['.', 'e', '+', '-'].contains(&c) {
                    buf.push(c);
                    continue;
                }

                self.put_back(c);
            }

            break;
        }

        match buf.parse() {
            Ok(f) => Ok(LispExpr::Lit(f)),
            Err(..) => Err(ParseError::Float),
        }
    }

    fn parse_ident<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        // TODO: Herbie also supports ‘pi’ and ‘e’ as native constants.
        let mut buf = String::new();
        loop {
            let c = self.get_char(it, false);
            if let Some(c) = c {
                if buf.is_empty() && 'a' <= c && c <= 'z' {
                    continue;
                }
                else if c.is_digit(10)  {
                    buf.push(c);
                    continue;
                }
                else {
                    self.put_back(c);
                }
            }

            break;
        }

        match buf.parse() {
            Ok(id) => Ok(LispExpr::Ident(id)),
            Err(..) => Err(ParseError::Ident),
        }
    }

    fn parse_fun<It: Iterator<Item=char>>(&mut self, it: &mut It) -> Result<LispExpr, ParseError> {
        let mut buf = String::new();
        loop {
            let c = self.get_char(it, false);
            if let Some(c) = c {
                if 'a' <= c && c <= 'z' {
                    buf.push(c);
                    continue;
                }
                else {
                    self.put_back(c);
                }
            }

            break;
        }

        if !buf.is_empty() {
            let mut params = vec![];

            while let Ok(param) = self.parse_impl(it) {
                params.push(param);
            }

            try!(self.expect(it, ')', true));
            Ok(LispExpr::Fun(buf, params))
        }
        else {
            Err(ParseError::Ident)
        }
    }

    fn parse_op<It: Iterator<Item=char>>(&mut self, it: &mut It, op: BinOp_) -> Result<LispExpr, ParseError> {
        // TODO: Herbie seems to also support the following for the repip of a float: (/ 42) and
        // rust has a function recip for that
        let lhs = try!(self.parse_impl(it));
        let r = if let Ok(rhs) = self.parse_impl(it) {
            Ok(LispExpr::Binary(op, box lhs, box rhs))
        }
        else if op == BinOp_::BiSub {
            Ok(LispExpr::Unary(UnOp::UnNeg, box lhs))
        }
        else {
            return Err(ParseError::Arity);
        };
        try!(self.expect(it, ')', true));
        r
    }

    fn get_char<It: Iterator<Item=char>>(&mut self, it: &mut It, skip_whitespace: bool) -> Option<char> {
        loop {
            match self.stack.pop() {
                Some(e) if skip_whitespace && e.is_whitespace() => continue,
                Some(e) => return Some(e),
                None => break,
            }
        }

        loop {
            match it.next() {
                Some(e) if skip_whitespace && e.is_whitespace() => continue,
                Some(e) => return Some(e),
                None => return None,
            }
        }
    }

    fn put_back(&mut self, c: char) {
        self.stack.push(c);
    }
}
<|endoftext|>


<commit_before>// UDP stuff adapted from http://illegalargumentexception.blogspot.co.uk/2015/05/rust-send-and-receive-on-localhost-with.html
use std::net;
#[macro_use]
extern crate clap;
use clap::{Arg, App};

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
    let attempt = net::UdpSocket::bind(listen_on);
    let socket;
    match attempt {
        Ok(sock) => {
            socket = sock;
        }
        Err(err) => panic!("Could not bind: {}", err),
    }
    socket
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
    let socket = socket(send_addr);
    let _ = socket.send_to(&data, target);
    drop(socket);
}

fn convert(inp: String) -> String {
    // to_lowercase is still unstable.
    // This madness from IRC is the workaround
    // works though

    // Strings do not live for the entire life of your program
    // http://stackoverflow.com/a/23977218/416626
    let intermediate: &str = &*inp;
    let outp = intermediate.chars()
                           .flat_map(char::to_lowercase)
                           .collect::<String>();
    outp
}

fn main() {
    let command_vals = ["white", "red", "orange", "yellow", "green", "cyan", "blue", "purple",
                        "black", "?", "!", "quit"];
    let matches = App::new("rust_anybar")
                      .version(&crate_version!()[..])
                      .author("Stephan Hügel <urschrei@gmail.com>")
                      .about("A Rust command-line client for Anybar")
                      .args_from_usage("-p --port=[PORT] 'Set destination UDP port. Input must \
                                        be 0 – 65535")
                      .arg(Arg::with_name("COMMAND")
                               .help("The command you wish to send to Anybar")
                               .index(1)
                               .possible_values(&command_vals)
                               .required(true))
                      .get_matches();
    let port = matches.value_of("PORT").unwrap_or("1738");
    let to_send = convert(matches.value_of("COMMAND").unwrap().to_string());
    // // cast to int and ensure it worked
    let numeric_port = port.parse::<u16>();
    // blam our control message into a vector
    let mut message: Vec<u8> = Vec::new();
    message.extend(to_send.as_bytes()
                          .iter()
                          .cloned());
    // bind to the correct UDP port
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    // parse() gives us Result which we need to unwrap
    // it's safe to unwrap here, cos we already checked success
    let listen_addr = net::SocketAddrV4::new(ip, numeric_port.unwrap());
    let send_addr = net::SocketAddrV4::new(ip, 0);
    // and send our message
    send_message(net::SocketAddr::V4(send_addr),
                 net::SocketAddr::V4(listen_addr),
                 message);
}
<commit_msg>Simplify lowercase conversion<commit_after>// UDP stuff adapted from http://illegalargumentexception.blogspot.co.uk/2015/05/rust-send-and-receive-on-localhost-with.html
use std::net;
#[macro_use]
extern crate clap;
use clap::{Arg, App};

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
    let attempt = net::UdpSocket::bind(listen_on);
    let socket;
    match attempt {
        Ok(sock) => {
            socket = sock;
        }
        Err(err) => panic!("Could not bind: {}", err),
    }
    socket
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
    let socket = socket(send_addr);
    let _ = socket.send_to(&data, target);
    drop(socket);
}

fn convert(inp: String) -> String {
        let outp = inp.to_lowercase();
    outp
}

fn main() {
    let command_vals = ["white", "red", "orange", "yellow", "green", "cyan", "blue", "purple",
                        "black", "?", "!", "quit"];
    let matches = App::new("rust_anybar")
                      .version(&crate_version!()[..])
                      .author("Stephan Hügel <urschrei@gmail.com>")
                      .about("A Rust command-line client for Anybar")
                      .args_from_usage("-p --port=[PORT] 'Set destination UDP port. Input must \
                                        be 0 – 65535")
                      .arg(Arg::with_name("COMMAND")
                               .help("The command you wish to send to Anybar")
                               .index(1)
                               .possible_values(&command_vals)
                               .required(true))
                      .get_matches();
    let port = matches.value_of("PORT").unwrap_or("1738");
    let to_send = convert(matches.value_of("COMMAND").unwrap().to_string());
    // // cast to int and ensure it worked
    let numeric_port = port.parse::<u16>();
    // blam our control message into a vector
    let mut message: Vec<u8> = Vec::new();
    message.extend(to_send.as_bytes()
                          .iter()
                          .cloned());
    // bind to the correct UDP port
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    // parse() gives us Result which we need to unwrap
    // it's safe to unwrap here, cos we already checked success
    let listen_addr = net::SocketAddrV4::new(ip, numeric_port.unwrap());
    let send_addr = net::SocketAddrV4::new(ip, 0);
    // and send our message
    send_message(net::SocketAddr::V4(send_addr),
                 net::SocketAddr::V4(listen_addr),
                 message);
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate docopt;
#[macro_use]
extern crate lust;

use std::io::{self, Write, Read};
use std::path::Path;
use std::fs::{File, metadata};
use docopt::Docopt;
use lust::Parser;
use lust::State;

macro_rules! try_ok {
    ($e:expr) => (match $e {
        Ok(res) => {
            res
        },
        Err(err) => {
            return println!("Whoops, error detected.\n{}.\n\
                             Please, try again...", err)
        }
    })
}

static USAGE: &'static str = "
Usage:
    lust [options] [<expr>]

Options:
    -f <file_path>, --file <file_path>          Evaluate expresions from file
    -i, --interactive                           Run REPL session
";

#[derive(RustcDecodable, Debug)]
struct CliArgs {
    arg_expr: Option<String>,
    flag_file: Option<String>,
    flag_interactive: bool,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    let args = try_ok!(Docopt::new(USAGE).and_then(|d| d.decode::<CliArgs>()));
    let ref mut state = State::new("user".to_string());
    let mut last_evaled = None;

    if let Some(ref flag_file) = args.flag_file {
        let path = Path::new(flag_file);
        let md = metadata(path);
        if is_file_exists!(md) {
            if is_file!(md) {
                let mut file = try_ok!(File::open(&path));
                let ref mut buf = String::new();
                try_ok!(file.read_to_string(buf));
                for parsed_expr in Parser::new(buf.chars()) {
                    last_evaled = Some(try_ok!(state.eval(&try_ok!(parsed_expr))));
                }
            } else {
                return println!("Whoops, error detected.\n\
                                 Specified path is not a file.\n\
                                 Please, specify existing file.");
            }
        } else {
            return println!("Whoops, error detected.\n\
                             File doesn't exist.\n\
                             Please, specify existing file.");
        }
    }

    if let Some(ref arg_expr) = args.arg_expr {
        for parsed_expr in Parser::new(arg_expr.chars()) {
            last_evaled = Some(try_ok!(state.eval(&try_ok!(parsed_expr))))
        }
    }

    if args.flag_interactive {
        let mut stdin = io::stdin();
        let mut stdout = io::stdout();

        loop {
            print!("-> ");
            stdout.flush().ok();
            let ref mut buf = String::new();
            if try_ok!(stdin.read_line(buf)) > 0 {
                for expr in Parser::new(buf.chars()) {
                    match expr {
                        Ok(parsed_expr) => {
                            match state.eval(&parsed_expr) {
                                Ok(res) => {
                                    println!("{}", res);
                                },
                                Err(err) => {
                                    println!("Whoops, error detected.\n{}.\n\
                                              Please, try again...", err);
                                }
                            }
                        },
                        Err(err) => {
                            println!("Whoops, error detected.\n{}.\n\
                                      Please, try again...", err)
                        },
                    }
                }
            } else {
                return println!("\nHope you enjoyed.\nSee you...");
            }
        }
    } else if let Some(ref expr) = last_evaled {
        println!("{}", expr);
    }
}
<commit_msg>Fix warning issues<commit_after>extern crate rustc_serialize;
extern crate docopt;
#[macro_use]
extern crate lust;

use std::io::{self, Write, Read};
use std::path::Path;
use std::fs::{File, metadata};
use docopt::Docopt;
use lust::Parser;
use lust::State;

macro_rules! try_ok {
    ($e:expr) => (match $e {
        Ok(res) => {
            res
        },
        Err(err) => {
            return println!("Whoops, error detected.\n{}.\n\
                             Please, try again...", err)
        }
    })
}

static USAGE: &'static str = "
Usage:
    lust [options] [<expr>]

Options:
    -f <file_path>, --file <file_path>          Evaluate expresions from file
    -i, --interactive                           Run REPL session
";

#[derive(RustcDecodable, Debug)]
struct CliArgs {
    arg_expr: Option<String>,
    flag_file: Option<String>,
    flag_interactive: bool,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    let args = try_ok!(Docopt::new(USAGE).and_then(|d| d.decode::<CliArgs>()));
    let ref mut state = State::new("user".to_string());
    let mut last_evaled = None;

    if let Some(ref flag_file) = args.flag_file {
        let path = Path::new(flag_file);
        let md = metadata(path);
        if is_file_exists!(md) {
            if is_file!(md) {
                let mut file = try_ok!(File::open(&path));
                let ref mut buf = String::new();
                try_ok!(file.read_to_string(buf));
                for parsed_expr in Parser::new(buf.chars()) {
                    last_evaled = Some(try_ok!(state.eval(&try_ok!(parsed_expr))));
                }
            } else {
                return println!("Whoops, error detected.\n\
                                 Specified path is not a file.\n\
                                 Please, specify existing file.");
            }
        } else {
            return println!("Whoops, error detected.\n\
                             File doesn't exist.\n\
                             Please, specify existing file.");
        }
    }

    if let Some(ref arg_expr) = args.arg_expr {
        for parsed_expr in Parser::new(arg_expr.chars()) {
            last_evaled = Some(try_ok!(state.eval(&try_ok!(parsed_expr))))
        }
    }

    if args.flag_interactive {
        let stdin = io::stdin();
        let mut stdout = io::stdout();

        loop {
            print!("-> ");
            stdout.flush().ok();
            let ref mut buf = String::new();
            if try_ok!(stdin.read_line(buf)) > 0 {
                for expr in Parser::new(buf.chars()) {
                    match expr {
                        Ok(parsed_expr) => {
                            match state.eval(&parsed_expr) {
                                Ok(res) => {
                                    println!("{}", res);
                                },
                                Err(err) => {
                                    println!("Whoops, error detected.\n{}.\n\
                                              Please, try again...", err);
                                }
                            }
                        },
                        Err(err) => {
                            println!("Whoops, error detected.\n{}.\n\
                                      Please, try again...", err)
                        },
                    }
                }
            } else {
                return println!("\nHope you enjoyed.\nSee you...");
            }
        }
    } else if let Some(ref expr) = last_evaled {
        println!("{}", expr);
    }
}
<|endoftext|>


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

#[macro_use]
extern crate clap;
extern crate requests;
extern crate serde;
extern crate serde_json;

use clap::{App, SubCommand, AppSettings};
mod crates;

const CARGO: &'static str = "cargo";

fn reportv(reply: crates::Reply, verbose: bool) {
    if verbose {
        println!("{:#}", reply.krate);
    } else {
        println!("{}", reply.krate);
    }
}

fn query(krate: &str) -> Option<crates::Reply> {
    let response = requests::get(&format!("http://crates.io/api/v1/crates/{}", krate)).unwrap();
    // println!("{:?}", response.json().unwrap());
    response.from_json::<crates::Reply>()
}

// use std::fmt;
// fn debug<T>(item: &T)
//     where T: fmt::Debug
// {
//     println!("{:#?}", item);
// }

fn main() {

    let matches = App::new(CARGO)
                      .bin_name(CARGO)
                      .author(crate_authors!())
                      .version(crate_version!())
                      .about("Queries registry for crates details")
                      .setting(AppSettings::GlobalVersion)
                      .setting(AppSettings::VersionlessSubcommands)
                      .setting(AppSettings::SubcommandRequired)
                      .setting(AppSettings::ArgRequiredElseHelp)
                      .subcommand(SubCommand::with_name("info")
                                      .setting(AppSettings::ArgRequiredElseHelp)
                                      .setting(AppSettings::TrailingVarArg)
                                      .arg_from_usage("-v, --verbose 'Provides more info'")
                                      .arg_from_usage("<crate>... 'crate to query'"))
                      .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        let verbose = info.is_present("verbose");
        let report = |k| reportv(k, verbose);
        if let Some(crates) = info.values_of("crate") {
            for krate in crates {
                // debug(&krate);
                query(krate).map(&report);
            }
        }
    }
}
<commit_msg>Simplify code a bit<commit_after>#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

#[macro_use]
extern crate clap;
extern crate requests;
extern crate serde;
extern crate serde_json;

use clap::{App, SubCommand, AppSettings};
mod crates;

const CARGO: &'static str = "cargo";

fn reportv(reply: crates::Reply, verbose: bool) {
    if verbose {
        println!("{:#}", reply.krate);
    } else {
        println!("{}", reply.krate);
    }
}

fn query(krate: &str) -> Option<crates::Reply> {
    let response = requests::get(&format!("http://crates.io/api/v1/crates/{}", krate)).unwrap();
    // println!("{:?}", response.json().unwrap());
    response.from_json::<crates::Reply>()
}

// use std::fmt;
// fn debug<T>(item: &T)
//     where T: fmt::Debug
// {
//     println!("{:#?}", item);
// }

fn main() {

    let matches = App::new(CARGO)
                      .bin_name(CARGO)
                      .author(crate_authors!())
                      .version(crate_version!())
                      .about("Queries registry for crates details")
                      .setting(AppSettings::GlobalVersion)
                      .setting(AppSettings::VersionlessSubcommands)
                      .setting(AppSettings::SubcommandRequired)
                      .setting(AppSettings::ArgRequiredElseHelp)
                      .subcommand(SubCommand::with_name("info")
                                      .setting(AppSettings::ArgRequiredElseHelp)
                                      .setting(AppSettings::TrailingVarArg)
                                      .arg_from_usage("-v, --verbose 'Provides more info'")
                                      .arg_from_usage("<crate>... 'crate to query'"))
                      .get_matches();

    if let Some(info) = matches.subcommand_matches("info") {
        let report = |k| reportv(k, info.is_present("verbose"));
        if let Some(crates) = info.values_of("crate") {
            for krate in crates {
                // debug(&krate);
                query(krate).map(&report);
            }
        }
    }
}
<|endoftext|>


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

#[feature(phase)];
#[phase(syntax, link)] extern crate log;

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

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

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

static SCALE: int = 2;

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

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

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

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

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

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

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

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

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

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

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

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

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

	let waitticks = (4194.304 * 4.0) as uint;

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

		match channel.try_recv() {
			std::comm::Data(event) => match event {
				KeyUp(key) => c.mmu.keypad.keyup(key),
				KeyDown(key) => c.mmu.keypad.keydown(key),
				SpeedUp => periodic = timer.periodic(1),
				SlowDown => periodic = timer.periodic(8),
			},
			std::comm::Empty => {},
			std::comm::Disconnected => { break },
		};
	}
}
<commit_msg>Start main thread also with native<commit_after>#[crate_id = "rboy"];

#[feature(phase)];
#[phase(syntax, link)] extern crate log;

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

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

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

static SCALE: int = 2;

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

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

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

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

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

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

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

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

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

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

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

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

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

	let waitticks = (4194.304 * 4.0) as uint;

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

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


<commit_before>extern crate docopt;
extern crate image;
extern crate serde_json;
extern crate vegas_lattice;

use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

use docopt::{ArgvMap, Docopt};
use image::GenericImage;
use vegas_lattice::{Axis, Lattice};

const USAGE: &'static str = "
Vegas lattice.

Usage:
    vegas-lattice check [<input>]
    vegas-lattice compress [<input>]
    vegas-lattice drop [-x -y -z] [<input>]
    vegas-lattice expand [--x=<x> --y=<y> --z=<z>] [<input>]
    vegas-lattice mask (--xy | --yz | --xz) <mask> [<input>]
    vegas-lattice (-h | --help)
    vegas-lattice --version

Options:
    -h --help       Show this message.
    --version       Show version and exit.
";

fn read(input: &str) -> Result<Lattice, Box<Error>> {
    let mut data = String::new();
    if !input.is_empty() {
        let mut file = File::open(input)?;
        file.read_to_string(&mut data)?;
    } else {
        io::stdin().read_to_string(&mut data)?;
    };
    let lattice: Lattice = data.parse()?;
    Ok(lattice)
}

fn write_compressed(lattice: Lattice) {
    println!("{}", serde_json::to_string(&lattice).unwrap());
}

fn write(lattice: Lattice) {
    println!("{}", serde_json::to_string_pretty(&lattice).unwrap());
}

fn axis_map<'a>(prefix: Option<String>) -> Vec<(String, Axis)> {
    let axes = vec![("x", Axis::X), ("y", Axis::Y), ("z", Axis::Z)];
    match prefix {
        Some(p) => axes.into_iter().map(|(k, i)| (format!("{}{}", p, k), i)).collect(),
        None => axes.into_iter().map(|(k, i)| (k.to_string(), i)).collect(),
    }
}

fn check_error(res: Result<(), Box<Error>>) {
    match res {
        Err(e) => {
            eprintln!("{}", e);
            std::process::exit(1);
        },
        _ => {},
    }
}

// Commands over here

fn check(args: ArgvMap) -> Result<(), Box<Error>> {
    let lattice = read(args.get_str("<input>"))?;
    write(lattice);
    Ok(())
}

fn compress(args: ArgvMap) -> Result<(), Box<Error>> {
    let lattice = read(args.get_str("<input>"))?;
    write_compressed(lattice);
    Ok(())
}

fn drop(args: ArgvMap) -> Result<(), Box<Error>> {
    let mut lattice = read(args.get_str("<input>"))?;
    for (key, axis) in axis_map(Some("-".to_string())) {
        if args.get_bool(&key) {
            lattice = lattice.drop(axis);
        }
    }
    write(lattice);
    Ok(())
}

fn expand(args: ArgvMap) -> Result<(), Box<Error>> {
    let map = axis_map(Some("--".to_string()));
    let mut lattice = read(args.get_str("<input>"))?;
    for (flag, axis) in map.into_iter() {
        let string_value = args.get_str(&flag);
        if !string_value.is_empty() {
            let size: usize = string_value.parse()?;
            lattice = lattice.expand_along(axis, size);
        }
    }
    write(lattice);
    Ok(())
}

fn mask(args: ArgvMap) -> Result<(), Box<Error>> {
    // Use the open function to load an image from a Path.
    // ```open``` returns a dynamic image.
    let img = image::open(&Path::new(args.get_str("<mask>")))?;

    println!("Work in progress!");

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", img.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", img.color());

    Ok(())
}

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|doc| doc.version(Some("0.0.1".to_string())).parse())
        .unwrap_or_else(|e| e.exit());

    if args.get_bool("check") {
        check_error(check(args));
    } else if args.get_bool("compress") {
        check_error(compress(args));
    } else if args.get_bool("drop") {
        check_error(drop(args));
    } else if args.get_bool("expand") {
        check_error(expand(args));
    } else if args.get_bool("mask") {
        check_error(mask(args));
    } else {
        println!("{:?}", args);
    }
}<commit_msg>Get to the info we need<commit_after>extern crate docopt;
extern crate image;
extern crate serde_json;
extern crate vegas_lattice;

use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

use docopt::{ArgvMap, Docopt};
use image::{GenericImage, Pixel};
use vegas_lattice::{Axis, Lattice};

const USAGE: &'static str = "
Vegas lattice.

Usage:
    vegas-lattice check [<input>]
    vegas-lattice compress [<input>]
    vegas-lattice drop [-x -y -z] [<input>]
    vegas-lattice expand [--x=<x> --y=<y> --z=<z>] [<input>]
    vegas-lattice mask (--xy | --yz | --xz) <mask> [<input>]
    vegas-lattice (-h | --help)
    vegas-lattice --version

Options:
    -h --help       Show this message.
    --version       Show version and exit.
";

fn read(input: &str) -> Result<Lattice, Box<Error>> {
    let mut data = String::new();
    if !input.is_empty() {
        let mut file = File::open(input)?;
        file.read_to_string(&mut data)?;
    } else {
        io::stdin().read_to_string(&mut data)?;
    };
    let lattice: Lattice = data.parse()?;
    Ok(lattice)
}

fn write_compressed(lattice: Lattice) {
    println!("{}", serde_json::to_string(&lattice).unwrap());
}

fn write(lattice: Lattice) {
    println!("{}", serde_json::to_string_pretty(&lattice).unwrap());
}

fn axis_map<'a>(prefix: Option<String>) -> Vec<(String, Axis)> {
    let axes = vec![("x", Axis::X), ("y", Axis::Y), ("z", Axis::Z)];
    match prefix {
        Some(p) => axes.into_iter().map(|(k, i)| (format!("{}{}", p, k), i)).collect(),
        None => axes.into_iter().map(|(k, i)| (k.to_string(), i)).collect(),
    }
}

fn check_error(res: Result<(), Box<Error>>) {
    match res {
        Err(e) => {
            eprintln!("{}", e);
            std::process::exit(1);
        },
        _ => {},
    }
}

// Commands over here

fn check(args: ArgvMap) -> Result<(), Box<Error>> {
    let lattice = read(args.get_str("<input>"))?;
    write(lattice);
    Ok(())
}

fn compress(args: ArgvMap) -> Result<(), Box<Error>> {
    let lattice = read(args.get_str("<input>"))?;
    write_compressed(lattice);
    Ok(())
}

fn drop(args: ArgvMap) -> Result<(), Box<Error>> {
    let mut lattice = read(args.get_str("<input>"))?;
    for (key, axis) in axis_map(Some("-".to_string())) {
        if args.get_bool(&key) {
            lattice = lattice.drop(axis);
        }
    }
    write(lattice);
    Ok(())
}

fn expand(args: ArgvMap) -> Result<(), Box<Error>> {
    let map = axis_map(Some("--".to_string()));
    let mut lattice = read(args.get_str("<input>"))?;
    for (flag, axis) in map.into_iter() {
        let string_value = args.get_str(&flag);
        if !string_value.is_empty() {
            let size: usize = string_value.parse()?;
            lattice = lattice.expand_along(axis, size);
        }
    }
    write(lattice);
    Ok(())
}

fn mask(args: ArgvMap) -> Result<(), Box<Error>> {
    // Use the open function to load an image from a Path.
    // ```open``` returns a dynamic image.
    let img = image::open(&Path::new(args.get_str("<mask>")))?;

    println!("Work in progress!");

    // The dimensions method returns the images width and height
    println!("dimensions {:?}", img.dimensions());

    // The color method returns the image's ColorType
    println!("{:?}", img.color());

    // First pixel
    println!("{:?}", img.get_pixel(0, 0));

    for (i, j, pixel) in img.pixels() {
        println!("{:?}", pixel.channels()[3]);
    }

    Ok(())
}

fn main() {
    let args = Docopt::new(USAGE)
        .and_then(|doc| doc.version(Some("0.0.1".to_string())).parse())
        .unwrap_or_else(|e| e.exit());

    if args.get_bool("check") {
        check_error(check(args));
    } else if args.get_bool("compress") {
        check_error(compress(args));
    } else if args.get_bool("drop") {
        check_error(drop(args));
    } else if args.get_bool("expand") {
        check_error(expand(args));
    } else if args.get_bool("mask") {
        check_error(mask(args));
    } else {
        println!("{:?}", args);
    }
}<|endoftext|>


<commit_before>extern crate hkg;

extern crate rustbox;

use std::default::Default;

use rustbox::{Color, RustBox};
use rustbox::Key;

fn main() {

    let rustbox = match RustBox::init(Default::default()) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    let w = rustbox.width();
    let h = rustbox.height();
    let title = String::from("高登");
    print_header(&rustbox, w, h, title);
    // print_body(&rustbox, w, h, 2, 2);
    // rustbox.print(1, 23, rustbox::RB_BOLD, Color::White, Color::Black, "Press 'q' to quit.");

    print_cjk_count(&rustbox);

    loop {
        rustbox.present();
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Key::Char('q') => {
                        break;
                    }
                    _ => {}
                }
            }
            Err(e) => panic!("{}", e),
            _ => {}
        }
    }
}

fn contains(c: char) -> bool {
    let cjks = vec![(0x4E00..0xA000),
                    (0x3400..0x4DC0),
                    (0x20000..0x2A6E0),
                    (0x2A700..0x2B740),
                    (0x2B740..0x2B820),
                    (0xF900..0xFB00),
                    (0x2F800..0x2FA20),
                    (0x9FA6..0x9FCC)];

    for cjk in cjks {
        let h = c as u32;
        if cjk.start <= h && h < cjk.end {
            return true;
        }
    }
    return false;
}

fn print_header(rustbox: &rustbox::RustBox, width: usize, height: usize, text: String) {
    let padding = (width - text.len()) / 2;
    let header_bottom = (0..width).map(|i| "─").collect::<Vec<_>>().join("");
    rustbox.print(padding,
                  0,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  &text);
    rustbox.print(0,
                  1,
                  rustbox::RB_BOLD,
                  Color::Yellow,
                  Color::Black,
                  &header_bottom);
}

fn print_body(rustbox: &rustbox::RustBox,
              width: usize,
              height: usize,
              offset_x: usize,
              rows: usize) {
    let titles = vec!["紅魔英超睇敢帥　十分之高招",
                      "發覺好多後生仔女搭火車地鐵 有位都唔坐"];
    let authors = vec!["電超", "程詠樂"];

    for i in (0..rows) {
        rustbox.print(0,
                      i + offset_x,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &format!("{no:>2}|{title:<50}|{author}",
                               no = i + 1,
                               title = &titles[i],
                               author = &authors[i]));
    }
}

fn print_cjk_count(rustbox: &rustbox::RustBox){

    let mut offset_y = 2;

    let s1 = String::from("紅魔英超睇敢帥　十分之高招");
    for (b, c) in s1.chars().enumerate() {
        rustbox.print(1,
                      b + 2,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &format!("{} 0x{:X}", c, c as u32));
    }

    offset_y = 16;

    let s2 = String::from("<<100%成功率>>如何成為成功?香港Youtuber");
    let mut s2count = 0;
    for (d, c) in s2.chars().enumerate() {
        if contains(c) {
            rustbox.print(1,
                          d + offset_y,
                          rustbox::RB_BOLD,
                          Color::White,
                          Color::Black,
                          &format!("[{:<2}] {:>2} 0x{:X} {}", d + offset_y, c, c as u32, &"YES"));
                          s2count = s2count + 2;
        } else {
            rustbox.print(1,
                          d + offset_y,
                          rustbox::RB_BOLD,
                          Color::White,
                          Color::Black,
                          &format!("[{:<2}] {:>2} 0x{:X} {}", d + offset_y, c, c as u32, &"NO"));
                          s2count = s2count + 1;
        }
    }

    let sum = s2.chars().map(|x| if contains(x) { 2 } else { 1 } ).collect::<Vec<u32>>().iter().fold(0, |acc, &x| acc + x);

    rustbox.print(1,
                  45,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  &format!("{} {}", sum, s2count));

}
<commit_msg>working draft<commit_after>extern crate hkg;

extern crate rustbox;

use std::default::Default;

use rustbox::{Color, RustBox};
use rustbox::Key;

fn main() {

    let rustbox = match RustBox::init(Default::default()) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    let w = rustbox.width();
    let h = rustbox.height();
    let title = String::from("高登");
    print_header(&rustbox, w, h, title);
    print_body(&rustbox, w, h, 2, 2);
    rustbox.print(1,
                  23,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  "Press 'q' to quit.");

    // print_cjk_count(&rustbox);
    //
    // let s2 = String::from("<<100%成功率>>如何成為成功?香港Youtuber");
    //
    // rustbox.print(1,
    //               3,
    //               rustbox::RB_BOLD,
    //               Color::White,
    //               Color::Black,
    //               &format!("{}", real_count(s2)));

    loop {
        rustbox.present();
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Key::Char('q') => {
                        break;
                    }
                    _ => {}
                }
            }
            Err(e) => panic!("{}", e),
            _ => {}
        }
    }
}

fn contains(c: char) -> bool {
    let cjks = vec![(0x4E00..0xA000),
                    (0x3400..0x4DC0),
                    (0x20000..0x2A6E0),
                    (0x2A700..0x2B740),
                    (0x2B740..0x2B820),
                    (0xF900..0xFB00),
                    (0x2F800..0x2FA20),
                    (0x9FA6..0x9FCC)];

    for cjk in cjks {
        let h = c as u32;
        if cjk.start <= h && h < cjk.end {
            return true;
        }
    }
    return false;
}

fn real_count(s: &str) -> usize {
    return s.chars()
            .map(|x| if contains(x) {
                2
            } else {
                1
            })
            .collect::<Vec<usize>>()
            .iter()
            .fold(0, |acc, &x| acc + x);
}

fn print_header(rustbox: &rustbox::RustBox, width: usize, height: usize, text: String) {
    let padding = (width - text.len()) / 2;
    let header_bottom = (0..width).map(|i| "─").collect::<Vec<_>>().join("");
    rustbox.print(padding,
                  0,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  &text);
    rustbox.print(0,
                  1,
                  rustbox::RB_BOLD,
                  Color::Yellow,
                  Color::Black,
                  &header_bottom);
}

fn print_body(rustbox: &rustbox::RustBox,
              width: usize,
              height: usize,
              offset_x: usize,
              rows: usize) {
    let titles = vec!["紅魔英超睇敢帥　十分之高招",
                      "發覺好多後生仔女搭火車地鐵 有位都唔坐"];
    let authors = vec!["電超", "程詠樂"];

    let mut title_spacing = 0;
    for i in (0..rows) {

        let s1 = format!("{no:>2}|", no = i + 1);
        let s2 = format!("{title}", title = &titles[i]);

        rustbox.print(0,
                      i + offset_x,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &(format!("{}{}", s1,s2)));

        title_spacing = s1.len() + real_count(&titles[i]) + 55 - real_count(&titles[i]);

        rustbox.print(title_spacing,
                      i + offset_x,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &format!("|{author}", author = &authors[i]));
    }
}

fn print_cjk_count(rustbox: &rustbox::RustBox) {

    let mut offset_y = 2;

    let s1 = String::from("紅魔英超睇敢帥　十分之高招");
    for (b, c) in s1.chars().enumerate() {
        rustbox.print(1,
                      b + 2,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &format!("{} 0x{:X}", c, c as u32));
    }

    offset_y = 16;

    let s2 = String::from("<<100%成功率>>如何成為成功?香港Youtuber");
    let mut s2count = 0;
    for (d, c) in s2.chars().enumerate() {
        if contains(c) {
            rustbox.print(1,
                          d + offset_y,
                          rustbox::RB_BOLD,
                          Color::White,
                          Color::Black,
                          &format!("[{:<2}] {:>2} 0x{:X} {}", d + offset_y, c, c as u32, &"YES"));
            s2count = s2count + 2;
        } else {
            rustbox.print(1,
                          d + offset_y,
                          rustbox::RB_BOLD,
                          Color::White,
                          Color::Black,
                          &format!("[{:<2}] {:>2} 0x{:X} {}", d + offset_y, c, c as u32, &"NO"));
            s2count = s2count + 1;
        }
    }

    let sum = s2.chars()
                .map(|x| if contains(x) {
                    2
                } else {
                    1
                })
                .collect::<Vec<u32>>()
                .iter()
                .fold(0, |acc, &x| acc + x);

    rustbox.print(1,
                  45,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  &format!("{} {}", sum, s2count));

}
<|endoftext|>


<commit_before>extern crate libc;
extern crate x11;
extern crate getopts;

mod matches;
mod ui;

use ui::UI;
use matches::simple_match;
use matches::fuzzy_match;
use matches::dmenu_match;
use std::str::FromStr;
use std::io::BufRead;
use std::io::BufReader;
use std::fs::File;
use std::env;
use std::iter::Iterator;

use getopts::Options;

const VERSION: &'static str = "0.0.1";

pub struct Settings {
    topbar: bool,
    fast: bool,
    casesensitive: bool,
    lines: u32,
    prompt: String,
    font: String,
    normbgcolor: String,
    normfgcolor: String,
    selbgcolor: String,
    selfgcolor: String,
    cache_file: String,
    matcher: String,
}

impl Settings {
    fn new() -> Settings{
        Settings {
            topbar: false,
            fast: false,
            casesensitive: true,
            lines: 0,
            prompt: String::new(),
            font: "fixed".to_string(),
            normbgcolor: "rgb:22/22/22".to_string(),
            normfgcolor: "rgb:bb/bb/bb".to_string(),
            selbgcolor: "rgb:00/55/77".to_string(),
            selfgcolor: "rgb:ee/ee/ee".to_string(),
            cache_file: "-".to_string(),
            matcher: "simple".to_string(),
        }
    }
}

struct Status {
    text: String,
    matches: Vec<String>,
    items: Vec<String>,
    selected: String,
    page: u32,
    settings: Settings,
}

fn readitems(settings: &Settings) -> Vec<String> {
    let mut items = vec![];
    let mut input_items: Vec<_>;

    if settings.cache_file == "-" {
        let stdin = std::io::stdin();
        input_items = stdin.lock().lines().collect();
    } else {
        input_items = match File::open(settings.cache_file.clone()) {
            Ok(file) => BufReader::new(file).lines().collect(),
            Err(e) => panic!("{}", e)
        }
    }
    for item in input_items {
        items.push(item.unwrap())
    }
    items
}

fn main () {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut settings = Settings::new();

    let mut opts = Options::new();
    opts.optflag("v", "version", "show version");
    opts.optflag("b", "topbar", "show topbar");
    opts.optflag("f", "fast", "fast start");
    opts.optflag("h", "help", "show help");
    opts.optflag("i", "caseinsensitive", "activate case insensitive");

    opts.optopt("l", "lines", "lines of vertical list", "LINES");
    opts.optopt("c", "cache", "cache file with available commands", "CACHE_FILE");
    opts.optopt("p", "prompt", "add prompt to left of input field", "PROMPT");
    opts.optopt("m", "matcher", "select matcher function", "simple|dmenu|fuzzy");
    opts.optopt("", "font", "font or font set", "FONT");
    opts.optopt("", "background", "normal background color", "NBG");
    opts.optopt("", "foreground", "normal foreground color", "NFG");
    opts.optopt("", "sbackground", "selected background color", "SBG");
    opts.optopt("", "sforeground", "selected foreground color", "SFG");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("v") {
        println!("rumenu-{}, © 2015 Jesús Espino, see LICENSE for details", VERSION);
        return;
    }

    if matches.opt_present("h") {
        let brief = format!("Usage: {} [options]", program);
        print!("{}", opts.usage(&brief));
        return;
    }

    settings.topbar = matches.opt_present("b");
    settings.fast = matches.opt_present("f");
    settings.casesensitive = !matches.opt_present("i");

    match matches.opt_str("l") {
        Some(lines_str) => {
            match u32::from_str(lines_str.trim()) {
                Ok(l) => { settings.lines = l }
                Err(f) => { println!("{}", f.to_string()); return }
            }
        }
        None => {
            settings.lines = 0
        }
    }

    settings.prompt =  matches.opt_str("p").unwrap_or(String::new());
    settings.matcher =  matches.opt_str("m").unwrap_or("simple".to_string());
    settings.font = matches.opt_str("font").unwrap_or("fixed".to_string());
    settings.normbgcolor = matches.opt_str("background").unwrap_or("rgb:22/22/22".to_string());
    settings.normfgcolor = matches.opt_str("foreground").unwrap_or("rgb:bb/bb/bb".to_string());
    settings.selbgcolor = matches.opt_str("sbackground").unwrap_or("rgb:00/55/77".to_string());
    settings.selfgcolor = matches.opt_str("sforeground").unwrap_or("rgb:ee/ee/ee".to_string());
    settings.cache_file = matches.opt_str("cache").unwrap_or("-".to_string());

    let mut ui = UI::new(&settings);

    let items = readitems(&settings);

    let mut status = Status {
        text: "".to_string(),
        matches: vec![],
        items: items,
        selected: "".to_string(),
        page: 0,
        settings: settings,
    };

    status.items.sort();

    if status.settings.matcher == "fuzzy" {
        status.matches = fuzzy_match(&status.text, &status.items);
    } else if status.settings.matcher == "dmenu" {
        status.matches = dmenu_match(&status.text, &status.items);
    } else {
        status.matches = simple_match(&status.text, &status.items);
    }

    status.selected = status.matches.first().unwrap_or(&"".to_string()).clone();
    ui.run(status);
}
<commit_msg>Removed unnecesary sort<commit_after>extern crate libc;
extern crate x11;
extern crate getopts;

mod matches;
mod ui;

use ui::UI;
use matches::simple_match;
use matches::fuzzy_match;
use matches::dmenu_match;
use std::str::FromStr;
use std::io::BufRead;
use std::io::BufReader;
use std::fs::File;
use std::env;
use std::iter::Iterator;

use getopts::Options;

const VERSION: &'static str = "0.0.1";

pub struct Settings {
    topbar: bool,
    fast: bool,
    casesensitive: bool,
    lines: u32,
    prompt: String,
    font: String,
    normbgcolor: String,
    normfgcolor: String,
    selbgcolor: String,
    selfgcolor: String,
    cache_file: String,
    matcher: String,
}

impl Settings {
    fn new() -> Settings{
        Settings {
            topbar: false,
            fast: false,
            casesensitive: true,
            lines: 0,
            prompt: String::new(),
            font: "fixed".to_string(),
            normbgcolor: "rgb:22/22/22".to_string(),
            normfgcolor: "rgb:bb/bb/bb".to_string(),
            selbgcolor: "rgb:00/55/77".to_string(),
            selfgcolor: "rgb:ee/ee/ee".to_string(),
            cache_file: "-".to_string(),
            matcher: "simple".to_string(),
        }
    }
}

struct Status {
    text: String,
    matches: Vec<String>,
    items: Vec<String>,
    selected: String,
    page: u32,
    settings: Settings,
}

fn readitems(settings: &Settings) -> Vec<String> {
    let mut items = vec![];
    let mut input_items: Vec<_>;

    if settings.cache_file == "-" {
        let stdin = std::io::stdin();
        input_items = stdin.lock().lines().collect();
    } else {
        input_items = match File::open(settings.cache_file.clone()) {
            Ok(file) => BufReader::new(file).lines().collect(),
            Err(e) => panic!("{}", e)
        }
    }
    for item in input_items {
        items.push(item.unwrap())
    }
    items
}

fn main () {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut settings = Settings::new();

    let mut opts = Options::new();
    opts.optflag("v", "version", "show version");
    opts.optflag("b", "topbar", "show topbar");
    opts.optflag("f", "fast", "fast start");
    opts.optflag("h", "help", "show help");
    opts.optflag("i", "caseinsensitive", "activate case insensitive");

    opts.optopt("l", "lines", "lines of vertical list", "LINES");
    opts.optopt("c", "cache", "cache file with available commands", "CACHE_FILE");
    opts.optopt("p", "prompt", "add prompt to left of input field", "PROMPT");
    opts.optopt("m", "matcher", "select matcher function", "simple|dmenu|fuzzy");
    opts.optopt("", "font", "font or font set", "FONT");
    opts.optopt("", "background", "normal background color", "NBG");
    opts.optopt("", "foreground", "normal foreground color", "NFG");
    opts.optopt("", "sbackground", "selected background color", "SBG");
    opts.optopt("", "sforeground", "selected foreground color", "SFG");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };

    if matches.opt_present("v") {
        println!("rumenu-{}, © 2015 Jesús Espino, see LICENSE for details", VERSION);
        return;
    }

    if matches.opt_present("h") {
        let brief = format!("Usage: {} [options]", program);
        print!("{}", opts.usage(&brief));
        return;
    }

    settings.topbar = matches.opt_present("b");
    settings.fast = matches.opt_present("f");
    settings.casesensitive = !matches.opt_present("i");

    match matches.opt_str("l") {
        Some(lines_str) => {
            match u32::from_str(lines_str.trim()) {
                Ok(l) => { settings.lines = l }
                Err(f) => { println!("{}", f.to_string()); return }
            }
        }
        None => {
            settings.lines = 0
        }
    }

    settings.prompt =  matches.opt_str("p").unwrap_or(String::new());
    settings.matcher =  matches.opt_str("m").unwrap_or("simple".to_string());
    settings.font = matches.opt_str("font").unwrap_or("fixed".to_string());
    settings.normbgcolor = matches.opt_str("background").unwrap_or("rgb:22/22/22".to_string());
    settings.normfgcolor = matches.opt_str("foreground").unwrap_or("rgb:bb/bb/bb".to_string());
    settings.selbgcolor = matches.opt_str("sbackground").unwrap_or("rgb:00/55/77".to_string());
    settings.selfgcolor = matches.opt_str("sforeground").unwrap_or("rgb:ee/ee/ee".to_string());
    settings.cache_file = matches.opt_str("cache").unwrap_or("-".to_string());

    let mut ui = UI::new(&settings);

    let items = readitems(&settings);

    let mut status = Status {
        text: "".to_string(),
        matches: vec![],
        items: items,
        selected: "".to_string(),
        page: 0,
        settings: settings,
    };

    if status.settings.matcher == "fuzzy" {
        status.matches = fuzzy_match(&status.text, &status.items);
    } else if status.settings.matcher == "dmenu" {
        status.matches = dmenu_match(&status.text, &status.items);
    } else {
        status.matches = simple_match(&status.text, &status.items);
    }

    status.selected = status.matches.first().unwrap_or(&"".to_string()).clone();
    ui.run(status);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate rustc_serialize;
extern crate structopt;
extern crate url;
#[macro_use]
extern crate structopt_derive;

use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::os::unix::process::ExitStatusExt;
use std::process::Command;
use std::thread;
use structopt::StructOpt;
use url::Url;

#[derive(StructOpt, Debug)]
#[structopt()]
struct Opt {
    #[structopt(short = "c", long = "command", default_value = "xdg-open")]
    /// Command executed for each URL received
    command: String,

    #[structopt(short = "l", long = "listen-address", default_value = "127.0.0.1:7777")]
    /// Address and port to listen to
    address: String,
}

fn main() {
    let opt = Opt::from_args();

    let browser_command = opt.command;
    let listener = match TcpListener::bind(opt.address) {
        Ok(l) => l,
        Err(e) => panic!("Could not bind to {}: {}", opt.address, e),
    };

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                debug!("Accepted new incoming connection");
                let command = browser_command.clone();
                thread::spawn(move || {
                    debug!("Spawned new thread to handle connection");
                    handle_client(stream, command)
                });
            }
            Err(e) => panic!("Could not handle incoming connection: {}", e),
        }
    }

    drop(listener);
}

fn handle_client(mut stream: TcpStream, browser_command: String) {
    let mut message = String::new();
    match stream.read_to_string(&mut message) {
        Ok(_) => {}
        Err(e) => {
            error!("Input isn't a valid UTF-8 string: {}", e);
            return;
        }
    };

    for line in message.split('\n') {
        debug!("Current line is: {}", line);
        match Url::parse(line) {
            Ok(u) => {
                debug!("Found URL in: {}", line);
                if url_valid(&u) {
                    debug!("Found URL is valid");
                    spawn_browser(&browser_command, &format!("{}", u));
                }
            }
            Err(e) => info!("No URL found in '{}': {}", line, e),
        }
    }
}

fn url_valid(u: &Url) -> bool {
    (u.scheme() == "http" || u.scheme() == "https") && u.host().is_some()
}

fn spawn_browser(command: &str, url: &str) {
    debug!("Spawning process: {} {}", command, url);
    let output = match Command::new(command).arg(url).output() {
        Ok(output) => output,
        Err(e) => panic!("Failed to spawn process '{} {}': {}", command, url, e),
    };
    if output.status.success() {
        debug!("Process exited successfully");
    } else {
        info!(
            "stdout:\n{:?}\n\nstderr:\n{:?}",
            output.stdout, output.stderr
        );
        match output.status.code() {
            None => match output.status.signal() {
                None => panic!("Should never happen!"),
                Some(i) => panic!("Process received signal: {}", i),
            },
            Some(i) => panic!("Process exited with status: {}", i),
        }
    }
}
<commit_msg>main: minor String/str fixes<commit_after>#[macro_use]
extern crate log;
extern crate rustc_serialize;
extern crate structopt;
extern crate url;
#[macro_use]
extern crate structopt_derive;

use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::os::unix::process::ExitStatusExt;
use std::process::Command;
use std::thread;
use structopt::StructOpt;
use url::Url;

#[derive(StructOpt, Debug)]
#[structopt()]
struct Opt {
    #[structopt(short = "c", long = "command", default_value = "xdg-open")]
    /// Command executed for each URL received
    command: String,

    #[structopt(short = "l", long = "listen-address", default_value = "127.0.0.1:7777")]
    /// Address and port to listen to
    address: String,
}

fn main() {
    let opt = Opt::from_args();

    let browser_command = opt.command;
    let listener = match TcpListener::bind(opt.address.clone()) {
        Ok(l) => l,
        Err(e) => panic!("Could not bind to {}: {}", opt.address, e),
    };

    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                debug!("Accepted new incoming connection");
                let command = browser_command.clone();
                thread::spawn(move || {
                    debug!("Spawned new thread to handle connection");
                    handle_client(stream, &command)
                });
            }
            Err(e) => panic!("Could not handle incoming connection: {}", e),
        }
    }

    drop(listener);
}

fn handle_client(mut stream: TcpStream, browser_command: &str) {
    let mut message = String::new();
    match stream.read_to_string(&mut message) {
        Ok(_) => {}
        Err(e) => {
            error!("Input isn't a valid UTF-8 string: {}", e);
            return;
        }
    };

    for line in message.split('\n') {
        debug!("Current line is: {}", line);
        match Url::parse(line) {
            Ok(u) => {
                debug!("Found URL in: {}", line);
                if url_valid(&u) {
                    debug!("Found URL is valid");
                    spawn_browser(&browser_command, &format!("{}", u));
                }
            }
            Err(e) => info!("No URL found in '{}': {}", line, e),
        }
    }
}

fn url_valid(u: &Url) -> bool {
    (u.scheme() == "http" || u.scheme() == "https") && u.host().is_some()
}

fn spawn_browser(command: &str, url: &str) {
    debug!("Spawning process: {} {}", command, url);
    let output = match Command::new(command).arg(url).output() {
        Ok(output) => output,
        Err(e) => panic!("Failed to spawn process '{} {}': {}", command, url, e),
    };
    if output.status.success() {
        debug!("Process exited successfully");
    } else {
        info!(
            "stdout:\n{:?}\n\nstderr:\n{:?}",
            output.stdout, output.stderr
        );
        match output.status.code() {
            None => match output.status.signal() {
                None => panic!("Should never happen!"),
                Some(i) => panic!("Process received signal: {}", i),
            },
            Some(i) => panic!("Process exited with status: {}", i),
        }
    }
}
<|endoftext|>


<commit_before>#![crate_type = "bin"]

extern crate metrics;

use metrics::{counter,gauge};

fn main() {
    // Create a metric w val 0
    let mut g1: gauge::Gauge = gauge::Gauge{value: 0};
    println!("{}", g1.value);
    g1.update(100);

    // Get a snapshot of it to g2
    let g2: gauge::Gauge = g1.snapshot();

    // Update g1 to 200
    g1.update(200);

    println!("g1 {} g2 {}", g1.value, g2.value);

    println!("{}", g1.value);

    let mut c1 = counter::Counter{count: 0};
    c1.inc(1);
    c1.inc(5);
    println!("{}", c1.count)
}<commit_msg>counter > value<commit_after>#![crate_type = "bin"]

extern crate metrics;

use metrics::{counter,gauge};

fn main() {
    // Create a metric w val 0
    let mut g1: gauge::Gauge = gauge::Gauge{value: 0};
    println!("{}", g1.value);
    g1.update(100);

    // Get a snapshot of it to g2
    let g2: gauge::Gauge = g1.snapshot();

    // Update g1 to 200
    g1.update(200);

    println!("g1 {} g2 {}", g1.value, g2.value);

    println!("{}", g1.value);

    let mut c1 = counter::Counter{value: 0};
    c1.inc(1);
    c1.inc(5);
    println!("{}", c1.value)
}<|endoftext|>