<commit_before>//! The parser works based on the following grammar
//!
//! Equation ==> Term { "+" Term }
//!           |  Term { "-" Term }
//!
//! Term     ==> Function Product
//!           |  Product
//!
//! Product  ==> Factor { "*" Factor }
//!           |  Factor { "/" Factor }
//!
//! Factor   ==> "-" Factor
//!           |  Exponent { "^" Factor }
//!
//! Exponent ==> Number { "!" }
//!
//! Number   ==> "(" Equation ")"
//!           |  "|" Equation "|"
//!           |  Constant
//!           |  { Digit }
//!
//! Function ==> "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "sqrt" | "qbrt" | "abs" | "exp"
//!           |  "ln" | "log"
//!
//! Constant ==> "pi" | "e" | "phi"
//!
//! Digit    ==> "0".."9"

use std::str::CharRange;
use errors::{CResult, CError};
use ast::{Ast, AstFunc, AstConst};
use ast::AstBranch::*;
use ast::AstVal::*;
use ast::AstFunc::*;
use ast::AstOp::*;
use ast::AstConst::*;

#[derive(Debug)]
pub struct Parser {
    pos: usize,
    input: String,
    paren_level: u32,
    abs_level: u32,
}

impl Parser {
    pub fn new(input: String) -> Self {
        Parser {
            pos: 0,
            input: input,
            paren_level: 0,
            abs_level: 0,
        }
    }

