7 个稳定版本
1.2.1 | 2019 年 5 月 2 日 |
---|---|
1.2.0 | 2019 年 4 月 30 日 |
#592 in 命令行界面
每月 24 次下载
1MB
1K SLoC
代码片段
其他语言
为什么是这个?
长期以来,在 Rust 中开发 CLI 很困难。社区提供了一系列解决方案。是的,它们很优秀,但并不简单。
受 commander.js 和 rocket.rs 的启发,这个 crate 诞生了。
特性
- API 友好
- 易于使用
- 支持近似动态语言
- 低性能损失
- 自动支持
--version
和--help
- 自动运行相应命令
限制
如果您想使用这个 crate,请确保您遵守以下规则:
- 使用
Rust 2018
(需要完整的 proc macro 支持,包括 [proc_macro] 和 [proc_macro_attribute]) - 使用
cargo
(cargo
会根据Cargo.toml
生成一些环境变量,我们需要这些) - 熟悉
Rust
(因为它是为Rust
开发的)
以下是我的版本作为参考:
cargo
: cargo 1.35.0-nightly (95b45eca1 2019-03-06)rustc
: rustc 1.35.0-nightly (e68bf8ae1 2019-03-11)Linux 内核
: 4.15.0-47-genericUbuntu
: 16.04
使用方法
安装 commander-rust
支持两种安装方式:从 Github
或 crates.io
。它们的区别在于 Github
提供的是最新版本但不稳定,而 crates.io
提供的是稳定版本但可能不是最新版本。
从 Github
安装
[dependencies.commander_rust]
git = "https://github.com/MSDimos/commander_rust"
branch = "master"
从 crates.io
安装
[dependencies]
commander_rust = "1.1.3" # or other version you want to install
使用它
我们提供了一个简单但完整的示例,您可以通过它学习所有内容。是的,就是这样。非常简单!
// this is required! Beacuse we used `run!()`, it's a proc_macro
#![feature(proc_macro_hygiene)]
// Only five items you will use
use commander_rust::{ Cli, command, option, entry, run };
// what's option? what's command?
// See `commander.js` and document of `commander-rust` for more!
// Note, types of parameters are not fixed, any type implemented `From<Raw>` is valid!
// So you can even use `rmdir(dir: i32, other_dirs: Vec<i32>, cli: Cli)` here.
// And `Cli` is not required! So you can miss it.
// See document of `commander-rust` for more details.
#[option(-s, --format <format>, "format output")]
#[option(-r, --recursive, "recursively")]
#[command(rmdir <dir> [otherDirs...], "remove files and directories")]
fn rmdir(dir: String, other_dirs: Option<Vec<String>>, cli: Cli) {
// get value of no-parameter options, using `has`
// get value if normal options, using `get`, `get_or`, `get_or_else`
// `get_or` and `get_or_else` can be using for specifying default value
// for the most time, I suggest you using `get_or` and `has`.
let format = cli.get_or("format", String::new("%s"));
if !cli.has("recursive") {
let silently = cli.get_or("silently", false);
if silently {
// delete all files silently
// just like `rm -rf /`
} else {
// tell the world I'm going to delete the files
}
} else {
// delete files recursively is slowly
// so drink a cup of coffee, relax.
}
}
// options here are public, options above `#[command]` are private
#[option(-s, --silently <silently>, "don't display anything")]
#[entry]
fn main() {
// Run it now!!!!!
let app = run!();
// printing app is same as you inputting `--help`.
println!("app is {:#?}", app);
}
试试吧
尝试输入 [pkg-name] --help
。
版本、描述和 CLI 名称是什么?
version
、description
、cli-name
的应用程序来自 Cargo.toml
。
例如
# part of Cargo.toml
[package]
name = "example-test"
version = "0.1.0"
description = "Using for test"
直接
如果您不想定义子命令,可以使用 #[direct]
。什么是 direct
?在某些情况下,例如,如果您想开发一个像 rm ./* -rf
这样可以调用的 CLI。如果没有 direct
,您只能使用子命令,看起来像 rm delete ./* -rf
。来吧!delete
是多余的,我们不希望这样!它应该是 rm -rf ./*
而不是 rm delete ./* -rf
。所以,现在是时候使用 #[direct]
。
/*
You can still define sub-command here
suc-command can work together with direct-func well
*/
// function name is whatever you like
// last parameter can be `CLI`, it's not necessary like `command`.
// `cli` can only get public options here.
#[direct(<a> <b> [c] [d])]
fn whatever_you_like(a: String, b: String, cli: Cli) {
println!("hello! {} {}", a, b);
}
现在,如果您输入 [pkg-name] 1 2 3
,CLI 将打印 hello! 1 2
。所以它允许您在某些简单情况下不再需要定义子命令。仅支持 1.2.x
或更高版本的 direct
。可以很好地与子命令一起工作,您可以使用它们两个一起。
错误
我无法保证它将在所有情况下都能完美工作。我的能力非常有限,测试不是我的专长,对此表示歉意。我在学习。所以如果您发现任何 BUG,请告诉我。谢谢。
示例
这里有两个完整的示例。一个是 cargo-bp,另一个是 hash。还有一个简单示例展示了 commander-rust
的所有用法,更多信息请参阅 ./examples
。
主页
正在开发中。请参阅 ./homepage
规则
您应该遵循几个规则。
- 所有
#[options]
应定义在#[command]
和#[entry]
之上。 - 不要定义重复选项!!!作为让步,您可以在不同的命令和入口处定义相同的选项。
- 私有选项对特定子命令可见。公共选项对所有子命令可见。
警告
此软件包是在使用 Ubuntu 16.04
开发的,我们无法假设所有平台都能很好地工作。如果您发现它在其他平台上无法很好地工作,请告诉我。
贡献
欢迎任何有用的贡献。您可以向我发送 pull 请求。
许可
GPL-3.0。因为开源是未来。