<commit_before>use std::collections::HashMap;

use std::cmp::*;

use types::WashArgs::*;

use constants::*;
use types::*;
use util::*;
use env::*;

use self::HandlerResult::*;

// Note with handlers: Err means Stop, not necessarily Fail
// return semi-redundant result type because try! is so damn useful
pub type WashHandler = fn(&mut Vec<WashArgs>, &mut Vec<InputValue>, &mut ShellState) -> Result<HandlerResult, String>;

pub type HandlerTable = HashMap<String, WashHandler>;

pub enum HandlerResult {
    Continue,
    Stop,
    More(WashBlock)
}

#[derive(Clone)]
pub struct WashBlock {
    pub start: String,
    pub next: Vec<InputValue>,
    pub close: Vec<InputValue>,
    pub content: Vec<InputValue>
}

pub struct ShellState {
    pub env: WashEnv,
    blocks: Vec<WashBlock>,
    handlers: HandlerTable,
    last: Option<Result<WashArgs, String>>
}

impl ShellState {
    pub fn new() -> ShellState {
        ShellState {
            handlers: HashMap::new(),
            env: WashEnv::new(),
            blocks: vec![],
            last: None
        }
    }

    pub fn in_block(&self) -> bool {
        return !self.blocks.is_empty();
    }
    
    pub fn has_handler(&self, word:&String) -> bool {
        return self.handlers.contains_key(word);
    }

    pub fn insert_handler(&mut self, word:&str, func:WashHandler) -> Result<WashArgs, String> {
        self.handlers.insert(word.to_string(), func);
        return Ok(Empty);
    }

    pub fn run_handler(&mut self, word:&String, pre:&mut Vec<WashArgs>, next:&mut Vec<InputValue>) -> Result<HandlerResult, String> {
        let func = match self.handlers.get(word) {
            None => return Err("Handler not found".to_string()),
            Some(func) => func.clone()
        };
        return func(pre, next, self);
    }
        
    pub fn process_command(&mut self, args:Vec<WashArgs>) -> Result<WashArgs, String> {
        if args.is_empty() {
            // this happens when a handler ends a line and passes nothing on
            return Ok(Empty);
        } else if self.env.hasf(&args[0].flatten()) {
            // run as a function instead
            return self.env.runf(&args[0].flatten(), &Long(args[min(1, args.len())..].to_vec()));
        } else {
            let out = try!(self.process_function("run".to_string(), args));
            return self.env.describe_process_output(&out);
        }
    }

    pub fn process_function(&mut self, name:String, args:Vec<WashArgs>) -> Result<WashArgs, String> {
        let out = try!(self.env.runf(&name, &WashArgs::Long(args)));
        return Ok(out);
    }

    pub fn process_lines<'a, T:Iterator<Item=&'a InputValue>>(&mut self, mut lines:T) -> Result<WashArgs, String> {
        let mut out = Flat(String::new());
        let reset_sigint;
        if self.env.catch_sigint {
            reset_sigint = true;
            // handle sigint
            self.env.handle_sigint();
            // prevent env from unsetting that handler
            self.env.catch_sigint = false;
        } else {
            reset_sigint = false;
        }<commit_msg>Update for rust nightly<commit_after>use std::collections::HashMap;

use std::cmp::*;

use types::WashArgs::*;

use constants::*;
use types::*;
use util::*;
use env::*;

use self::HandlerResult::*;

// Note with handlers: Err means Stop, not necessarily Fail
// return semi-redundant result type because try! is so damn useful
pub type WashHandler = fn(&mut Vec<WashArgs>, &mut Vec<InputValue>, &mut ShellState) -> Result<HandlerResult, String>;

pub type HandlerTable = HashMap<String, WashHandler>;

pub enum HandlerResult {
    Continue,
    Stop,
    More(WashBlock)
}

#[derive(Clone)]
pub struct WashBlock {
    pub start: String,
    pub next: Vec<InputValue>,
    pub close: Vec<InputValue>,
    pub content: Vec<InputValue>
}

pub struct ShellState {
    pub env: WashEnv,
    blocks: Vec<WashBlock>,
    handlers: HandlerTable,
    last: Option<Result<WashArgs, String>>
}

impl ShellState {
    pub fn new() -> ShellState {
        ShellState {
            handlers: HashMap::new(),
            env: WashEnv::new(),
            blocks: vec![],
            last: None
        }
    }

    pub fn in_block(&self) -> bool {
        return !self.blocks.is_empty();
    }
    
    pub fn has_handler(&self, word:&String) -> bool {
        return self.handlers.contains_key(word);
    }

    pub fn insert_handler(&mut self, word:&str, func:WashHandler) -> Result<WashArgs, String> {
        self.handlers.insert(word.to_string(), func);
        return Ok(Empty);
    }

    pub fn run_handler(&mut self, word:&String, pre:&mut Vec<WashArgs>, next:&mut Vec<InputValue>) -> Result<HandlerResult, String> {
        let func = match self.handlers.get(word) {
            None => return Err("Handler not found".to_string()),
            Some(func) => func.clone()
        };
        return func(pre, next, self);
    }
        
    pub fn process_command(&mut self, args:Vec<WashArgs>) -> Result<WashArgs, String> {
        if args.is_empty() {
            // this happens when a handler ends a line and passes nothing on
            return Ok(Empty);
        } else if self.env.hasf(&args[0].flatten()) {
            // run as a function instead
            return self.env.runf(&args[0].flatten(), &Long(args[min(1, args.len())..].to_vec()));
        } else {
            let out = try!(self.process_function("run".to_string(), args));
            return self.env.describe_process_output(&out);
        }
    }

    pub fn process_function(&mut self, name:String, args:Vec<WashArgs>) -> Result<WashArgs, String> {
        let out = try!(self.env.runf(&name, &WashArgs::Long(args)));
        return Ok(out);
    }

    pub fn process_lines<'a, T:Iterator<Item=&'a InputValue>>(&mut self, lines:T) -> Result<WashArgs, String> {
        let mut out = Flat(String::new());
        let reset_sigint;
        if self.env.catch_sigint {
            reset_sigint = true;
            // handle sigint
            self.env.handle_sigint();
            // prevent env from unsetting that handler
            self.env.catch_sigint = false;
        } else {
            reset_sigint = false;
        }
{'fraction_non_alphanumeric': 0.13795336787564766, 'fraction_numerical': 0.0009715025906735751, 'mean_word_length': 2.5520414031052328, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 2, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '859069', 'n_tokens_mistral': 1908, 'n_tokens_neox': 1872, 'n_words': 486}