diff options
| -rw-r--r-- | examples/06_command_framework.rs | 2 | ||||
| -rw-r--r-- | src/ext/framework/command.rs | 55 | ||||
| -rw-r--r-- | src/ext/framework/mod.rs | 62 |
3 files changed, 72 insertions, 47 deletions
diff --git a/examples/06_command_framework.rs b/examples/06_command_framework.rs index cb838fd..b93b952 100644 --- a/examples/06_command_framework.rs +++ b/examples/06_command_framework.rs @@ -21,9 +21,9 @@ fn main() { // Commands are equivilant to: // "~about" - // "~ping" // "~emoji cat" // "~emoji dog" + // "~ping" // "~some complex command" client.with_framework(|f| f .configure(|c| c diff --git a/src/ext/framework/command.rs b/src/ext/framework/command.rs index 43d3c9a..6a9a713 100644 --- a/src/ext/framework/command.rs +++ b/src/ext/framework/command.rs @@ -1,7 +1,62 @@ use std::sync::Arc; +use super::{CommandType, Configuration}; use ::client::Context; use ::model::Message; pub type Command = Fn(Context, Message, Vec<String>) + Send + Sync; #[doc(hidden)] pub type InternalCommand = Arc<Command>; + +pub fn positions(content: &str, conf: &Configuration) + -> Option<(Vec<usize>, CommandType)> { + if let Some(ref prefix) = conf.prefix { + // Find out if they were mentioned. If not, determine if the prefix + // was used. If not, return None. + let (mut positions, kind) = if let Some(mention_end) = find_mention_end(content, conf) { + (vec![mention_end], CommandType::Mention) + } else if content.starts_with(prefix) { + (vec![prefix.len()], CommandType::Prefix) + } else { + return None; + }; + + if conf.allow_whitespace { + let pos = *unsafe { + positions.get_unchecked(0) + }; + + positions.insert(0, pos + 1); + } + + Some((positions, kind)) + } else if conf.on_mention.is_some() { + match find_mention_end(content, conf) { + Some(mention_end) => { + let mut positions = vec![mention_end]; + + if conf.allow_whitespace { + positions.insert(0, mention_end + 1); + } + + Some((positions, CommandType::Mention)) + }, + None => None, + } + } else { + None + } +} + +fn find_mention_end(content: &str, conf: &Configuration) -> Option<usize> { + if let Some(ref mentions) = conf.on_mention { + for mention in mentions { + if !content.starts_with(&mention[..]) { + continue; + } + + return Some(mention.len()); + } + } + + None +} diff --git a/src/ext/framework/mod.rs b/src/ext/framework/mod.rs index 1949e24..80844c3 100644 --- a/src/ext/framework/mod.rs +++ b/src/ext/framework/mod.rs @@ -11,6 +11,13 @@ use std::thread; use ::client::Context; use ::model::Message; +#[derive(Clone, Copy, Debug)] +pub enum CommandType { + Mention, + None, + Prefix, +} + #[allow(type_complexity)] #[derive(Default)] pub struct Framework { @@ -31,54 +38,17 @@ impl Framework { #[doc(hidden)] pub fn dispatch(&mut self, context: Context, message: Message) { - // Determine the point at which the prefix ends, and the command starts. - let positions = if let Some(ref prefix) = self.configuration.prefix { - let pos = if let Some(mention_ends) = self.find_mention_end(&message.content) { - mention_ends - } else if !message.content.starts_with(prefix) { - return; - } else { - prefix.len() - }; - - let mut positions = vec![pos]; - - if self.configuration.allow_whitespace { - positions.push(pos - 1); - } - - positions - } else if self.configuration.on_mention.is_some() { - match self.find_mention_end(&message.content) { - Some(mention_end) => { - let mut positions = vec![mention_end]; - - if self.configuration.allow_whitespace { - positions.push(mention_end - 1); - } + let res = command::positions(&message.content, &self.configuration); - positions - }, - None => return, - } - } else { - vec![0] + let (positions, kind) = match res { + Some((positions, kind)) => (positions, kind), + None => return, }; - // Ensure that the message length is at least longer than the prefix + // Ensure that the message length is at least longer than a prefix // length. There's no point in checking further ahead if there's nothing - // to check. - let mut less_than = true; - - for position in &positions { - if message.content.len() > *position { - less_than = false; - - break; - } - } - - if less_than { + // _to_ check. + if positions.iter().all(|p| message.content.len() <= *p) { return; } @@ -86,7 +56,7 @@ impl Framework { let mut built = String::new(); for i in 0..self.configuration.depth { - if i > 0 { + if i != 0 { built.push(' '); } @@ -113,7 +83,7 @@ impl Framework { let command = command.clone(); thread::spawn(move || { - let args = message.content[built.len() + 1..] + let args = message.content[position + built.len()..] .split_whitespace() .map(|arg| arg.to_owned()) .collect::<Vec<String>>(); |