    pub fn parse_equation(&mut self) -> CResult<Ast> {
        let mut lhs = try!(self.parse_term());
        self.consume_whitespace();
        while self.peek_char() == Some('+') || self.peek_char() == Some('-') {
            let op = if self.consume_char() == '+' {
                Plus
            } else {
                Minus
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_term());
            lhs = Ast {
                val: Op(op),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        Ok(lhs)
    }

    fn parse_term(&mut self) -> CResult<Ast> {
        if let Some(func) = self.consume_function() {
            self.consume_whitespace();
            let arg = try!(self.parse_product());
            Ok(Ast {
                val: Func(func),
                branches: Unary(Box::new(arg)),
            })
        } else {
            self.parse_product()
        }
    }

    fn parse_product(&mut self) -> CResult<Ast> {
        let mut lhs = try!(self.parse_factor());
        self.consume_whitespace();
        while self.peek_char() == Some('*') || self.peek_char() == Some('/') {
            let op = if self.consume_char() == '*' {
                Mult
            } else {
                Div
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_factor());
            lhs = Ast {
                val: Op(op),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        Ok(lhs)
    }

    fn parse_factor(&mut self) -> CResult<Ast> {
        if self.peek_char() == Some('-') {
            self.consume_char();
            let rhs = try!(self.parse_factor());
            Ok(Ast {
                val: Op(Neg),
                branches: Unary(Box::new(rhs)),
            })
        } else {
            let lhs = try!(self.parse_exponent());
            if self.peek_char() == Some('^') {
                self.consume_char();
                let rhs = try!(self.parse_factor());
                Ok(Ast {
                    val: Op(Pow),
                    branches: Binary(Box::new(lhs), Box::new(rhs)),
                })
            } else {
                Ok(lhs)
            }
        }
    }

    fn parse_exponent(&mut self) -> CResult<Ast> {
        let mut out = try!(self.parse_number());
        self.consume_whitespace();

        // we don't parse the factorial signs (`!`) using recursion, since we need to put the
        // current `out` at the bottum of the tree at each step, so it is easier if we have access
        // to each node as we create them.
        while self.peek_char() == Some('!') {
            self.consume_char();
            self.consume_whitespace();
            out = Ast {
                val: Op(Fact),
                branches: Unary(Box::new(out)),
            };
        }
        Ok(out)
    }

    fn parse_number(&mut self) -> CResult<Ast> {
        if self.peek_char() == Some('(') {
            // store the current pos in case we need to report a paren error
            let pre_pos = self.pos;
            self.consume_char();
            self.consume_whitespace();
            self.paren_level += 1;
            let eq = try!(self.parse_equation());

            if self.eof() || self.consume_char() != ')' {
                Err(CError {
                    desc: "Missing closing parentheses".to_string(),
                    span: (pre_pos, pre_pos),
                })
            } else {
                self.paren_level -= 1;
                Ok(eq)
            }
        } else if self.peek_char() == Some('|') {
            // store the current pos in case we need to report an abs delim error
            let pre_pos = self.pos;
            self.consume_char();
            self.consume_whitespace();
            self.abs_level += 1;
            let eq = try!(self.parse_equation());

            if self.eof() || self.consume_char() != '|' {
                Err(CError {
                    desc: "Missing closing abs delimiter".to_string(),
                    span: (pre_pos, pre_pos),
                })
            } else {
                self.abs_level -= 1;
                Ok(Ast {
                    val: Func(Abs),
                    branches: Unary(Box::new(eq)),
                })
            }
        } else if let Some(cnst) = self.consume_constant() {
            Ok(Ast {
                val: Const(cnst),
                branches: Leaf,
            })
        } else {
            if let Ok(num) = self.consume_while(|ch| ch.is_numeric()).parse::<f64>() {
                Ok(Ast {
                    val: Num(num),
                    branches: Leaf,
                })
            } else {
                Err(CError {
                    desc: "Missing number or constant".to_string(),
                    span: (self.pos, self.pos),
                })
            }
        }
    }

    fn consume_function(&mut self) -> Option<AstFunc> {
        let pre_pos = self.pos;
        match self.consume_while(|ch| ch.is_alphabetic()).as_slice() {
            "sin" => Some(Sin),
            "cos" => Some(Cos),
            "tan" => Some(Tan),
            "asin" => Some(Asin),
            "acos" => Some(Acos),
            "atan" => Some(Atan),
            "sqrt" => Some(Sqrt),
            "qbrt" => Some(Qbrt),
            "abs" => Some(Abs),
            "exp" => Some(Exp),
            "ln" => Some(Ln),
            "log" => Some(Log),
            _ => {
                // no function found, so restore the previous position
                self.pos = pre_pos;
                None
            },
        }
    }

    fn consume_constant(&mut self) -> Option<AstConst> {
        let pre_pos = self.pos;
        match self.consume_while(|ch| ch.is_alphabetic()).as_slice() {
            "pi" => Some(Pi),
            "e" => Some(E),
            "phi" => Some(Phi),
            _ => {
                // no constant found, so restore the previous position
                self.pos = pre_pos;
                None
            }
        }
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&self) -> Option<char> {
        if self.eof() {
            None
        } else {
            Some(self.input.char_at(self.pos).to_lowercase())
        }
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let CharRange { ch, next } = self.input.char_range_at(self.pos);
        self.pos = next;
        ch.to_lowercase()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }

    /// Returns true if we are the end of input
    fn eof(&self) -> bool {
        self.pos >= self.input.len()
    }
}<commit_msg>Change parser to make error reporting better<commit_after>//! The parser works based on the following grammar
//!
//! Equation ==> Term { "+" Term }
//!           |  Term { "-" Term }
//!
//! Term     ==> Function Product
//!           |  Product
//!
//! Product  ==> Factor { "*" Factor }
//!           |  Factor { "/" Factor }
//!
//! Factor   ==> "-" Factor
//!           |  Exponent { "^" Factor }
//!
//! Exponent ==> Number { "!" }
//!
//! Number   ==> "(" Equation ")"
//!           |  "|" Equation "|"
//!           |  Constant
//!           |  { Digit }
//!
//! Function ==> "sin" | "cos" | "tan" | "asin" | "acos" | "atan" | "sqrt" | "qbrt" | "abs" | "exp"
//!           |  "ln" | "log"
//!
//! Constant ==> "pi" | "e" | "phi"
//!
//! Digit    ==> "0".."9"

use std::str::CharRange;
use errors::{CResult, CError};
use ast::{Ast, AstFunc, AstConst};
use ast::AstBranch::*;
use ast::AstVal::*;
use ast::AstFunc::*;
use ast::AstOp::*;
use ast::AstConst::*;

#[derive(Debug)]
pub struct Parser {
    pos: usize,
    input: String,
    paren_level: u32,
    abs_level: u32,
}

impl Parser {
    pub fn new(input: String) -> Self {
        Parser {
            pos: 0,
            input: input,
            paren_level: 0,
            abs_level: 0,
        }
    }

    pub fn parse_equation(&mut self) -> CResult<Ast> {
        let mut lhs = try!(self.parse_term());
        self.consume_whitespace();
        while self.peek_char() == Some('+') || self.peek_char() == Some('-') {
            let op = if self.consume_char() == '+' {
                Plus
            } else {
                Minus
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_term());
            lhs = Ast {
                val: Op(op),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        Ok(lhs)
    }

    fn parse_term(&mut self) -> CResult<Ast> {
        if let Some(func) = self.consume_function() {
            self.consume_whitespace();
            let arg = try!(self.parse_product());
            Ok(Ast {
                val: Func(func),
                branches: Unary(Box::new(arg)),
            })
        } else {
            self.parse_product()
        }
    }

    fn parse_product(&mut self) -> CResult<Ast> {
        let mut lhs = try!(self.parse_factor());
        self.consume_whitespace();
        while self.peek_char() == Some('*') || self.peek_char() == Some('/') {
            let op = if self.consume_char() == '*' {
                Mult
            } else {
                Div
            };
            self.consume_whitespace();
            let rhs = try!(self.parse_factor());
            lhs = Ast {
                val: Op(op),
                branches: Binary(Box::new(lhs), Box::new(rhs)),
            };
            self.consume_whitespace();
        }
        Ok(lhs)
    }

    fn parse_factor(&mut self) -> CResult<Ast> {
        if self.peek_char() == Some('-') {
            self.consume_char();
            let rhs = try!(self.parse_factor());
            Ok(Ast {
                val: Op(Neg),
                branches: Unary(Box::new(rhs)),
            })
        } else {
            let lhs = try!(self.parse_exponent());
            if self.peek_char() == Some('^') {
                self.consume_char();
                let rhs = try!(self.parse_factor());
                Ok(Ast {
                    val: Op(Pow),
                    branches: Binary(Box::new(lhs), Box::new(rhs)),
                })
            } else {
                Ok(lhs)
            }
        }
    }

    fn parse_exponent(&mut self) -> CResult<Ast> {
        let mut out = try!(self.parse_number());
        self.consume_whitespace();

        // we don't parse the factorial signs (`!`) using recursion, since we need to put the
        // current `out` at the bottum of the tree at each step, so it is easier if we have access
        // to each node as we create them.
        while self.peek_char() == Some('!') {
            self.consume_char();
            self.consume_whitespace();
            out = Ast {
                val: Op(Fact),
                branches: Unary(Box::new(out)),
            };
        }
        Ok(out)
    }

    fn parse_number(&mut self) -> CResult<Ast> {
        match self.peek_char() {
            Some('(') => {
                // store the current pos in case we need to report a paren error
                let pre_pos = self.pos;
                self.consume_char();
                self.consume_whitespace();
                self.paren_level += 1;
                let eq = try!(self.parse_equation());

                if self.eof() || self.consume_char() != ')' {
                    Err(CError {
                        desc: "Missing closing parentheses".to_string(),
                        span: (pre_pos, pre_pos),
                    })
                } else {
                    self.paren_level -= 1;
                    Ok(eq)
                }
            },
            Some('|') => {
                // store the current pos in case we need to report an abs delim error
                let pre_pos = self.pos;
                self.consume_char();
                self.consume_whitespace();
                self.abs_level += 1;
                let eq = try!(self.parse_equation());

                if self.eof() || self.consume_char() != '|' {
                    Err(CError {
                        desc: "Missing closing abs delimiter".to_string(),
                        span: (pre_pos, pre_pos),
                    })
                } else {
                    self.abs_level -= 1;
                    Ok(Ast {
                        val: Func(Abs),
                        branches: Unary(Box::new(eq)),
                    })
                }
            },
            Some(ch) if ch.is_alphabetic() => {
                let cnst = match self.consume_while(|ch| ch.is_alphabetic()).as_slice() {
                    "pi" => Pi,
                    "e" => E,
                    "phi" => Phi,
                    val => return Err(CError {
                        desc: format!("Invalid function or constant: {}", val),
                        span: (self.pos - val.len(), self.pos),
                    }),
                };
                Ok(Ast {
                    val: Const(cnst),
                    branches: Leaf,
                })
            },
            Some(ch) if ch.is_numeric() => {
                let num_str = self.consume_while(|ch| ch.is_numeric() || ch == '.');
                if let Ok(num) = num_str.parse::<f64>() {
                    Ok(Ast {
                        val: Num(num),
                        branches: Leaf,
                    })
                } else {
                    Err(CError {
                        desc: format!("Invalid number: {}", num_str),
                        span: (self.pos - num_str.len(), self.pos),
                    })
                }
            },
            Some(')') => {
                Err(CError {
                    desc: format!("Missing opening parentheses"),
                    span: (self.pos, self.pos),
                })
            },
            Some(ch) => {
                Err(CError {
                    desc: format!("Illegal character: {}", ch),
                    span: (self.pos, self.pos),
                })
            },
            _ => Err(CError {
                desc: format!("Unexpected end of equation"),
                span: (self.pos, self.pos),
            }),
        }
    }

    fn consume_function(&mut self) -> Option<AstFunc> {
        let pre_pos = self.pos;
        match self.consume_while(|ch| ch.is_alphabetic()).as_slice() {
            "sin" => Some(Sin),
            "cos" => Some(Cos),
            "tan" => Some(Tan),
            "asin" => Some(Asin),
            "acos" => Some(Acos),
            "atan" => Some(Atan),
            "sqrt" => Some(Sqrt),
            "qbrt" => Some(Qbrt),
            "abs" => Some(Abs),
            "exp" => Some(Exp),
            "ln" => Some(Ln),
            "log" => Some(Log),
            _ => {
                // no function found, so restore the previous position
                self.pos = pre_pos;
                None
            },
        }
    }

    /// Peeks at the next `char` and returns `Some` if one was found, or `None` if none are left
    fn peek_char(&self) -> Option<char> {
        if self.eof() {
            None
        } else {
            Some(self.input.char_at(self.pos).to_lowercase())
        }
    }

    /// Consumes a `char` - thereby advanding `pos` - and returns it
    ///
    /// # Panics
    /// This function panics if there are no more chars to consume
    fn consume_char(&mut self) -> char {
        let CharRange { ch, next } = self.input.char_range_at(self.pos);
        self.pos = next;
        ch.to_lowercase()
    }

    /// Consumes `char`s long as `pred` returns true and we are not eof
    ///
    /// The `char`s are returned as a `String`. Note that unlike `consume_char` this function will
    /// panic.
    fn consume_while<F>(&mut self, pred: F) -> String where F: Fn(char) -> bool {
        let mut out = String::new();
        loop {
            match self.peek_char() {
                Some(ch) if pred(ch) => out.push(self.consume_char()),
                _ => break,
            }
        }
        out
    }

    /// Consumes any current whitespace
    fn consume_whitespace(&mut self) {
        self.consume_while(|ch| ch.is_whitespace());
    }

    /// Returns true if we are the end of input
    fn eof(&self) -> bool {
        self.pos >= self.input.len()
    }
}<|endoftext|>


<commit_before>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs, so I listed it here
use pest::Parser;

use ast::Expression;

use std::f64;

const _GRAMMAR: &'static str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

pub fn parse(input: String) -> Expression {
    // TODO: Remove unwrap
    let mut pairs = ExpressionParser::parse_str(Rule::expression_literal, &input).unwrap();

    let first = pairs.nth(0).unwrap().into_inner().nth(0).unwrap();

    match first.as_rule() {
        Rule::boolean_literal =>
            Expression::Boolean(
                first.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::identifier_literal =>
            Expression::Identifier(first.into_span().as_str().to_string()),

        // TODO: For now, just conver the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                first.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&first.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&first.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&first.into_span().as_str()[2..], 16).unwrap())
            ),

        // Temporary
        _ => unreachable!()
    }
}<commit_msg>Parse now returns a result. Remove old parse struct for Result instead<commit_after>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs, so I listed it here
use pest::Parser;
use pest::iterators::Pair;
use pest::inputs::StrInput;

use ast::Expression;

use std::f64;

const _GRAMMAR: &'static str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule, StrInput>) -> Expression {
    match input.as_rule() {
        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just conver the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: String) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse_str(Rule::expression_literal, &input) {
        Ok(mut pair) =>
            Ok(parse_expression(pair.nth(0).unwrap().into_inner().nth(0).unwrap())),

        Err(e) => Err(format!("{}", e))
    }
}<|endoftext|>


<commit_before>use std::io;
pub struct Player<'a> {
    pub name: &'a str,
    pub health: i8,
    pub attack: i8,
    pub stamina: i8,
    pub dexterity: i8,
    pub mana: i8,
    pub vitality: i8,
    pub defense: i8,
    pub experience: i8,
    pub points: i8,
}

impl<'a> Default for Player<'a> {
    fn default () -> Player<'a> {
      Player {
          name: "Player",
          health: 100,
          attack: 5,
          stamina: 100,
          dexterity: 100,
          mana: 100,
          vitality: 100,
          defense: 100,
          experience: 0,
          points: 8}
    }
}

pub trait PlayerFunctionality {
    fn display_all_stats(&self);
    fn display_core_stats(&self);
    fn level_up(&mut self);
}

impl<'a> PlayerFunctionality for Player<'a> {
    fn display_all_stats(&self) {
        println!("Name:       {}", &self.name);
        println!("Health:     {}", &self.health);
        println!("Attack:     {}", &self.attack);
        println!("Stamina:    {}", &self.stamina);
        println!("Dexterity:  {}", &self.dexterity);
        println!("Mana:       {}", &self.mana);
        println!("Vitality:   {}", &self.vitality);
        println!("Defense     {}", &self.defense);
        println!("Experience: {}", &self.experience);
        println!("Points:     {}", &self.points);
    }
    fn display_core_stats(&self) {
        println!("1. Health:    {}", &self.health);
        println!("2. Attack:    {}", &self.attack);
        println!("3. Stamina:   {}", &self.stamina);
        println!("4. Dexterity: {}", &self.dexterity);
        println!("5. Mana:      {}", &self.mana);
        println!("6. Vitality:  {}", &self.vitality);
        println!("7. Defense    {}", &self.defense);
    }
    fn level_up(&mut self) {
        if &self.points == &0 {
            println!("You don't have any point's to spend leveling up.");
        } else {
            loop {
            println!("Level up points to spend: {}", &self.points);
            &self.display_core_stats();
            println!("Enter 0 to exit.");
            println!("Stat to level up? (1-7)");
            let mut input = String::new();
                match io::stdin().read_line(&mut input) {
                      Ok(_)   => {
                          let input: i8 = match input.trim().parse() {
                              Ok(i)  => i,
                              Err(_) => {
                                  println!("Can't parse {}", &input);
                                  continue;
                              }
                          };
                          match input {
                              0 => break,
                              1...7 => {
                                  println!("You have {} points to spend.", &self.points);
                                  println!("Increase {} stat by how much?", match input {
                                      1 => "Health",
                                      2 => "Attack",
                                      3 => "Stamina",
                                      4 => "Dexterity",
                                      5 => "Mana",
                                      6 => "Vitality",
                                      7 => "Defense",
                                      _ => "Unknown",
                                  });
                                  loop {
                                      let mut point_amount = String::new();
                                          match io::stdin().read_line(&mut point_amount) {
                                              Ok(_)   => {
                                                  let point_amount: i8 = match point_amount.trim().parse() {
                                                      Ok(i)  => i,
                                                      Err(_) => {
                                                          println!("Can't parse {}", &point_amount);
                                                          continue;
                                                      }
                                                  };
                                                  if &point_amount <= &self.points && &point_amount > &0 {
                                                      match input {
                                                          1 => self.health = &self.health + &point_amount,
                                                          2 => self.attack = &self.attack + &point_amount,
                                                          3 => self.stamina = &self.stamina + &point_amount,
                                                          4 => self.dexterity = &self.dexterity + &point_amount,
                                                          5 => self.mana = &self.mana + &point_amount,
                                                          6 => self.vitality = &self.vitality + &point_amount,
                                                          7 => self.defense = &self.defense + &point_amount,
                                                          _ => continue,
                                                      }
                                                      self.points = &self.points - &point_amount;
                                                      break;
                                                  } else {
                                                      println!("You have {} point(s), you can't spend {}. Sorry.", &self.points, &point_amount);
                                                  }
                                              }
                                          Err(_) => {
                                              println!("Can't parse {}", &point_amount);
                                          }
                                      }
                                  }
                              }
                              _ => {
                                  println!("{} is not a valid input (1-7)", &input);
                              }
                          }
                      }
                      Err(_) => {
                          println!("Can't parse {}", &input);
                      }
                };
            }
        }
    }
}
<commit_msg>changed minimum point use to 0<commit_after>use std::io;
pub struct Player<'a> {
    pub name: &'a str,
    pub health: i8,
    pub attack: i8,
    pub stamina: i8,
    pub dexterity: i8,
    pub mana: i8,
    pub vitality: i8,
    pub defense: i8,
    pub experience: i8,
    pub points: i8,
}

impl<'a> Default for Player<'a> {
    fn default () -> Player<'a> {
      Player {
          name: "Player",
          health: 100,
          attack: 5,
          stamina: 100,
          dexterity: 100,
          mana: 100,
          vitality: 100,
          defense: 100,
          experience: 0,
          points: 8}
    }
}

pub trait PlayerFunctionality {
    fn display_all_stats(&self);
    fn display_core_stats(&self);
    fn level_up(&mut self);
}

impl<'a> PlayerFunctionality for Player<'a> {
    fn display_all_stats(&self) {
        println!("Name:       {}", &self.name);
        println!("Health:     {}", &self.health);
        println!("Attack:     {}", &self.attack);
        println!("Stamina:    {}", &self.stamina);
        println!("Dexterity:  {}", &self.dexterity);
        println!("Mana:       {}", &self.mana);
        println!("Vitality:   {}", &self.vitality);
        println!("Defense     {}", &self.defense);
        println!("Experience: {}", &self.experience);
        println!("Points:     {}", &self.points);
    }
    fn display_core_stats(&self) {
        println!("1. Health:    {}", &self.health);
        println!("2. Attack:    {}", &self.attack);
        println!("3. Stamina:   {}", &self.stamina);
        println!("4. Dexterity: {}", &self.dexterity);
        println!("5. Mana:      {}", &self.mana);
        println!("6. Vitality:  {}", &self.vitality);
        println!("7. Defense    {}", &self.defense);
    }
    fn level_up(&mut self) {
        if &self.points == &0 {
            println!("You don't have any point's to spend leveling up.");
        } else {
            loop {
            println!("Level up points to spend: {}", &self.points);
            &self.display_core_stats();
            println!("Enter 0 to exit.");
            println!("Stat to level up? (1-7)");
            let mut input = String::new();
                match io::stdin().read_line(&mut input) {
                      Ok(_)   => {
                          let input: i8 = match input.trim().parse() {
                              Ok(i)  => i,
                              Err(_) => {
                                  println!("Can't parse {}", &input);
                                  continue;
                              }
                          };
                          match input {
                              0 => break,
                              1...7 => {
                                  println!("You have {} points to spend.", &self.points);
                                  println!("Increase {} stat by how much?", match input {
                                      1 => "Health",
                                      2 => "Attack",
                                      3 => "Stamina",
                                      4 => "Dexterity",
                                      5 => "Mana",
                                      6 => "Vitality",
                                      7 => "Defense",
                                      _ => "Unknown",
                                  });
                                  loop {
                                      let mut point_amount = String::new();
                                          match io::stdin().read_line(&mut point_amount) {
                                              Ok(_)   => {
                                                  let point_amount: i8 = match point_amount.trim().parse() {
                                                      Ok(i)  => i,
                                                      Err(_) => {
                                                          println!("Can't parse {}", &point_amount);
                                                          continue;
                                                      }
                                                  };
                                                  if &point_amount <= &self.points && &point_amount >= &0 {
                                                      match input {
                                                          1 => self.health = &self.health + &point_amount,
                                                          2 => self.attack = &self.attack + &point_amount,
                                                          3 => self.stamina = &self.stamina + &point_amount,
                                                          4 => self.dexterity = &self.dexterity + &point_amount,
                                                          5 => self.mana = &self.mana + &point_amount,
                                                          6 => self.vitality = &self.vitality + &point_amount,
                                                          7 => self.defense = &self.defense + &point_amount,
                                                          _ => continue,
                                                      }
                                                      self.points = &self.points - &point_amount;
                                                      break;
                                                  } else {
                                                      println!("You have {} point(s), you can't spend {}. Sorry.", &self.points, &point_amount);
                                                  }
                                              }
                                          Err(_) => {
                                              println!("Can't parse {}", &point_amount);
                                          }
                                      }
                                  }
                              }
                              _ => {
                                  println!("{} is not a valid input (1-7)", &input);
                              }
                          }
                      }
                      Err(_) => {
                          println!("Can't parse {}", &input);
                      }
                };
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
use memchr::memchr;

/// A prefix extracted from a compiled regular expression.
///
/// A regex prefix is a set of literal strings that *must* be matched at the
/// beginning of a regex in order for the entire regex to match.
///
/// There are a variety of ways to efficiently scan the search text for a
/// prefix. Currently, there are three implemented:
///
/// 1. The prefix is a single byte. Just use memchr.
/// 2. If the prefix is a set of two or more single byte prefixes, then
///    a single sparse map is created. Checking if there is a match is a lookup
///    in this map for each byte in the search text.
/// 3. In all other cases, build an Aho-Corasick automaton.
///
/// It's possible that there's room here for other substring algorithms,
/// such as Boyer-Moore for single-set prefixes greater than 1, or Rabin-Karp
/// for small sets of same-length prefixes.
#[derive(Clone)]
pub enum Prefix {
    /// No prefixes. (Never advances through the input.)
    Empty,
    /// A single byte prefix.
    Byte(u8),
    /// A set of two or more single byte prefixes.
    /// This could be reduced to a bitset, which would use only 8 bytes,
    /// but I don't think we care.
    Bytes {
        chars: Vec<u8>,
        sparse: Vec<bool>,
    },
    Single(SingleSearch),
    /// A full Aho-Corasick DFA automaton.
    Automaton(FullAcAutomaton<String>),
}

impl Prefix {
    /// Create a new prefix matching machine.
    pub fn new(mut pfxs: Vec<String>) -> Prefix {
        if pfxs.len() == 0 || pfxs[0].len() == 0 {
            Prefix::Empty
        } else if pfxs.len() == 1 && pfxs[0].len() == 1 {
            Prefix::Byte(pfxs[0].as_bytes()[0])
        } else if pfxs.len() >= 2 && pfxs.iter().all(|s| s.len() == 1) {
            let mut set = vec![false; 256];
            let mut chars = vec![];
            for p in pfxs {
                chars.push(p.as_bytes()[0]);
                set[p.as_bytes()[0] as usize] = true;
            }
            Prefix::Bytes { chars: chars, sparse: set }
        } else if pfxs.len() == 1 {
            Prefix::Single(SingleSearch::new(pfxs.pop().unwrap()))
        } else {
            Prefix::Automaton(AcAutomaton::new(pfxs).into_full())
        }
    }

    /// Find the position of a prefix in `haystack` if it exists.
    ///
    /// In the matching engines, we only actually need the starting index
    /// because the prefix is used to only skip ahead---the matching engine
    /// still needs to run over the prefix input. However, we return the ending
    /// location as well in case the prefix corresponds to the entire regex,
    /// in which case, you need the end of the match.
    pub fn find(&self, haystack: &str) -> Option<(usize, usize)> {
        use self::Prefix::*;
        match *self {
            Empty => Some((0, 0)),
            Byte(b) => memchr(b, haystack.as_bytes()).map(|i| (i, i+1)),
            Bytes { ref sparse, .. } => {
                find_singles(sparse, haystack.as_bytes())
            }
            Single(ref searcher) => {
                searcher.find(haystack).map(|i| (i, i + searcher.pat.len()))
            }
            Automaton(ref aut) => {
                aut.find(haystack).next().map(|m| (m.start, m.end))
            }
        }
    }

    /// Returns true iff this prefix is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of prefixes in this machine.
    pub fn len(&self) -> usize {
        match *self {
            Prefix::Empty => 0,
            Prefix::Byte(_) => 1,
            Prefix::Bytes { ref chars, .. } => chars.len(),
            Prefix::Single(_) => 1,
            Prefix::Automaton(ref aut) => aut.len(),
        }
    }

    /// Returns true iff the prefix match preserves priority.
    ///
    /// For example, given the alternation `ab|a` and the target string `ab`,
    /// does the prefix machine guarantee that `ab` will match? (A full
    /// Aho-Corasick automaton does not!)
    pub fn preserves_priority(&self) -> bool {
        match *self {
            Prefix::Empty => true,
            Prefix::Byte(_) => true,
            Prefix::Bytes{..} => true,
            Prefix::Single(_) => true,
            Prefix::Automaton(ref aut) => {
                // Okay, so the automaton can respect priority in one
                // particular case: when every pattern is of the same length.
                // The trick is that the automaton will report the leftmost
                // match, which in this case, corresponds to the correct
                // match for the regex engine. If any other alternate matches
                // at the same position, then they must be exactly equivalent.

                // Guaranteed at least one prefix by construction, so use
                // that for the length.
                aut.patterns().iter().all(|p| p.len() == aut.pattern(0).len())
            }
        }
    }

    /// Returns all of the prefixes participating in this machine.
    ///
    /// For debug/testing only! (It allocates.)
    #[allow(dead_code)]
    pub fn prefixes(&self) -> Vec<String> {
        match *self {
            Prefix::Empty => vec![],
            Prefix::Byte(b) => vec![format!("{}", b as char)],
            Prefix::Bytes { ref chars, .. } => {
                chars.iter().map(|&b| format!("{}", b as char)).collect()
            }
            Prefix::Single(ref searcher) => vec![searcher.pat.clone()],
            Prefix::Automaton(ref aut) => aut.patterns().to_vec(),
        }
    }
}

/// Provides an implementation of fast subtring search.
///
/// In particular, this uses Boyer-Moore-Horspool with Tim Raita's twist:
/// https://en.wikipedia.org/wiki/Raita_Algorithm
///
/// I'm skeptical of the utility here, because benchmarks suggest that it is
/// difficult to beat Aho-Corasick on random text. Namely, both algorithms are
/// dominated by the performance of `memchr` for the leading byte prefix.
/// With that said, BMH does seem to surpass AC when the search text gets
/// longer (see the `easy0_1MB` vs. `easy1_1MB` benchmarks).
///
/// More analysis needs to be done to test this on different search texts.
#[derive(Clone, Debug)]
struct SingleSearch {
    pat: String,
    shift: Vec<usize>,
}

impl SingleSearch {
    fn new(pat: String) -> SingleSearch {
        assert!(pat.len() >= 1);
        let mut shift = vec![pat.len(); 256];
        for i in 0..(pat.len() - 1) {
            shift[pat.as_bytes()[i] as usize] = pat.len() - i - 1;
        }
        SingleSearch {
            pat: pat,
            shift: shift,
        }
    }

    fn find(&self, haystack: &str) -> Option<usize> {
        let pat = self.pat.as_bytes();
        let haystack = haystack.as_bytes();
        if haystack.len() < pat.len() {
            return None;
        }
        let mut i = match memchr(pat[0], haystack) {
            None => return None,
            Some(i) => i,
        };
        while i <= haystack.len() - pat.len() {
            let b = haystack[i + pat.len() - 1];
            if b == pat[pat.len() - 1]
               && haystack[i] == pat[0]
               && haystack[i + (pat.len() / 2)] == pat[pat.len() / 2]
               && pat == &haystack[i..i + pat.len()] {
                return Some(i);
            }
            i += self.shift[b as usize];
            i += match memchr(pat[0], &haystack[i..]) {
                None => return None,
                Some(i) => i,
            };
        }
        None
    }
}

/// A quick scan for multiple single byte prefixes using a sparse map.
fn find_singles(sparse: &[bool], haystack: &[u8]) -> Option<(usize, usize)> {
    // TODO: Improve this with ideas found in jetscii crate.
    for (hi, &b) in haystack.iter().enumerate() {
        if sparse[b as usize] {
            return Some((hi, hi+1));
        }
    }
    None
}

impl fmt::Debug for Prefix {
    #[allow(deprecated)] // connect => join in 1.3
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Prefix::Empty => write!(f, "Empty"),
            Prefix::Byte(b) => write!(f, "{:?}", b as char),
            Prefix::Bytes { ref chars, .. } => {
                let chars: Vec<String> =
                    chars.iter()
                         .map(|&c| format!("{:?}", c as char))
                         .collect();
                write!(f, "{}", chars.connect(", "))
            }
            Prefix::Single(ref searcher) => write!(f, "{:?}", searcher),
            Prefix::Automaton(ref aut) => write!(f, "{:?}", aut),
        }
    }
}
<commit_msg>Avoid repeated memchr in SingleSearch<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
use memchr::memchr;

/// A prefix extracted from a compiled regular expression.
///
/// A regex prefix is a set of literal strings that *must* be matched at the
/// beginning of a regex in order for the entire regex to match.
///
/// There are a variety of ways to efficiently scan the search text for a
/// prefix. Currently, there are three implemented:
///
/// 1. The prefix is a single byte. Just use memchr.
/// 2. If the prefix is a set of two or more single byte prefixes, then
///    a single sparse map is created. Checking if there is a match is a lookup
///    in this map for each byte in the search text.
/// 3. In all other cases, build an Aho-Corasick automaton.
///
/// It's possible that there's room here for other substring algorithms,
/// such as Boyer-Moore for single-set prefixes greater than 1, or Rabin-Karp
/// for small sets of same-length prefixes.
#[derive(Clone)]
pub enum Prefix {
    /// No prefixes. (Never advances through the input.)
    Empty,
    /// A single byte prefix.
    Byte(u8),
    /// A set of two or more single byte prefixes.
    /// This could be reduced to a bitset, which would use only 8 bytes,
    /// but I don't think we care.
    Bytes {
        chars: Vec<u8>,
        sparse: Vec<bool>,
    },
    Single(SingleSearch),
    /// A full Aho-Corasick DFA automaton.
    Automaton(FullAcAutomaton<String>),
}

impl Prefix {
    /// Create a new prefix matching machine.
    pub fn new(mut pfxs: Vec<String>) -> Prefix {
        if pfxs.len() == 0 || pfxs[0].len() == 0 {
            Prefix::Empty
        } else if pfxs.len() == 1 && pfxs[0].len() == 1 {
            Prefix::Byte(pfxs[0].as_bytes()[0])
        } else if pfxs.len() >= 2 && pfxs.iter().all(|s| s.len() == 1) {
            let mut set = vec![false; 256];
            let mut chars = vec![];
            for p in pfxs {
                chars.push(p.as_bytes()[0]);
                set[p.as_bytes()[0] as usize] = true;
            }
            Prefix::Bytes { chars: chars, sparse: set }
        } else if pfxs.len() == 1 {
            Prefix::Single(SingleSearch::new(pfxs.pop().unwrap()))
        } else {
            Prefix::Automaton(AcAutomaton::new(pfxs).into_full())
        }
    }

    /// Find the position of a prefix in `haystack` if it exists.
    ///
    /// In the matching engines, we only actually need the starting index
    /// because the prefix is used to only skip ahead---the matching engine
    /// still needs to run over the prefix input. However, we return the ending
    /// location as well in case the prefix corresponds to the entire regex,
    /// in which case, you need the end of the match.
    pub fn find(&self, haystack: &str) -> Option<(usize, usize)> {
        use self::Prefix::*;
        match *self {
            Empty => Some((0, 0)),
            Byte(b) => memchr(b, haystack.as_bytes()).map(|i| (i, i+1)),
            Bytes { ref sparse, .. } => {
                find_singles(sparse, haystack.as_bytes())
            }
            Single(ref searcher) => {
                searcher.find(haystack).map(|i| (i, i + searcher.pat.len()))
            }
            Automaton(ref aut) => {
                aut.find(haystack).next().map(|m| (m.start, m.end))
            }
        }
    }

    /// Returns true iff this prefix is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of prefixes in this machine.
    pub fn len(&self) -> usize {
        match *self {
            Prefix::Empty => 0,
            Prefix::Byte(_) => 1,
            Prefix::Bytes { ref chars, .. } => chars.len(),
            Prefix::Single(_) => 1,
            Prefix::Automaton(ref aut) => aut.len(),
        }
    }

    /// Returns true iff the prefix match preserves priority.
    ///
    /// For example, given the alternation `ab|a` and the target string `ab`,
    /// does the prefix machine guarantee that `ab` will match? (A full
    /// Aho-Corasick automaton does not!)
    pub fn preserves_priority(&self) -> bool {
        match *self {
            Prefix::Empty => true,
            Prefix::Byte(_) => true,
            Prefix::Bytes{..} => true,
            Prefix::Single(_) => true,
            Prefix::Automaton(ref aut) => {
                // Okay, so the automaton can respect priority in one
                // particular case: when every pattern is of the same length.
                // The trick is that the automaton will report the leftmost
                // match, which in this case, corresponds to the correct
                // match for the regex engine. If any other alternate matches
                // at the same position, then they must be exactly equivalent.

                // Guaranteed at least one prefix by construction, so use
                // that for the length.
                aut.patterns().iter().all(|p| p.len() == aut.pattern(0).len())
            }
        }
    }

    /// Returns all of the prefixes participating in this machine.
    ///
    /// For debug/testing only! (It allocates.)
    #[allow(dead_code)]
    pub fn prefixes(&self) -> Vec<String> {
        match *self {
            Prefix::Empty => vec![],
            Prefix::Byte(b) => vec![format!("{}", b as char)],
            Prefix::Bytes { ref chars, .. } => {
                chars.iter().map(|&b| format!("{}", b as char)).collect()
            }
            Prefix::Single(ref searcher) => vec![searcher.pat.clone()],
            Prefix::Automaton(ref aut) => aut.patterns().to_vec(),
        }
    }
}

/// Provides an implementation of fast subtring search.
///
/// In particular, this uses Boyer-Moore-Horspool with Tim Raita's twist:
/// https://en.wikipedia.org/wiki/Raita_Algorithm
///
/// I'm skeptical of the utility here, because benchmarks suggest that it is
/// difficult to beat Aho-Corasick on random text. Namely, both algorithms are
/// dominated by the performance of `memchr` for the leading byte prefix.
/// With that said, BMH does seem to surpass AC when the search text gets
/// longer (see the `easy0_1MB` vs. `easy1_1MB` benchmarks).
///
/// More analysis needs to be done to test this on different search texts.
#[derive(Clone, Debug)]
struct SingleSearch {
    pat: String,
    shift: Vec<usize>,
}

impl SingleSearch {
    fn new(pat: String) -> SingleSearch {
        assert!(pat.len() >= 1);
        let mut shift = vec![pat.len(); 256];
        for i in 0..(pat.len() - 1) {
            shift[pat.as_bytes()[i] as usize] = pat.len() - i - 1;
        }
        SingleSearch {
            pat: pat,
            shift: shift,
        }
    }

    fn find(&self, haystack: &str) -> Option<usize> {
        let pat = self.pat.as_bytes();
        let haystack = haystack.as_bytes();
        if haystack.len() < pat.len() {
            return None;
        }
        let mut i = match memchr(pat[0], haystack) {
            None => return None,
            Some(i) => i,
        };
        while i <= haystack.len() - pat.len() {
            let b = haystack[i + pat.len() - 1];
            if b == pat[pat.len() - 1]
               && haystack[i] == pat[0]
               && haystack[i + (pat.len() / 2)] == pat[pat.len() / 2]
               && pat == &haystack[i..i + pat.len()] {
                return Some(i);
            }
            i += self.shift[b as usize];
        }
        None
    }
}

/// A quick scan for multiple single byte prefixes using a sparse map.
fn find_singles(sparse: &[bool], haystack: &[u8]) -> Option<(usize, usize)> {
    // TODO: Improve this with ideas found in jetscii crate.
    for (hi, &b) in haystack.iter().enumerate() {
        if sparse[b as usize] {
            return Some((hi, hi+1));
        }
    }
    None
}

impl fmt::Debug for Prefix {
    #[allow(deprecated)] // connect => join in 1.3
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Prefix::Empty => write!(f, "Empty"),
            Prefix::Byte(b) => write!(f, "{:?}", b as char),
            Prefix::Bytes { ref chars, .. } => {
                let chars: Vec<String> =
                    chars.iter()
                         .map(|&c| format!("{:?}", c as char))
                         .collect();
                write!(f, "{}", chars.connect(", "))
            }
            Prefix::Single(ref searcher) => write!(f, "{:?}", searcher),
            Prefix::Automaton(ref aut) => write!(f, "{:?}", aut),
        }
    }
}
<|endoftext|>


<commit_before>use libc::*;

use std::collections::RingBuf;

use std::num::*;

use input::*;
use controls::*;
use constants::*;
use signal::*;
use types::*;
use ioctl::*;

pub struct LineReader {
    pub line: InputLine,
    pub controls: Controls,
    pub bpart: String,
    pub escape: bool,
    pub escape_chars: String,
    pub finished: bool,
    pub eof: bool,
    pub restarted: bool,
    history: RingBuf<InputLine>,
    bhistory: Vec<InputLine>,
    first_rsave: bool
}

impl LineReader {
    pub fn new() -> LineReader {
        LineReader {
            line: InputLine::new(),
            controls: Controls::new(),
            bpart: String::new(),
            escape: false,
            escape_chars: String::new(),
            finished: false,
            eof: false,
            restarted: false,
            history: RingBuf::new(),
            bhistory: vec![],
            first_rsave: false
        }
    }

