From bd0d29973ced36e5b88dd90dd72eb4bc5bd3a68d Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 6 May 2021 23:51:14 -0400 Subject: [PATCH] add command parser and tests (wip) --- src/dispatcher.rs | 2 + src/main.rs | 3 + .../first_pass_command_parser.rs | 83 +++++++++++++++++++ src/text_chat_parsers/mod.rs | 1 + 4 files changed, 89 insertions(+) create mode 100644 src/text_chat_parsers/first_pass_command_parser.rs create mode 100644 src/text_chat_parsers/mod.rs diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 887518e4ce..b5e78467c3 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -81,6 +81,8 @@ impl Dispatcher { static ref COMMAND_REGEX : Regex = Regex::new(r"^\s*(\w+)\s+(.*)$").expect("Regex should work"); } + "".to_string() + } } diff --git a/src/main.rs b/src/main.rs index 41e3124754..bdb126507a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,7 @@ #[macro_use] extern crate serde_derive; +#[macro_use] +extern crate lazy_static; mod dispatcher; mod handlers; @@ -8,6 +10,7 @@ mod protos; mod redis_client; mod redis_subscriber; mod secrets; +mod text_chat_parsers; use anyhow::anyhow; use anyhow::{Context, Error}; diff --git a/src/text_chat_parsers/first_pass_command_parser.rs b/src/text_chat_parsers/first_pass_command_parser.rs new file mode 100644 index 0000000000..fb6447bd7f --- /dev/null +++ b/src/text_chat_parsers/first_pass_command_parser.rs @@ -0,0 +1,83 @@ +use anyhow::anyhow; +use log::debug; +use lazy_static::lazy_static; +use crate::AnyhowResult; +use regex::Regex; + +struct FirstPassParsedCommand { + /// The first "word" / "verb" of a sentence. + /// This is all-lowercase, no spaces, `[\w\-]+` + pub command: String, + + /// The remaining portion, stripped of leading/trailing spaces. + pub unparsed_arguments: String, +} + +impl FirstPassParsedCommand { + + pub fn try_parse(message: &str) -> AnyhowResult { + lazy_static! { + static ref COMMAND_REGEX : Regex = Regex::new(r"^\s*([\w\-]+)\s+(.*)$").expect("should parse"); + } + + let captures = match COMMAND_REGEX.captures(&message) { + None => return Err(anyhow!("message could not parse")), + Some(caps) => caps, + }; + + let command = match captures.get(1) { + None => return Err(anyhow!("could not get first capture group")), + Some(cmd) => cmd.as_str().trim().to_lowercase(), + }; + + debug!("Command: {}", command); + + let unparsed_payload = match captures.get(2) { + None => return Err(anyhow!("could not get second capture group")), + Some(p) => p.as_str().trim(), + }; + + debug!("Unparsed payload: {}", unparsed_payload); + + Ok(Self { + command: "".to_string(), + unparsed_arguments: "".to_string() + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn failure_cases() { + assert!(FirstPassParsedCommand::try_parse("").is_err()); + assert!(FirstPassParsedCommand::try_parse(" ").is_err()); + assert!(FirstPassParsedCommand::try_parse("foo").is_err()); + assert!(FirstPassParsedCommand::try_parse("foo-bar").is_err()); + } + + #[test] + fn parse_two_words() { + let r = FirstPassParsedCommand::try_parse("foo bar"); + assert!(r.is_ok()); + let r = r.expect("Is okay"); + assert_eq!(&r.command, "foo"); + assert_eq!(&r.unparsed_arguments, "bar"); + } + + #[test] + fn parse_two_words_spaces() { + let r = FirstPassParsedCommand::try_parse(" foo \t bar \t \n "); + assert!(r.is_ok()); + let r = r.expect("Is okay"); + assert_eq!(&r.command, "foo"); + assert_eq!(&r.unparsed_arguments, "bar"); + } + + #[test] + fn parse_hyphenated_command() { + todo!(); + } +} diff --git a/src/text_chat_parsers/mod.rs b/src/text_chat_parsers/mod.rs new file mode 100644 index 0000000000..ad505ed485 --- /dev/null +++ b/src/text_chat_parsers/mod.rs @@ -0,0 +1 @@ +pub mod first_pass_command_parser; \ No newline at end of file