mod buffer; mod enums; pub use self::buffer::Buffer; pub use self::enums::{parse_address, parse_command, Address, Command}; use nom::bytes::complete::take_while; use nom::character::complete::one_of; use nom::error::ErrorKind; use nom::sequence::Tuple; use nom::Err::Error; use std::fs::File; use std::io; use std::io::prelude::*; use std::io::BufReader; const FILE: &str = "test"; #[derive(PartialEq)] enum Exit { Continue, HasBeenModified, Quit, } // TODO juste $ pour l'instant dans l'adresse // TODO faire les commandes mais juste p pour l'instant // TODO faire un système de retour d'erreur pour afficher ? et l'erreur si l'utilisateur le demande // (cad les fonctions pour parser retournent un Err et on peut parser ce Err pour voir le type de // l'erreur, idem pour les fonctions d'exécutiosn ?) /* fn read_address(input: &str) -> Result<&str, Address> { } */ /* * Le char doit être une commande valide. */ fn check_address(c: char) -> bool { c.is_ascii_digit() || c == '$' || c == ' ' || c == '.' } fn check_address_complete(c: char) -> bool { check_address(c) || c == ',' || c == ';' } fn read_user_input() -> Vec { let mut buffer: Vec = Vec::new(); let mut buffer_input = String::new(); while buffer_input != "." { buffer_input.clear(); match io::stdin().read_line(&mut buffer_input) { Ok(_) => { buffer_input.pop(); if buffer_input != "." { buffer.push(buffer_input.clone()); } } Err(e) => panic!("{}", e), } } buffer } fn execute_command(buffer: &mut Buffer, c: Command) -> Exit { let mut ret = Exit::Continue; match c { Command::Append(a) => buffer.append(a, read_user_input()), Command::Insert(a) => buffer.insert(a, read_user_input()), Command::Delete(a) => buffer.delete(a), Command::Print(a) => buffer.print(a, false), Command::Number(a) => buffer.print(a, true), Command::Quit(q) => { if buffer.is_modified() { if q { ret = Exit::Quit; } else { ret = Exit::HasBeenModified; } } else { ret = Exit::Quit; } } Command::Write(a) => { buffer.save(a); ret = Exit::Continue; } _ => (), } ret } fn parse_line(input: &str) -> Result { let address = take_while(check_address_complete); let command = one_of::<_, _, (&str, ErrorKind)>("aidpnqQw"); //if let Ok((input, (a, c))) = alt(address, command).parse(input) { let tmp = (address, command).parse(input); if let Ok((_input, (a, c))) = tmp { let addr = parse_address(a); parse_command(c, addr) } else if let Err(Error((_, _))) = tmp { Err(String::from("Erreur de parsing")) } else { Err(String::from("Grosse erreur")) } } fn main() { let buffer: Vec> = if let Ok(f) = File::open(FILE) { let buff = BufReader::new(f); buff.lines().collect() } else { panic!("Le fichier n'existe pas."); }; let mut buffer_struct = Buffer::new(FILE, buffer); println!("fichier lu !"); let mut pred = Exit::Continue; while pred != Exit::Quit { let mut input = String::new(); match io::stdin().read_line(&mut input) { Ok(_) => { let result_parse = parse_line(&input); if let Ok(c) = result_parse { pred = match execute_command(&mut buffer_struct, c) { Exit::HasBeenModified => { if pred == Exit::HasBeenModified { Exit::Quit } else { Exit::HasBeenModified } } exit => exit, } } else if let Err(e) = result_parse { println!("?"); println!("{}", e); pred = Exit::Continue; } } Err(e) => panic!("{}", e), } } }