changed name of trait from TelegramCommandEnum to TelegramBotCommand and divided parse_command into parse_command and parse_command_with_prefix

This commit is contained in:
p0lunin 2020-01-19 15:48:02 +02:00
parent 4af7b9f1f0
commit 5f34d7ffc6
2 changed files with 79 additions and 26 deletions

View file

@ -1,53 +1,106 @@
pub use teloxide_macros::TelegramCommandEnum;
pub use teloxide_macros::TelegramBotCommand;
/// Enum for telegram commands
///
/// Example:
/// ```
/// use teloxide::utils::TelegramCommandEnum;
/// use teloxide::utils::TelegramBotCommand;
/// use teloxide::utils::parse_command_into_enum;
/// #[derive(TelegramCommandEnum, PartialEq, Debug)]
/// enum TelegramCommand {
/// Start,
/// Help,
/// #[derive(TelegramBotCommand, PartialEq, Debug)]
/// enum TelegramAdminCommand {
/// Ban,
/// Kick,
/// }
/// let (command, args) = parse_command_into_enum::<TelegramCommand>("/", "/start arg1 arg2").unwrap();
/// assert_eq!(command, TelegramCommand::Start);
/// assert_eq!(args, vec!["arg1", "arg2"]);
/// let (command, args) = parse_command_into_enum::<TelegramAdminCommand>("/ban 5 h").unwrap();
/// assert_eq!(command, TelegramAdminCommand::Ban);
/// assert_eq!(args, vec!["5", "h"]);
/// ```
pub trait TelegramCommandEnum: Sized {
pub trait TelegramBotCommand: Sized {
fn try_from(s: &str) -> Option<Self>;
}
pub fn parse_command_into_enum<'a, T>(
/// Function to parse message with command into enum. Command must started with `/`
///
/// Example:
/// ```
/// use teloxide::utils::TelegramBotCommand;
/// use teloxide::utils::parse_command_into_enum;
/// #[derive(TelegramBotCommand, PartialEq, Debug)]
/// enum TelegramAdminCommand {
/// Ban,
/// Kick,
/// }
/// let (command, args) = parse_command_into_enum::<TelegramAdminCommand>("/ban 5 h").unwrap();
/// assert_eq!(command, TelegramAdminCommand::Ban);
/// assert_eq!(args, vec!["5", "h"]);
/// ```
pub fn parse_command_into_enum<T>(
text: &str,
) -> Option<(T, Vec<&str>)>
where
T: TelegramBotCommand,
{
parse_command_into_enum_with_prefix("/", text)
}
/// Function to parse message with command with custom prefix into enum.
///
/// Example:
/// ```
/// use teloxide::utils::TelegramBotCommand;
/// use teloxide::utils::parse_command_into_enum_with_prefix;
/// #[derive(TelegramBotCommand, PartialEq, Debug)]
/// enum TelegramAdminCommand {
/// Ban,
/// Kick,
/// }
/// let (command, args) = parse_command_into_enum_with_prefix::<TelegramAdminCommand>("!", "!ban 5 h").unwrap();
/// assert_eq!(command, TelegramAdminCommand::Ban);
/// assert_eq!(args, vec!["5", "h"]);
/// ```
pub fn parse_command_into_enum_with_prefix<'a, T>(
prefix: &str,
text: &'a str,
) -> Option<(T, Vec<&'a str>)>
where
T: TelegramCommandEnum,
T: TelegramBotCommand,
{
let (command, args) = parse_command(prefix,text)?;
return match T::try_from(command) {
let (command, args) = parse_command_with_prefix(prefix, text)?;
match T::try_from(command) {
Some(command) => Some((command, args)),
_ => None,
};
}
}
/// Function which parse string and return command with args
/// Function which parse string and return command with args. It calls [`parse_command_with_prefix`] with default prefix `/`
///
/// Example:
/// ```
/// use teloxide::utils::parse_command;
/// let text = "/ban 5 hours";
/// let (command, args) = parse_command("/", text).unwrap();
/// let (command, args) = parse_command(text).unwrap();
/// assert_eq!(command, "ban");
/// assert_eq!(args, vec!["5", "hours"]);
/// ```
pub fn parse_command<'a>(prefix: &str, text: &'a str) -> Option<(&'a str, Vec<&'a str>)> {
pub fn parse_command(text: &str) -> Option<(&str, Vec<&str>)> {
parse_command_with_prefix("/", text)
}
/// Function which parse string and return command with args. Prefix - start symbols which denote start of command
///
/// Example:
/// ```
/// use teloxide::utils::parse_command_with_prefix;
/// let text = "!ban 5 hours";
/// let (command, args) = parse_command_with_prefix("!", text).unwrap();
/// assert_eq!(command, "ban");
/// assert_eq!(args, vec!["5", "hours"]);
/// ```
pub fn parse_command_with_prefix<'a>(prefix: &str, text: &'a str) -> Option<(&'a str, Vec<&'a str>)> {
if !text.starts_with(prefix) {
return None;
}
let mut words = text.split_whitespace();
let command = &words.next()?[1..];
let command = &words.next()?[prefix.len()..];
Some((command, words.collect()))
}
@ -59,7 +112,7 @@ mod tests {
fn parse_command_with_args_() {
let data = "/command arg1 arg2";
let expected = Some(("command", vec!["arg1", "arg2"]));
let actual = parse_command("/", data);
let actual = parse_command(data);
assert_eq!(actual, expected)
}
@ -67,13 +120,13 @@ mod tests {
fn parse_command_with_args_without_args() {
let data = "/command";
let expected = Some(("command", vec![]));
let actual = parse_command("/", data);
let actual = parse_command(data);
assert_eq!(actual, expected)
}
#[test]
fn parse_command__with_args() {
#[derive(TelegramCommandEnum, Debug, PartialEq)]
#[derive(TelegramBotCommand, Debug, PartialEq)]
enum DefaultCommands {
Start,
Help,
@ -81,7 +134,7 @@ mod tests {
let data = "/start arg1 arg2";
let expected = Some((DefaultCommands::Start, vec!["arg1", "arg2"]));
let actual = parse_command_into_enum::<DefaultCommands>("/", data);
let actual = parse_command_into_enum::<DefaultCommands>(data);
assert_eq!(actual, expected)
}
}

View file

@ -4,7 +4,7 @@ use proc_macro::TokenStream;
use quote::quote;
use syn::{DeriveInput, parse_macro_input};
#[proc_macro_derive(TelegramCommandEnum)]
#[proc_macro_derive(TelegramBotCommand)]
pub fn derive_telegram_command_enum(tokens: TokenStream) -> TokenStream {
let input = parse_macro_input!(tokens as DeriveInput);
@ -15,13 +15,13 @@ pub fn derive_telegram_command_enum(tokens: TokenStream) -> TokenStream {
variant.ident.to_string().to_lowercase()
}))
}
_ => panic!("TelegramCommandEnum allowed only for enums")
_ => return TokenStream::from(quote! { compile_error!("TelegramBotCommand allowed only for enums") })
};
let ident = input.ident;
let expanded = quote! {
impl TelegramCommandEnum for #ident {
impl TelegramBotCommand for #ident {
fn try_from(value: &str) -> Option<Self> {
match value {
#(