    pub fn clear(&mut self) {
        self.line.clear();
        self.bpart.clear();
        self.escape = false;
        self.escape_chars.clear();
        self.finished = false;
        self.eof = false;
        self.restarted = false;
        self.first_rsave = false;
    }

    pub fn restart(&mut self) {
        self.finished = false;
        self.eof = false;
        self.restarted = true;
    }

    fn handle_signal(&mut self, set:&SigSet) {
        let sig = match signal_wait_set(set, None) {
            Err(e) => panic!("Didn't get signal: {}", e),
            Ok(s) => s
        };
        match sig.signo {
            SIGINT => {
                self.controls.outs("\nInterrupt");
                self.clear();
                self.finished = true;
            },
            SIGWINCH => {
                match term_winsize() {
                    Err(e) => self.controls.errf(format_args!("\nCouldn't get terminal size: {}\n", e)),
                    Ok(size) => self.controls.update_size(size)
                }
                self.controls.query_cursor();
            },
            s => panic!("Caught bad signal: {}", s)
        }
    }

    fn read_character(&mut self) {
        match self.controls.read() {
            Err(e) => panic!("Error: {}", e),
            Ok(ch) => match
                if self.escape {
                    self.handle_escape(ch)
                } else if ch.is_control() {
                    self.handle_control(ch)
                } else {
                    self.handle_ch(ch)
                } {
                    false => self.controls.bell(),
                    _ => {}
                }
        }
    }

