Skip to content

How to implement a new Command?

JohnsonLee edited this page Apr 13, 2024 · 1 revision

Main Idea: Each command has its static infomation and instance. Basically, to implement a new command you need to implement two trait CommandInstance and CommandTypeInfo, respectively providing information about how to execute an instance of command and static information about command.

Suppose we are going to add a command call Foo in mod foo We use Command to hold static information about command:

#[derive(Clone)]
pub struct Command {
    /// command id i.e. command name
    id: CommandIdRef<'static>,
    create_instance_fn: CreateInstanceFn,
}

By implementing CommandTypeInfo trait for Foo, we can acquire the related Command. Usaually we just need to implement new to tell how to build a instance, and command to tell other related static information.

pub trait CommandTypeInfo: CommandInstance + Sized + 'static {
    /// Tell the system how to create instance
    fn new() -> Self;

    /// Static typing infomation of command, which is used to register the command
    fn command() -> &'static Command;

    /// Boxed version of `new`
    fn boxed() -> Box<dyn CommandInstance> {
        Box::new(Self::new())
    }

    fn id() -> CommandIdRef<'static> {
        Self::command().id
    }
}

We can implement command via the macro command_type_stub, then we have code below:

struct Foo;
impl CommandTypeInfo for Foo {
    fn new() -> Self{
        Foo
    }
    command_type_stub!{ id: "foo" }
}

Then implement CommandInstance for Foo:

#[asycn_trait]
impl CommandInstance for Foo {
    ...
}

Now we should first register the mod foo to GlobalCommandTable to let it know foo including commands. To do this, just modify the definition of GLOBAL_COMMAND_TABLE in commands.rs, add the mod foo inside register_mod!

pub static GLOBAL_COMMANDS_TABLE: Lazy<GlobalCommandTable> = register_mod! {..., foo};

Then to tell that Foo is a command, we should also register Foo to foo by using register! inside foo like below:

register! { Foo }

The relationship of Foo, Command, CommandInstance, CommandTypeInfo and GlobalCommandTable is shown as below:

image

Clone this wiki locally