diff --git a/src/framework/commands/arguments.rs b/src/framework/commands/arguments.rs index 7b43985..3b88a1b 100644 --- a/src/framework/commands/arguments.rs +++ b/src/framework/commands/arguments.rs @@ -96,6 +96,38 @@ impl FromArguments for NeedyString { } } +pub struct NeedyGreedyString(pub String); + +impl Deref for NeedyGreedyString { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for NeedyGreedyString { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl fmt::Display for NeedyGreedyString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl FromArguments for NeedyGreedyString { + fn from_args(args: &str) -> Result<(Self, &str), ArgumentParsingError> { + if !args.is_empty() { + Ok((Self(args.to_string()), "")) + } else { + Err(ArgumentParsingError::MissingArgument) + } + } +} + impl FromArguments for bool { fn from_args(args: &str) -> Result<(Self, &str), ArgumentParsingError> { let arg: &str; diff --git a/src/framework/mod.rs b/src/framework/mod.rs index 8d4d578..c881120 100644 --- a/src/framework/mod.rs +++ b/src/framework/mod.rs @@ -73,7 +73,10 @@ //! //! async fn execute(&self, ctx: CommandContext<'_, T>, _args: &str) -> Result<(), CommandError> { //! // Your command logic here. -//! ctx.send().content("Hello, world!").await.map_err(|_| CommandError::MessageSendingFailed)?; +//! ctx.send() +//! .content("Hello, world!") +//! .await +//! .map_err(|_| CommandError::MessageSendingFailed)?; //! //! Ok(()) //! } @@ -88,8 +91,66 @@ //! bot.run(&token).await.unwrap(); //! ``` //! -//! Log into your Discord account and invite the bot to your server. Then you can test the command by sending -//! `p.my_command` in a channel the bot has access to. +//! Log into your Discord account and invite the bot to your server. Then you can test the command +//! by sending `p.my_command` in a channel the bot has access to. +//! +//! ### Configuring Commands Further +//! +//! Commands can be configured with additional metadata, such as aliases, descriptions, and +//! arguments. The following is a full example of a command with all these features: +//! +//! ``` +//! use crate::framework::commands::{Command}; +//! +//! pub struct HelloCommand; +//! +//! #[async_trait::async_trait] +//! impl Command for HelloCommand { +//! fn name(&self) -> &'static str { +//! "hello" +//! } +//! +//! /// A list of alternative names for the command. +//! fn aliases(&self) -> &'static [&'static str] { +//! &["hola", "hey", "hi", "konnichiwa"] +//! } +//! +//! /// A description of the command and its functionality. +//! fn description(&self) -> &'static str { +//! "This command responds with a greeting." +//! } +//! +//! /// A list of arguments the command accepts. +//! fn arguments(&self) -> &'static [Argument] { +//! &[ +//! Argument { +//! name: "name", +//! is_optional: false, +//! is_greedy: true, +//! }, +//! ] +//! } +//! +//! async fn execute( +//! &self, +//! ctx: CommandContext<'_, T>, +//! args: &str, +//! ) -> Result<(), CommandError> { +//! // Parse the arguments using the `ParseArguments` trait. +//! let name: NeedyGreedyString = ParseArguments::parse( +//! args +//! ) +//! .unwrap_or(NeedyGreedyString("???".to_string())); +//! +//! ctx.send() +//! .content(format!("Hello, {}!", name.0)) +//! .await +//! .map_err(|_| CommandError::MessageSendingFailed)?; +//! +//! Ok(()) +//! } +//! } +//! ``` pub mod bot; pub mod commands;