    pub fn read_line(&mut self) -> Option<InputValue> {
        // these panic because if we can't do this we can't run wash at all
        let mut set = tryp!(empty_sigset());
        tryp!(sigset_add(&mut set, SIGINT));
        tryp!(sigset_add(&mut set, SIGWINCH));
        let sigfd = tryp!(signal_fd(&set));
        // the file descriptors we want to watch
        let read = vec![sigfd, STDIN];
        let emvc = vec![];
        let mut sread;
        let old_set = tryp!(signal_proc_mask(SIG_BLOCK, &set));
        match term_winsize() {
            Err(e) => self.controls.errf(format_args!("\nCouldn't get terminal size: {}\n", e)),
            Ok(size) => self.controls.update_size(size)
        }
        // update cursor position before anything
        self.controls.clear_rows();
        self.controls.query_cursor();
        while !self.finished && !self.eof {
            sread = match select(&read, &emvc, &emvc,
                                 None, &set) {
                Err(_) => continue, // try again
                Ok(v) => v
            };
            if sread.len() == 2 {
                // prefer SIGINT
                self.handle_signal(&set);
            } else {
                match sread.pop() {
                    None => self.handle_signal(&set),
                    Some(ref fd) if *fd == sigfd =>
                        self.handle_signal(&set),
                    Some(ref fd) if *fd == STDIN =>
                        self.read_character(),
                    _ => panic!("select returned unknown file descriptor")
                }
            }
            self.controls.flush();
        }
        tryp!(signal_proc_mask(SIG_SETMASK, &old_set));
        if self.eof {
            return None;
        } else {
            // push back history onto history
            if !self.bhistory.is_empty() {
                self.history.push_front(self.line.clone());
            }
            let mut popped;
            while !self.bhistory.is_empty() {
                popped = self.bhistory.pop().unwrap();
                if !popped.is_empty() {
                    self.history.push_front(popped);
                }
            }
            self.history.push_front(self.line.clone());
            while self.history.len() > HISTORY_SIZE {
                self.history.pop_back();
            }
            return self.line.process();
        }
    }

