mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 22:46:39 +01:00
Improve the docs of utils::command
This commit is contained in:
parent
54276aa8ba
commit
ae43f1f7ee
1 changed files with 115 additions and 81 deletions
|
@ -1,25 +1,27 @@
|
|||
//! Command parsers.
|
||||
//!
|
||||
//! You can either create an `enum`, containing commands of your bot, or use
|
||||
//! functions, which split input text into a string command with its arguments.
|
||||
//! You can either create an `enum` with derived [`BotCommand`], containing
|
||||
//! commands of your bot, or use functions, which split input text into a string
|
||||
//! command with its arguments.
|
||||
//!
|
||||
//! ## Examples
|
||||
//! Using `enum`:
|
||||
//! # Using BotCommand
|
||||
//! ```
|
||||
//! use teloxide::utils::command::BotCommand;
|
||||
//!
|
||||
//! type UnitOfTime = u8;
|
||||
//!
|
||||
//! #[derive(BotCommand, PartialEq, Debug)]
|
||||
//! #[command(rename = "lowercase", parser = "split")]
|
||||
//! enum AdminCommand {
|
||||
//! Mute(u8, char),
|
||||
//! Ban(u8, char),
|
||||
//! Mute(UnitOfTime, char),
|
||||
//! Ban(UnitOfTime, char),
|
||||
//! }
|
||||
//!
|
||||
//! let command = AdminCommand::parse("/ban 5 h", "bot_name").unwrap();
|
||||
//! assert_eq!(command, AdminCommand::Ban(5, 'h'));
|
||||
//! ```
|
||||
//!
|
||||
//! Using [`parse_command`]:
|
||||
//! # Using parse_command
|
||||
//! ```
|
||||
//! use teloxide::utils::command::parse_command;
|
||||
//!
|
||||
|
@ -29,7 +31,7 @@
|
|||
//! assert_eq!(args, vec!["3", "hours"]);
|
||||
//! ```
|
||||
//!
|
||||
//! Using [`parse_command_with_prefix`]:
|
||||
//! # Using parse_command_with_prefix
|
||||
//! ```
|
||||
//! use teloxide::utils::command::parse_command_with_prefix;
|
||||
//!
|
||||
|
@ -39,34 +41,25 @@
|
|||
//! assert_eq!(args, vec!["3", "hours"]);
|
||||
//! ```
|
||||
//!
|
||||
//! If the name of a bot does not match, it will return `None`:
|
||||
//! ```
|
||||
//! use teloxide::utils::command::parse_command;
|
||||
//!
|
||||
//! let result = parse_command("/ban@MyNameBot1 3 hours", "MyNameBot2");
|
||||
//! assert!(result.is_none());
|
||||
//! ```
|
||||
//!
|
||||
//! See [examples/admin_bot] as a more complicated examples.
|
||||
//!
|
||||
//! [`parse_command`]: crate::utils::command::parse_command
|
||||
//! [`parse_command_with_prefix`]:
|
||||
//! crate::utils::command::parse_command_with_prefix
|
||||
//! [examples/admin_bot]: https://github.com/teloxide/teloxide/blob/master/examples/miltiple_handlers_bot/
|
||||
//! [examples/admin_bot]: https://github.com/teloxide/teloxide/blob/master/examples/admin_bot/
|
||||
|
||||
pub use teloxide_macros::BotCommand;
|
||||
|
||||
/// An enumeration of bot's commands.
|
||||
///
|
||||
/// ## Example
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use teloxide::utils::command::BotCommand;
|
||||
///
|
||||
/// type UnitOfTime = u8;
|
||||
///
|
||||
/// #[derive(BotCommand, PartialEq, Debug)]
|
||||
/// #[command(rename = "lowercase", parser = "split")]
|
||||
/// enum AdminCommand {
|
||||
/// Mute(u8, char),
|
||||
/// Ban(u8, char),
|
||||
/// Mute(UnitOfTime, char),
|
||||
/// Ban(UnitOfTime, char),
|
||||
/// }
|
||||
///
|
||||
/// let command = AdminCommand::parse("/ban 5 h", "bot_name").unwrap();
|
||||
|
@ -75,8 +68,8 @@ pub use teloxide_macros::BotCommand;
|
|||
///
|
||||
/// ## Enum attributes
|
||||
/// 1. `#[command(rename = "rule")]`
|
||||
/// Rename all commands by rule. Allowed rules are `lowercase`. If you will not
|
||||
/// use this attribute, commands will be parsed by their original names.
|
||||
/// Rename all commands by `rule`. Allowed rules are `lowercase`. If you will
|
||||
/// not use this attribute, commands will be parsed by their original names.
|
||||
///
|
||||
/// 2. `#[command(prefix = "prefix")]`
|
||||
/// Change a prefix for all commands (the default is `/`).
|
||||
|
@ -86,10 +79,11 @@ pub use teloxide_macros::BotCommand;
|
|||
///
|
||||
/// 4. `#[command(parser = "parser")]`
|
||||
/// Change the parser of arguments. Possible values:
|
||||
/// - `default` - it also will be used if `parser` attribute will not be specified.
|
||||
/// It can only put all text after first space into first argument, which implement
|
||||
/// FromStr trait.
|
||||
/// Example:
|
||||
/// - `default` - the same as the unspecified parser. It only puts all text
|
||||
/// after the first space into the first argument, which must implement
|
||||
/// [`FromStr`].
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// use teloxide::utils::command::BotCommand;
|
||||
///
|
||||
|
@ -99,12 +93,16 @@ pub use teloxide_macros::BotCommand;
|
|||
/// Text(String),
|
||||
/// }
|
||||
///
|
||||
/// let command = AdminCommand::parse("/text hello my dear friend!", "").unwrap();
|
||||
/// let command =
|
||||
/// AdminCommand::parse("/text hello my dear friend!", "").unwrap();
|
||||
/// assert_eq!(command, Command::Text("hello my dear friend!".to_string()));
|
||||
/// ```
|
||||
/// - `split` - parse args by split incoming text by value specified in `separator`
|
||||
/// attribute. By default use space seperator. All args must implement FromStr trait.
|
||||
/// Example:
|
||||
///
|
||||
/// - `split` - separates a messsage by a given separator (the default is the
|
||||
/// space character) and parses each part into the corresponding arguments,
|
||||
/// which must implement [`FromStr`].
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// use teloxide::utils::command::BotCommand;
|
||||
///
|
||||
|
@ -117,19 +115,53 @@ pub use teloxide_macros::BotCommand;
|
|||
/// let command = AdminCommand::parse("/nums 1 32 -5", "").unwrap();
|
||||
/// assert_eq!(command, Command::Nums(1, 32, -5));
|
||||
/// ```
|
||||
/// - `custom_parser` - you can use your own parser, which must used signature `Fn(String) -> Result<Tuple, ParseError>`
|
||||
/// where `Tuple` - tuple with all fields in type. Allowed only on variant.
|
||||
/// Example:
|
||||
///
|
||||
/// 5. `#[command(separator = "sep")]`
|
||||
/// Specify separator used by the `split` parser. It will be ignored when
|
||||
/// accompanied by another type of parsers.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// use teloxide::utils::command::BotCommand;
|
||||
///
|
||||
/// #[derive(BotCommand, PartialEq, Debug)]
|
||||
/// #[command(rename = "lowercase", parser = "split", separator = "|")]
|
||||
/// enum Command {
|
||||
/// Nums(u8, u16, i32),
|
||||
/// }
|
||||
///
|
||||
/// let command = AdminCommand::parse("/nums 1|32|5", "").unwrap();
|
||||
/// assert_eq!(command, Command::Nums(1, 32, 5));
|
||||
/// ```
|
||||
///
|
||||
/// ## Variant attributes
|
||||
/// All variant attributes override the corresponding `enum` attributes.
|
||||
///
|
||||
/// 1. `#[command(rename = "rule")]`
|
||||
/// Rename one command by a rule. Allowed rules are `lowercase`, `%some_name%`,
|
||||
/// where `%some_name%` is any string, a new name.
|
||||
///
|
||||
/// 2. `#[command(parser = "parser")]`
|
||||
/// One more option is available for variants.
|
||||
/// - `custom_parser` - your own parser of the signature `fn(String) ->
|
||||
/// Result<Tuple, ParseError>`, where `Tuple` corresponds to the variant's
|
||||
/// arguments.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```
|
||||
/// use teloxide::utils::command::{BotCommand, ParseError};
|
||||
///
|
||||
/// fn accept_two_digits(input: String) -> Result<(u8), ParseError> {
|
||||
/// match input.len() {
|
||||
/// 2 => {
|
||||
/// let num = input.parse().map_err(|_|ParseError::IncorrectFormat)?;
|
||||
/// let num =
|
||||
/// input.parse().map_err(|_| ParseError::IncorrectFormat)?;
|
||||
/// Ok((num))
|
||||
/// }
|
||||
/// len => Err(ParseError::Custom(format!("Only 2 digits allowed, not {}", len)))
|
||||
/// len => Err(ParseError::Custom(format!(
|
||||
/// "Only 2 digits allowed, not {}",
|
||||
/// len
|
||||
/// ))),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
@ -145,41 +177,14 @@ pub use teloxide_macros::BotCommand;
|
|||
/// assert!(command.is_err());
|
||||
/// ```
|
||||
///
|
||||
/// 5. `#[command(separator = "sep")]`
|
||||
/// Specify separator used by `split` parser. Will be ignored when used another
|
||||
/// types of parser.
|
||||
/// Example:
|
||||
/// ```
|
||||
/// use teloxide::utils::command::BotCommand;
|
||||
/// 3. `#[command(prefix = "prefix")]`
|
||||
/// 4. `#[command(description = "description")]`
|
||||
/// 5. `#[command(separator = "sep")]`
|
||||
///
|
||||
/// #[derive(BotCommand, PartialEq, Debug)]
|
||||
/// #[command(rename = "lowercase", parser = "split", separator = "|")]
|
||||
/// enum Command {
|
||||
/// Nums(u8, u16, i32),
|
||||
/// }
|
||||
/// Analogous to the descriptions above.
|
||||
///
|
||||
/// let command = AdminCommand::parse("/nums 1|32|5", "").unwrap();
|
||||
/// assert_eq!(command, Command::Nums(1, 32, 5));
|
||||
/// ```
|
||||
///
|
||||
/// ## Variant attributes
|
||||
/// 1. `#[command(rename = "rule")]`
|
||||
/// Rename one command by a rule. Allowed rules are `lowercase`, `%some_name%`,
|
||||
/// where `%some_name%` is any string, a new name.
|
||||
///
|
||||
/// 2. `#[command(prefix = "prefix")]`
|
||||
/// Change a prefix for one command (the default is `/`).
|
||||
///
|
||||
/// 3. `#[command(description = "description")]`
|
||||
/// Add a description of one command.
|
||||
///
|
||||
/// 4. `#[command(parser = "parser")]`
|
||||
/// See description above.
|
||||
///
|
||||
/// 5. `#[command(separator = "sep")]`
|
||||
/// See description above.
|
||||
///
|
||||
/// All variant attributes overlap the `enum` attributes.
|
||||
/// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
|
||||
/// [`BotCommand`]: crate::utils::command::BotCommand
|
||||
pub trait BotCommand: Sized {
|
||||
fn descriptions() -> String;
|
||||
fn parse<N>(s: &str, bot_name: N) -> Result<Self, ParseError>
|
||||
|
@ -187,26 +192,38 @@ pub trait BotCommand: Sized {
|
|||
N: Into<String>;
|
||||
}
|
||||
|
||||
/// Error returned from `BotCommand::parse` method.
|
||||
/// Errors returned from [`BotCommand::parse`].
|
||||
///
|
||||
/// [`BotCommand::parse`]: crate::utils::command::BotCommand::parse
|
||||
#[derive(Debug)]
|
||||
pub enum ParseError {
|
||||
/// This error was returned when count of arguments will be less than expected count.
|
||||
TooFewArguments { expected: usize, found: usize, message: String },
|
||||
/// This error was returned when count of arguments will be greater than expected count.
|
||||
TooManyArguments { expected: usize, found: usize, message: String },
|
||||
/// This error was returned when error from `FromStr::from_str` was occured.
|
||||
TooFewArguments {
|
||||
expected: usize,
|
||||
found: usize,
|
||||
message: String,
|
||||
},
|
||||
TooManyArguments {
|
||||
expected: usize,
|
||||
found: usize,
|
||||
message: String,
|
||||
},
|
||||
|
||||
/// Redirected from [`FromStr::from_str`].
|
||||
///
|
||||
/// [`FromStr::from_str`]: https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str
|
||||
IncorrectFormat,
|
||||
/// This error was returned when input command does not represent in list of commands.
|
||||
|
||||
UnknownCommand(String),
|
||||
/// This error was returned when command bot name is different from expected bot name.
|
||||
WrongBotName(String),
|
||||
/// Custom error which you can return from custom parser.
|
||||
|
||||
/// A custom error which you can return from your custom parser.
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
/// Parses a string into a command with args.
|
||||
///
|
||||
/// It calls [`parse_command_with_prefix`] with the default prefix `/`.
|
||||
/// This function is just a shortcut for calling [`parse_command_with_prefix`]
|
||||
/// with the default prefix `/`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
|
@ -218,6 +235,14 @@ pub enum ParseError {
|
|||
/// assert_eq!(args, vec!["5", "hours"]);
|
||||
/// ```
|
||||
///
|
||||
/// If the name of a bot does not match, it will return `None`:
|
||||
/// ```
|
||||
/// use teloxide::utils::command::parse_command;
|
||||
///
|
||||
/// let result = parse_command("/ban@MyNameBot1 3 hours", "MyNameBot2");
|
||||
/// assert!(result.is_none());
|
||||
/// ```
|
||||
///
|
||||
/// [`parse_command_with_prefix`]:
|
||||
/// crate::utils::command::parse_command_with_prefix
|
||||
pub fn parse_command<N>(text: &str, bot_name: N) -> Option<(&str, Vec<&str>)>
|
||||
|
@ -240,6 +265,15 @@ where
|
|||
/// assert_eq!(command, "mute");
|
||||
/// assert_eq!(args, vec!["5", "hours"]);
|
||||
/// ```
|
||||
///
|
||||
/// If the name of a bot does not match, it will return `None`:
|
||||
/// ```
|
||||
/// use teloxide::utils::command::parse_command_with_prefix;
|
||||
///
|
||||
/// let result =
|
||||
/// parse_command_with_prefix("!", "!ban@MyNameBot1 3 hours", "MyNameBot2");
|
||||
/// assert!(result.is_none());
|
||||
/// ```
|
||||
pub fn parse_command_with_prefix<'a, N>(
|
||||
prefix: &str,
|
||||
text: &'a str,
|
||||
|
|
Loading…
Reference in a new issue