use regex::{regex, Regex}; #[derive(Debug,Eq,PartialEq,Clone)] pub struct EntryQuery<'a> { term : &'a str, language : Option <&'a str>, pos : Option <&'a str>, } impl<'a> EntryQuery<'a> { pub fn basic (term : &'a str) -> EntryQuery<'a> { EntryQuery { term, language: None, pos: None } } } #[derive(Debug,Eq,PartialEq,Clone)] pub enum Command<'a> { Define (EntryQuery<'a>), Etymology (EntryQuery<'a>), } #[derive(Debug,Eq,PartialEq,Clone)] pub struct ChatMessage<'a> { author : &'a str, content : &'a str, } impl<'a> ChatMessage<'a> { pub fn unauthored (content : &'a str) -> ChatMessage<'a> { ChatMessage { author: "", content } } pub fn parse (line : &'a str) -> Option> { let re : &Regex = regex! (r"(?:\*사망\* )?(.*?) : (.*)"); let r = re.captures (line)?; Some (ChatMessage { author: r.get (1)?.as_str (), content: r.get (2)?.as_str (), }) } } fn find_query<'a> (s : &'a str) -> Option> { let basic_re = regex! (r"^\s*define (.*)|define (\w+)"); let wikilink_re = regex! (r"(?m)\[\[([^]]*)]]"); let term = if let Some (r) = wikilink_re.captures (s) { r.get (1) } else if let Some (r) = basic_re.captures (s) { r.get (1).or (r.get (2)) } else { None }; Some (EntryQuery::basic (term?.as_str ())) } impl<'a> Command<'a> { pub fn parse (msg : &'a ChatMessage<'a>) -> Option> { Self::parse_str (msg.content) } pub fn parse_str (s : &'a str) -> Option> { Self::parse_etymology (s).or (Self::parse_define (s)) } fn parse_define (s : &'a str) -> Option> { let basic_re = regex! (r"^\s*define (.*)|define (\w+)"); let wikilink_re = regex! (r"\[\[([^]]*)]]"); let term = if let Some (r) = wikilink_re.captures (s) { r.get (1) } else if let Some (r) = basic_re.captures (s) { r.get (1).or (r.get (2)) } else { None }; Some (Command::Define (EntryQuery::basic (term?.as_str ()))) } fn parse_etymology (s : &'a str) -> Option> { let basic_re = regex! (r"^\s*etymology of (.*)|ety(?:m(?:ology(?: of)?)?)? (\w+)"); let wikilink_re = regex! (r"ety(?:m(?:ology(?: of)?)?)? \[\[([^]]*)]]"); let term = if let Some (r) = wikilink_re.captures (s) { r.get (1) } else if let Some (r) = basic_re.captures (s) { r.get (1).or (r.get (2)) } else { None }; Some (Command::Etymology (EntryQuery::basic (term?.as_str ()))) } } mod tests { use super::*; use super::Command as Cmd; #[test] fn etym_wikilink () { assert_eq! ( Cmd::parse_str ( "blah blah etymology of [[lexicography]]" ), Some (Cmd::Etymology (EntryQuery::basic ("lexicography"))) ); assert_eq! ( Cmd::parse_str ( "etym [[lexicography]]" ), Some (Cmd::Etymology (EntryQuery::basic ("lexicography"))) ); assert_eq! ( Cmd::parse_str ( "ety [[lexicography]]" ), Some (Cmd::Etymology (EntryQuery::basic ("lexicography"))) ); } #[test] fn etym_basic () { assert_eq! ( Cmd::parse_str ( "wiktionary, can you provide the etymology of lexicography??" ), Some (Cmd::Etymology (EntryQuery::basic ("lexicography"))) ) } #[test] fn define_basic () { assert_eq! ( Cmd::parse_str ("wiktionary, can you define lexicography??"), Some (Cmd::Define (EntryQuery::basic ("lexicography"))) ); } #[test] fn define_line () { assert_eq! ( Cmd::parse_str ("define I'm twenty years old"), Some (Cmd::Define (EntryQuery::basic ("I'm twenty years old"))) ); } #[test] fn define_wikilink () { assert_eq! ( Cmd::parse_str ("[[hoofjob]]"), Some (Cmd::Define (EntryQuery::basic ("hoofjob"))) ); assert_eq! ( Cmd::parse_str ("bkah blah blah [[quirkchungus]] blbalb"), Some (Cmd::Define (EntryQuery::basic ("quirkchungus"))) ); assert_eq! ( Cmd::parse_str ("define I'm [[twenty]] years old"), Some (Cmd::Define (EntryQuery::basic ("twenty"))) ); } }