    pub fn draw_part(&mut self) -> usize {
        // quick out if part is empty
        if self.line.part.is_empty() {
            return 0;
        }
        if self.bpart.is_empty() {
            // only calculate bpart when it needs to be recalculated
            let mut cpart = self.line.part.clone();
            loop {
                match cpart.pop() {
                    Some(c) => self.bpart.push(c),
                    None => break
                }
            }
        }
        let splits:Vec<&str> = NL_REGEX.split(self.bpart.as_slice()).collect();
        if self.controls.grow_check(splits[0].len()) {
            let old = self.controls.get_pos();
            for part in splits.iter() {
                if self.controls.grow_check(part.len()) {
                    let crow = self.controls.get_row();
                    let total = crow + part.len();
                    for row in range(crow + 1,
                                     crow + total/self.controls.width() + 1) {
                        self.controls.clear_line();
                        self.controls.move_to(Position {
                            col: 1,
                            row: row
                        });
                    }
                    self.controls.clear_line();
                    self.controls.next_start();
                } else {
                    self.controls.clear_line();
                    self.controls.next_start();
                }
            }
            self.controls.move_to(old);
            self.controls.outs(self.bpart.as_slice());
            return self.bpart.len();
        } else {
            // change doesn't affect anything other than this line
            self.controls.outs(splits[0]);
            return splits[0].len();
        }
    }

