use std::num::ParseIntError; use std::str::FromStr; #[derive(Debug)] pub enum Address { Actual, // utile pour write qui considère une adresse nulle comme l'ensemble du // fichier par défaut Empty, Last, Line(usize), FromStartTo(usize), FromToEnd(usize), // pas sur ? FromTo(usize, usize), FromActTo(usize), FromActToEnd, All, Null, } impl Address { pub fn is_multi_line(&self) -> bool { !matches!( self, Address::Null | Address::Actual | Address::Last | Address::Line(_) | Address::Empty ) } } pub fn parse_address(addr: &str) -> Address { let mut tmp = String::from(addr); tmp.retain(|c| c != ' '); let addr = tmp.as_str(); if addr.is_empty() { Address::Empty } else if addr.contains(',') || addr.contains(';') { parse_multi_addr(addr) } else if let Ok(l) = usize::from_str(addr) { Address::Line(l) } else { match addr { "." => Address::Actual, "$" => Address::Last, _ => Address::Null, } } } fn parse_multi_addr(addr: &str) -> Address { // garde con ou pas ? let is_comma = addr.contains(','); let tmp: Vec<&str> = if is_comma { addr.split(',').collect() } else { addr.split(';').collect() }; if tmp.len() != 2 { Address::Null } else { let start = usize::from_str(tmp[0]); let end = usize::from_str(tmp[1]); if let Ok(a) = start { if let Ok(b) = end { Address::FromTo(a, b) } else { Address::Line(a) } } else if is_comma { parse_comma(end) } else { parse_semicolon(end) } } } fn parse_comma(end: Result) -> Address { if let Ok(a) = end { Address::FromStartTo(a) } else { Address::All } } fn parse_semicolon(end: Result) -> Address { if let Ok(a) = end { Address::FromActTo(a) } else { Address::FromActToEnd } } #[derive(Debug)] pub enum Command { // TODO Append(Address), Insert(Address), // TODO Change(Address), // TODO Delete(Address), // bool pour check ou pas (e et E) TODO mettre le chemin vers le fichier Edit(bool), // TODO chemin vers fichier File(), // TODO Help, // TODO SetHelp, // TODO Join(Address), // TODO nom de la marque Mark(Address), // TODO List(Address), // TODO Move(Address), // TODO Number(Address), Print(Address), // TODO Prompt, // bool pour check ou pas (q et Q) Quit(bool), // TODO Read, // TODO Substitute, // TODO CopyLines, // TODO Undo, // TODO nom de fichier Write(Address), // TODO Line, // TODO ShellCommand, // TODO Null, // TODO Global, // TODO NonMatched, } /* fn parse_without_addr(c: char) -> Command { match c { 'q' => Command::Quit(false), 'Q' => Command::Quit(true), _ => Command::Help, } } */ fn parse(c: char, addr: Address) -> Result { match c { 'a' => { if addr.is_multi_line() { Err(String::from("Erreur d'adresse")) } else { Ok(Command::Append(addr)) } } 'i' => { if addr.is_multi_line() { Err(String::from("Erreur d'adresse")) } else { Ok(Command::Insert(addr)) } } 'd' => Ok(Command::Delete(addr)), 'p' => Ok(Command::Print(addr)), 'n' => Ok(Command::Number(addr)), 'q' => Ok(Command::Quit(false)), 'Q' => Ok(Command::Quit(true)), 'w' => Ok(Command::Write(addr)), _ => Ok(Command::Help), } } pub fn parse_command(c: char, addr: Address) -> Result { parse(c, addr) /* if let Some(a) = addr { println!("Ok"); parse_with_addr(c, a) } else { println!("No"); parse_without_addr(c) } */ }