34 个版本 (7 个稳定版)

2.2.0 2023 年 12 月 2 日
2.1.0 2022 年 4 月 16 日
2.0.0 2022 年 2 月 16 日
1.2.0 2022 年 2 月 10 日
0.2.5 2019 年 12 月 25 日

#54 in 命令行界面

Download history 1414/week @ 2024-03-14 1292/week @ 2024-03-21 1549/week @ 2024-03-28 1377/week @ 2024-04-04 1184/week @ 2024-04-11 1335/week @ 2024-04-18 1648/week @ 2024-04-25 1357/week @ 2024-05-02 1135/week @ 2024-05-09 1006/week @ 2024-05-16 813/week @ 2024-05-23 1138/week @ 2024-05-30 927/week @ 2024-06-06 1472/week @ 2024-06-13 1184/week @ 2024-06-20 829/week @ 2024-06-27

每月下载量 4,593
用于 22 crates

自定义许可协议

67KB
1.5K SLoC

seahorse

crates.io releases count issues count forks count license github actions CI

Logo

用 Rust 编写的最小化 CLI 框架

Join our Discord server!

特性

  • 易于使用
  • 无依赖
  • 类型化标志(Bool、String、Int、Float)

文档

在此处

用法

要使用 seahorse,请将以下内容添加到您的 Cargo.toml 中

[dependencies]
seahorse = "2.2"

示例

运行示例

$ git clone https://github.com/ksk001100/seahorse
$ cd seahorse
$ cargo run --example single_app -- --help
$ cargo run --example multiple_app -- --help

快速开始

$ cargo new cli
$ cd cli
$ echo 'seahorse = "*"' >> Cargo.toml
use seahorse::{App};
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let app = App::new(env!("CARGO_PKG_NAME"))
        .description(env!("CARGO_PKG_DESCRIPTION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .version(env!("CARGO_PKG_VERSION"))
        .usage("cli [args]")
        .action(|c| println!("Hello, {:?}", c.args));

    app.run(args);
}
$ cargo build --release
$ ./target/release/cli --help
$ ./target/release/cli John

多命令应用

use seahorse::{App, Context, Command};
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let app = App::new(env!("CARGO_PKG_NAME"))
        .description(env!("CARGO_PKG_DESCRIPTION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .version(env!("CARGO_PKG_VERSION"))
        .usage("cli [name]")
        .action(default_action)
        .command(add_command())
        .command(sub_command());

    app.run(args);
}

fn default_action(c: &Context) {
    println!("Hello, {:?}", c.args);
}

fn add_action(c: &Context) {
    let sum: i32 = c.args.iter().map(|n| n.parse::<i32>().unwrap()).sum();
    println!("{}", sum);
}

fn add_command() -> Command {
    Command::new("add")
        .description("add command")
        .alias("a")
        .usage("cli add(a) [nums...]")
        .action(add_action)
}

fn sub_action(c: &Context) {
    let sum: i32 = c.args.iter().map(|n| n.parse::<i32>().unwrap() * -1).sum();
    println!("{}", sum);
}

fn sub_command() -> Command {
    Command::new("sub")
        .description("sub command")
        .alias("s")
        .usage("cli sub(s) [nums...]")
        .action(sub_action)
}
$ cli John
Hello, ["John"]

$ cli add 32 10 43
85

$ cli sub 12 23 89
-124

通过标志进行分支处理

use seahorse::{App, Command, Context, Flag, FlagType, error::FlagError};
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let app = App::new(env!("CARGO_PKG_NAME"))
        .description(env!("CARGO_PKG_DESCRIPTION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .version(env!("CARGO_PKG_VERSION"))
        .usage("cli [name]")
        .action(default_action)
        .flag(
            Flag::new("bye", FlagType::Bool)
                .description("Bye flag")
                .alias("b"),
        )
        .flag(
            Flag::new("age", FlagType::Int)
                .description("Age flag")
                .alias("a"),
        )
        .command(calc_command());

    app.run(args);
}

fn default_action(c: &Context) {
    if c.bool_flag("bye") {
        println!("Bye, {:?}", c.args);
    } else {
        println!("Hello, {:?}", c.args);
    }

    if let Ok(age) = c.int_flag("age") {
        println!("{:?} is {} years old", c.args, age);
    }
}

fn calc_action(c: &Context) {
    match c.string_flag("operator") {
        Ok(op) => {
            let sum: i32 = match &*op {
                "add" => c.args.iter().map(|n| n.parse::<i32>().unwrap()).sum(),
                "sub" => c.args.iter().map(|n| n.parse::<i32>().unwrap() * -1).sum(),
                _ => panic!("undefined operator..."),
            };

            println!("{}", sum);
        }
        Err(e) => match e {
            FlagError::Undefined => panic!("undefined operator..."),
            FlagError::ArgumentError => panic!("argument error..."),
            FlagError::NotFound => panic!("not found flag..."),
            FlagError::ValueTypeError => panic!("value type mismatch..."),
            FlagError::TypeError => panic!("flag type mismatch..."),
        },
    }
}

fn calc_command() -> Command {
    Command::new("calc")
        .description("calc command")
        .alias("cl, c")
        .usage("cli calc(cl, c) [nums...]")
        .action(calc_action)
        .flag(
            Flag::new("operator", FlagType::String)
                .description("Operator flag(ex. cli calc --operator add 1 2 3)")
                .alias("op"),
        )
}
$ cli John
Hello, ["John"]

$ cli John --bye
Bye, ["John"]

$ cli John --age 10
Hello, ["John"]
["John"] is 10 years old

$ cli John -b -a=40
Bye, ["John"]
["John"] is 40 years old

$ cli calc --operator add 1 2 3 4 5
15

$ cli calc -op sub 10 6 3 2
-21

顶层错误处理

use seahorse::{ActionError, App, Context, Flag, FlagType};
use std::env;

fn main() {
    let args: Vec<String> = env::args().collect();
    let app = App::new(env!("CARGO_PKG_NAME"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .description(env!("CARGO_PKG_DESCRIPTION"))
        .usage("multiple_app [command] [arg]")
        .version(env!("CARGO_PKG_VERSION"))
        .action_with_result(|c: &Context| {
            if c.bool_flag("error") {
                Err(ActionError {
                    message: "ERROR...".to_string(),
                })
            } else {
                Ok(())
            }
        })
        .flag(
            Flag::new("error", FlagType::Bool)
                .description("error flag")
                .alias("e"),
        );

    match app.run_with_result(args) {
        Ok(_) => println!("OK"),
        Err(e) => match e {
            ActionError { message } => println!("{}", message),
        },
    };
}
$ cli
OK

$ cli --error
ERROR...

$ cli -e
ERROR...

贡献

请阅读 CONTRIBUTING.md 了解我们的行为准则和提交拉取请求的流程。

许可协议

本项目遵循 MIT 许可协议

行为准则

对 seahorse crate 的贡献是在贡献者协约的条款下组织的,seahorse 的维护者 @ksk001100 承诺将介入维护该行为准则。

无运行时依赖