    pub fn idraw_part(&mut self) {
        // in-place draw of the line part
        let count = self.draw_part();
        self.controls.cursors_left(count);
    }

    pub fn handle_ch(&mut self, ch:char) -> bool {
        if self.line.push(ch) {
            self.controls.outc(ch);
            self.idraw_part();
            return true;
        } else {
            return false;
        }
    }

    pub fn handle_control(&mut self, ch:char) -> bool {
        match ch {
            CEOF => {
                if self.line.is_empty() {
                    self.finished = true;
                    self.eof = true;
                }
            },
            NL => {
                if !self.line.push(NL) {
                    self.finished = true;
                } else {
                    self.controls.outc(NL);
                }
            },
            ESC => {
                self.escape = true;
                self.escape_chars = String::new();
            },
            DEL => {
                match self.line.pop() {
                    None => return false,
                    Some(_) => {
                        self.controls.del();
                        let count = self.draw_part();
                        self.controls.outc(SPC);
                        self.controls.del();
                        self.controls.cursors_left(count);
                    }
                }
            },
            CTA => {
                // C-a
                self.controls.cursors_left(self.line.fpart.len());
                loop {
                    match self.line.fpart.pop() {
                        Some(ch) => self.line.part.push(ch),
                        None => break
                    }
                }
                self.line.fpart.clear();
                self.line.back.clear();
                self.line.front.clear();
                self.line.back.push(InputValue::Long(vec![]));
                self.bpart.clear();
            },
            CTE => {
                // C-e
                self.controls.cursors_right(self.line.part.len());
                while self.line.right() {}
            },
            CTK => self.clear_line(),
            _ => return false
        }
        return true;
    }

