#命令行 #CLI # #命令行工具

fncli

一个用于简化编写简单命令行应用程序的属性宏

9个版本

0.3.4 2023年3月22日
0.3.3 2023年3月22日
0.3.2 2023年1月17日
0.3.1 2022年12月3日
0.1.0 2022年11月28日

#624 in 命令行界面

Download history 1/week @ 2024-03-08 35/week @ 2024-03-29 12/week @ 2024-04-05

每月57次下载
用于 chickensources

MIT/Apache

10KB
165

fncli

一个用于简化编写简单命令行应用程序的属性宏。

示例

#[fncli::cli]
fn main(a: i32, b: i32) {
    println!("{}", a + b);
}
$ cargo run 1 2
3
$ cargo run 1
missing argument: `b: i32`

USAGE:
    target/debug/examples/add <a: i32> <b: i32>
$ cargo run 1 2 3
too many arguments (expected 2)

USAGE:
    target/debug/examples/add <a: i32> <b: i32>
$ cargo run 1 a
failed to parse argument: `b: i32`: ParseIntError { kind: InvalidDigit }

USAGE:
    target/debug/examples/add <a: i32> <b: i32>

对于更完整的示例,请参阅时间流逝示例

工作原理

fn main() {
    let (a, b) = {
        let mut args = std::env::args();

        let cmd = args.next().expect("should have a command name");

        let exit = |err: &str| -> ! {
            eprintln!("{err}");
            eprintln!();
            eprintln!("USAGE:\n\t{cmd} <a: i32> <b: i32>");
            std::process::exit(1)
        };

        let tuple = (
            i32::from_str(
                &args
                    .next()
                    .unwrap_or_else(|| exit("missing argument: `a: i32`")),
            )
            .unwrap_or_else(|e| exit(&format!("failed to parse argument `a: i32` ({e:?})"))),
            i32::from_str(
                &args
                    .next()
                    .unwrap_or_else(|| exit("missing argument: `b: i32`")),
            )
            .unwrap_or_else(|e| exit(&format!("failed to parse argument `b: i32` ({e:?})"))),
        );

        if args.next().is_some() {
            exit("too many arguments (expected 2)");
        }

        tuple
    };

    {
        println!("{}", a + b);
    }
}

生成的代码非常简单,与手动编写的代码差别不大。

依赖项

~280–730KB
~17K SLoC