Add CommandExt trait

This commit is contained in:
Joscha 2024-12-28 19:50:10 +01:00
parent 346f4ff543
commit 49c4c91ccd
2 changed files with 50 additions and 14 deletions

View file

@ -3,10 +3,8 @@ use std::time::Duration;
use async_trait::async_trait; use async_trait::async_trait;
use euphoxide::api::Message; use euphoxide::api::Message;
use euphoxide_bot::{ use euphoxide_bot::{
bang::{General, Specific},
basic::Described,
botrulez::{FullHelp, Ping, ShortHelp}, botrulez::{FullHelp, Ping, ShortHelp},
Command, Commands, Context, Info, Propagate, Command, CommandExt, Commands, Context, Info, Propagate,
}; };
use euphoxide_client::MultiClient; use euphoxide_client::MultiClient;
use log::error; use log::error;
@ -45,17 +43,20 @@ async fn main() {
let (event_tx, mut event_rx) = mpsc::channel(10); let (event_tx, mut event_rx) = mpsc::channel(10);
let commands = Commands::new() let commands = Commands::new()
.then(Described::hidden(General::new("ping", Ping::default()))) .then(Ping::default().general("ping").hidden())
.then(Described::hidden(Specific::new("ping", Ping::default()))) .then(Ping::default().specific("ping").hidden())
.then(Described::hidden(General::new( .then(
"help", ShortHelp::new("/me demonstrates how to use euphoxide")
ShortHelp::new("/me demonstrates how to use euphoxide"), .general("help")
))) .hidden(),
.then(Described::hidden(Specific::new( )
"help", .then(
FullHelp::new().with_after("Created using euphoxide."), FullHelp::new()
))) .with_after("Created using euphoxide.")
.then(General::new("pyramid", Pyramid)) .specific("help")
.hidden(),
)
.then(Pyramid.general("pyramid"))
.build(); .build();
let clients = MultiClient::new(event_tx); let clients = MultiClient::new(event_tx);

View file

@ -7,6 +7,8 @@ pub mod clap;
use std::{future::Future, sync::Arc}; use std::{future::Future, sync::Arc};
use async_trait::async_trait; use async_trait::async_trait;
use bang::{General, Global, Specific};
use basic::{Described, Prefixed};
use euphoxide::{ use euphoxide::{
api::{self, Data, Message, MessageId, SendEvent, SendReply}, api::{self, Data, Message, MessageId, SendEvent, SendReply},
client::{ client::{
@ -118,6 +120,39 @@ pub trait Command<E = euphoxide::Error> {
async fn execute(&self, arg: &str, msg: &Message, ctx: &Context<E>) -> Result<Propagate, E>; async fn execute(&self, arg: &str, msg: &Message, ctx: &Context<E>) -> Result<Propagate, E>;
} }
pub trait CommandExt: Sized {
fn described(self) -> Described<Self> {
Described::new(self)
}
fn hidden(self) -> Described<Self> {
Described::hidden(self)
}
fn prefixed(self, prefix: impl ToString) -> Prefixed<Self> {
Prefixed::new(prefix, self)
}
fn global(self, name: impl ToString) -> Global<Self> {
Global::new(name, self)
}
fn general(self, name: impl ToString) -> General<Self> {
General::new(name, self)
}
fn specific(self, name: impl ToString) -> Specific<Self> {
Specific::new(name, self)
}
}
// Sadly this doesn't work: `impl<E, C: Command<E>> CommandExt for C {}`
// It leaves E unconstrained. Instead, we just implement CommandExt for all
// types. This is fine since it'll crash and burn once we try to use the created
// commands as actual commands. It also follows the spirit of adding trait
// constraints only where they are necessary.
impl<C> CommandExt for C {}
pub struct Commands<E = euphoxide::Error> { pub struct Commands<E = euphoxide::Error> {
commands: Vec<Box<dyn Command<E> + Sync + Send>>, commands: Vec<Box<dyn Command<E> + Sync + Send>>,
} }