    fn clear_line(&mut self) {
        self.controls.clear_line_to(self.line.part.len());
        self.line.part.clear();
        self.bpart.clear();
    }

    fn clear_entire_line(&mut self) {
        self.controls.cursors_left(self.line.fpart.len());
        self.controls.clear_line_to(self.line.fpart.len() + self.line.part.len());
        self.bpart.clear();
        self.line.clear();
    }

    pub fn handle_escape(&mut self, ch:char) -> bool {
        match ch {
            ESC => {
                self.escape = false;
            },
            ANSI => {
                if self.escape_chars.is_empty() {
                    self.escape_chars.push(ANSI);
                } else {
                    self.escape = false;
                }
            },
            'D' => {
                // left
                self.escape = false;
                if self.line.left() {
                    self.bpart.clear();
                    self.controls.cursor_left();
                } else {
                    return false;
                }
            },
            'C' => {
                // right
                self.escape = false;
                if self.line.right() {
                    self.bpart.clear();
                    self.controls.cursor_right();
                } else {
                    return false;
                }
            },
            'B' => {
                // down
                self.escape = false;
                match self.bhistory.pop() {
                    None if !self.line.is_empty() => {
                        self.history.push_front(self.line.clone());
                        self.clear_entire_line();
                    },
                    None => return false,
                    Some(line) => {
                        self.history.push_front(self.line.clone());
                        self.clear_entire_line();
                        self.line = line;
                        self.controls.outs(self.line.fpart.as_slice());
                        self.bpart.clear();
                        self.idraw_part();
                    }
                }
            },
            'A' => {
                // up
                self.escape = false;
                match self.history.pop_front() {
                    None => return false,
                    Some(line) => {
                        self.bhistory.push(self.line.clone());
                        self.clear_entire_line();
                        self.line = line;
                        self.controls.outs(self.line.fpart.as_slice());
                        self.bpart.clear();
                        self.idraw_part();
                    }
                }
            },
            'R' => {
                // cursor position
                self.escape = false;
                if !PPOS_REGEX.is_match(self.escape_chars.as_slice()) {
                    return false;
                } else {
                    let caps = PPOS_REGEX.captures(self.escape_chars.as_slice()).unwrap();
                    let row = caps.at(1).unwrap();
                    let col = caps.at(2).unwrap();
                    let pointer = Position {
                        row: match from_str_radix(row, 10) {
                            Err(_) => return false,
                            Ok(v) => v
                        },
                        col: match from_str_radix(col, 10) {
                            Err(_) => return false,
                            Ok(v) => v
                        }
                    };
                    self.controls.update_cursor(pointer);
                    if !self.first_rsave {
                        self.controls.save_row(pointer.col);
                        self.controls.update_line(pointer.col);
                        self.first_rsave = true;
                    }
                }
            },
            ch => {
                self.escape_chars.push(ch);
                if self.escape_chars.len() > MAX_ESCAPE {
                    self.escape = false;
                    return false;
                }
            }
        }
        return true;
    }
}

<commit_msg>Move to end of input before printing Interrupt<commit_after>use libc::*;

use std::collections::RingBuf;

use std::num::*;

use input::*;
use controls::*;
use constants::*;
use signal::*;
use types::*;
use ioctl::*;

pub struct LineReader {
    pub line: InputLine,
    pub controls: Controls,
    pub bpart: String,
    pub escape: bool,
    pub escape_chars: String,
    pub finished: bool,
    pub eof: bool,
    pub restarted: bool,
    history: RingBuf<InputLine>,
    bhistory: Vec<InputLine>,
    first_rsave: bool
}

impl LineReader {
    pub fn new() -> LineReader {
        LineReader {
            line: InputLine::new(),
            controls: Controls::new(),
            bpart: String::new(),
            escape: false,
            escape_chars: String::new(),
            finished: false,
            eof: false,
            restarted: false,
            history: RingBuf::new(),
            bhistory: vec![],
            first_rsave: false
        }
    }

    pub fn clear(&mut self) {
        self.line.clear();
        self.bpart.clear();
        self.escape = false;
        self.escape_chars.clear();
        self.finished = false;
        self.eof = false;
        self.restarted = false;
        self.first_rsave = false;
    }

    pub fn restart(&mut self) {
        self.finished = false;
        self.eof = false;
        self.restarted = true;
    }

    fn handle_signal(&mut self, set:&SigSet) {
        let sig = match signal_wait_set(set, None) {
            Err(e) => panic!("Didn't get signal: {}", e),
            Ok(s) => s
        };
        match sig.signo {
            SIGINT => {
                self.controls.cursors_right(self.line.part.len());
                self.controls.outs("\nInterrupt");
                self.clear();
                self.finished = true;
            },
            SIGWINCH => {
                match term_winsize() {
                    Err(e) => self.controls.errf(format_args!("\nCouldn't get terminal size: {}\n", e)),
                    Ok(size) => self.controls.update_size(size)
                }
                self.controls.query_cursor();
            },
            s => panic!("Caught bad signal: {}", s)
        }
    }

    fn read_character(&mut self) {
        match self.controls.read() {
            Err(e) => panic!("Error: {}", e),
            Ok(ch) => match
                if self.escape {
                    self.handle_escape(ch)
                } else if ch.is_control() {
                    self.handle_control(ch)
                } else {
                    self.handle_ch(ch)
                } {
                    false => self.controls.bell(),
                    _ => {}
                }
        }
    }

