1 个不稳定版本

0.1.0 2023 年 1 月 20 日

#2306 in Rust 模式

BSD-1-Clause

27KB
285

Clap Action Command

一个基于 Clap 解析器的命令映射模式,可以轻松配置和调度模块化子命令。这通过减少添加或修改附加子命令所需的接触点,使得构建和修改大型 CLI 项目更加直观。

通过实现 ActionCommand 特性来定义模块化子命令。通过将其放入 CommandMap 来调度模块化子命令。

use std::error::Error;
use clap::{Arg, ArgMatches, builder::NonEmptyStringValueParser, Command};
use clap_action_command::{
    ActionCommand, CommandMap, get_one, vec1::{Vec1, vec1}
};

static NAME_ARG: &str = "name";

struct HelloWorldCommand {}

impl ActionCommand for HelloWorldCommand {
    fn name(&self) -> &'static str {
        "hello-world"
    }

    fn command(&self, command: Command) -> Command {
        command
            .about("Say hello to the world")
            .alias("h")
            .arg(
                Arg::new(NAME_ARG)
                    .short('n')
                    .value_name("NAME")
                    .required(false)
                    .value_parser(NonEmptyStringValueParser::new())
            )
    }

    fn action(
            &self, matches: Vec1<&ArgMatches>
    ) -> Result<(), Box<dyn Error>> {
        if let Some(name) = get_one::<String>(&matches, NAME_ARG) {
            println!("Hello, {}!", name);
        } else {
            println!("Hello, world!");
        }

        Ok(())
    }
}

let command_map = CommandMap::builder()
    .push(HelloWorldCommand {})
    // adding a new subcommand is as easy as referencing it here
    .build();
let command = Command::new("my-program").subcommands(command_map.commands());
let matches = command.get_matches_from([
    "my-program", "hello-world", "-n", "Steeve"
]);
command_map.dispatch(vec1![&matches]);

关于异步

Tokio 示例在 main 函数上放置一个属性。

#[tokio::main]
fn main() {
    println!("Hello, world!");
}

ActionCommand 然而,不是异步的。将 Tokio 属性移动到 ActionCommand 下方以使用 ActionCommand 启动异步程序。

struct AsyncCommand {}

impl AsyncCommand {
    #[tokio::main]
    async fn async_action(&self) -> Result<(), Error> {
        println!("Hello, world!");

        Ok(())
    }
}

impl ActionCommand for AsyncCommand {
    fn name(&self) -> &'static str {
        "async-command"
    }

    fn command(&self, command: Command) -> Command {
        command
            .about("Say hello to the world")
    }

    fn action(
        &self, matches: Vec1<&ArgMatches>,
    ) -> Result<(), Box<dyn Error>> {
        self.async_action()?;

        Ok(())
    }
}

许可证

我希望无论你是谁,你在做什么,或者你在哪个环境中工作,你都能使用这个软件 - 希望你用它来做好事而不是坏事!为此,Clap Action Command 源代码在 1-clause BSD 许可证下发布,并可请求其他许可证。祝编码愉快!

依赖项

~2.5MB
~56K SLoC