    pub fn read_line(&mut self) -> Option<InputValue> {
        // these panic because if we can't do this we can't run wash at all
        let mut set = tryp!(empty_sigset());
        tryp!(sigset_add(&mut set, SIGINT));
        tryp!(sigset_add(&mut set, SIGWINCH));
        let sigfd = tryp!(signal_fd(&set));
        // the file descriptors we want to watch
        let read = vec![sigfd, STDIN];
        let emvc = vec![];
        let mut sread;
        let old_set = tryp!(signal_proc_mask(SIG_BLOCK, &set));
        match term_winsize() {
            Err(e) => self.controls.errf(format_args!("\nCouldn't get terminal size: {}\n", e)),
            Ok(size) => self.controls.update_size(size)
        }
        // update cursor position before anything
        self.controls.clear_rows();
        self.controls.query_cursor();
        while !self.finished && !self.eof {
            sread = match select(&read, &emvc, &emvc,
                                 None, &set) {
                Err(_) => continue, // try again
                Ok(v) => v
            };
            if sread.len() == 2 {
                // prefer SIGINT
                self.handle_signal(&set);
            } else {
                match sread.pop() {
                    None => self.handle_signal(&set),
                    Some(ref fd) if *fd == sigfd =>
                        self.handle_signal(&set),
                    Some(ref fd) if *fd == STDIN =>
                        self.read_character(),
                    _ => panic!("select returned unknown file descriptor")
                }
            }
            self.controls.flush();
        }
        tryp!(signal_proc_mask(SIG_SETMASK, &old_set));
        if self.eof {
            return None;
        } else {
            // push back history onto history
            if !self.bhistory.is_empty() {
                self.history.push_front(self.line.clone());
            }
            let mut popped;
            while !self.bhistory.is_empty() {
                popped = self.bhistory.pop().unwrap();
                if !popped.is_empty() {
                    self.history.push_front(popped);
                }
            }
            self.history.push_front(self.line.clone());
            while self.history.len() > HISTORY_SIZE {
                self.history.pop_back();
            }
            return self.line.process();
        }
    }

    pub fn draw_part(&mut self) -> usize {
        // quick out if part is empty
        if self.line.part.is_empty() {
            return 0;
        }
        if self.bpart.is_empty() {
            // only calculate bpart when it needs to be recalculated
            let mut cpart = self.line.part.clone();
            loop {
                match cpart.pop() {
                    Some(c) => self.bpart.push(c),
                    None => break
                }
            }
        }
        let splits:Vec<&str> = NL_REGEX.split(self.bpart.as_slice()).collect();
        if self.controls.grow_check(splits[0].len()) {
            let old = self.controls.get_pos();
            for part in splits.iter() {
                if self.controls.grow_check(part.len()) {
                    let crow = self.controls.get_row();
                    let total = crow + part.len();
                    for row in range(crow + 1,
                                     crow + total/self.controls.width() + 1) {
                        self.controls.clear_line();
                        self.controls.move_to(Position {
                            col: 1,
                            row: row
                        });
                    }
                    self.controls.clear_line();
                    self.controls.next_start();
                } else {
                    self.controls.clear_line();
                    self.controls.next_start();
                }
            }
            self.controls.move_to(old);
            self.controls.outs(self.bpart.as_slice());
            return self.bpart.len();
        } else {
            // change doesn't affect anything other than this line
            self.controls.outs(splits[0]);
            return splits[0].len();
        }
    }

    pub fn idraw_part(&mut self) {
        // in-place draw of the line part
        let count = self.draw_part();
        self.controls.cursors_left(count);
    }

    pub fn handle_ch(&mut self, ch:char) -> bool {
        if self.line.push(ch) {
            self.controls.outc(ch);
            self.idraw_part();
            return true;
        } else {
            return false;
        }
    }

    pub fn handle_control(&mut self, ch:char) -> bool {
        match ch {
            CEOF => {
                if self.line.is_empty() {
                    self.finished = true;
                    self.eof = true;
                }
            },
            NL => {
                if !self.line.push(NL) {
                    self.finished = true;
                } else {
                    self.controls.outc(NL);
                }
            },
            ESC => {
                self.escape = true;
                self.escape_chars = String::new();
            },
            DEL => {
                match self.line.pop() {
                    None => return false,
                    Some(_) => {
                        self.controls.del();
                        let count = self.draw_part();
                        self.controls.outc(SPC);
                        self.controls.del();
                        self.controls.cursors_left(count);
                    }
                }
            },
            CTA => {
                // C-a
                self.controls.cursors_left(self.line.fpart.len());
                loop {
                    match self.line.fpart.pop() {
                        Some(ch) => self.line.part.push(ch),
                        None => break
                    }
                }
                self.line.fpart.clear();
                self.line.back.clear();
                self.line.front.clear();
                self.line.back.push(InputValue::Long(vec![]));
                self.bpart.clear();
            },
            CTE => {
                // C-e
                self.controls.cursors_right(self.line.part.len());
                while self.line.right() {}
            },
            CTK => self.clear_line(),
            _ => return false
        }
        return true;
    }

    fn clear_line(&mut self) {
        self.controls.clear_line_to(self.line.part.len());
        self.line.part.clear();
        self.bpart.clear();
    }

    fn clear_entire_line(&mut self) {
        self.controls.cursors_left(self.line.fpart.len());
        self.controls.clear_line_to(self.line.fpart.len() + self.line.part.len());
        self.bpart.clear();
        self.line.clear();
    }

    pub fn handle_escape(&mut self, ch:char) -> bool {
        match ch {
            ESC => {
                self.escape = false;
            },
            ANSI => {
                if self.escape_chars.is_empty() {
                    self.escape_chars.push(ANSI);
                } else {
                    self.escape = false;
                }
            },
            'D' => {
                // left
                self.escape = false;
                if self.line.left() {
                    self.bpart.clear();
                    self.controls.cursor_left();
                } else {
                    return false;
                }
            },
            'C' => {
                // right
                self.escape = false;
                if self.line.right() {
                    self.bpart.clear();
                    self.controls.cursor_right();
                } else {
                    return false;
                }
            },
            'B' => {
                // down
                self.escape = false;
                match self.bhistory.pop() {
                    None if !self.line.is_empty() => {
                        self.history.push_front(self.line.clone());
                        self.clear_entire_line();
                    },
                    None => return false,
                    Some(line) => {
                        self.history.push_front(self.line.clone());
                        self.clear_entire_line();
                        self.line = line;
                        self.controls.outs(self.line.fpart.as_slice());
                        self.bpart.clear();
                        self.idraw_part();
                    }
                }
            },
            'A' => {
                // up
                self.escape = false;
                match self.history.pop_front() {
                    None => return false,
                    Some(line) => {
                        self.bhistory.push(self.line.clone());
                        self.clear_entire_line();
                        self.line = line;
                        self.controls.outs(self.line.fpart.as_slice());
                        self.bpart.clear();
                        self.idraw_part();
                    }
                }
            },
            'R' => {
                // cursor position
                self.escape = false;
                if !PPOS_REGEX.is_match(self.escape_chars.as_slice()) {
                    return false;
                } else {
                    let caps = PPOS_REGEX.captures(self.escape_chars.as_slice()).unwrap();
                    let row = caps.at(1).unwrap();
                    let col = caps.at(2).unwrap();
                    let pointer = Position {
                        row: match from_str_radix(row, 10) {
                            Err(_) => return false,
                            Ok(v) => v
                        },
                        col: match from_str_radix(col, 10) {
                            Err(_) => return false,
                            Ok(v) => v
                        }
                    };
                    self.controls.update_cursor(pointer);
                    if !self.first_rsave {
                        self.controls.save_row(pointer.col);
                        self.controls.update_line(pointer.col);
                        self.first_rsave = true;
                    }
                }
            },
            ch => {
                self.escape_chars.push(ch);
                if self.escape_chars.len() > MAX_ESCAPE {
                    self.escape = false;
                    return false;
                }
            }
        }
        return true;
    }
}

<|endoftext|>