3 个版本
0.0.2 | 2020年2月25日 |
---|---|
0.0.1 | 2020年2月25日 |
0.0.0 | 2020年2月7日 |
#170 in #subcommand
3KB
60 代码行数(不含注释)
Argh 演示
真正的知识来源于实践。
最近,我注意到一个名为 "argh" 的命令行参数解析工具,它轻量级、易于使用,并且非常人性化。
我喜欢它的两个原因
- 代码量小,简单直观
- 巧妙地使用 "Rust" 语法
在这里,我将从用户的角度来谈谈 "argh" 的使用,作为我自己一个小型的 "提示板"。
命令行参数
首先,让我们创建一个新的项目。自然地,使用 cargo new <argh-demo>
。
然后,像这样将 argh 添加到我们的依赖项中
[dependencies]
argh = "0.1"
让我们一起来做一些事情,比如实现一个简单的命令行加法器?就像 "a + b"。显然,我们的函数接受两个参数,num1
和 num2
。
fn add(num1: u16, num2: u16) {
println!(arg1 + arg2);
}
看看 argh 是如何做的
#[derive(FromArgs)]
/// Add two numbers
struct DemoCli {
/// the first number.
#[argh(option)]
num1: u16,
/// the second number
#[argh(option)]
num2: u16,
}
然后在主函数中将它们连接在一起。
fn main() {
let cli: DemoCli = argh::from_env();
add(cli.num1, cli.num2);
}
现在,让我们尝试运行 cargo run
看看会发生什么
Required options not provided:
--num1
--num2
尝试 --help
选项,target / debug / argh-demo --help
Usage: target/debug/argh-demo --num1 <num1> --num2 <num2>
Add two numbers
Options:
--num1 the first number.
--num2 the second number
--help display usage information
嗯,看起来我们不得不添加所有选项 target/debug/argh-demo --num1 1 --num2 2
:
1 + 2 = 3
子命令
看起来不错,但如果我们目标是完整的计算器,可以通过子命令选择功能,例如 argh-demo add --num1 1-num2 2
,这将使我们的设计有所改变。
让我们看看如何修改代码
-
首先,在
DemoCli
中声明一个名为subcommand
的子命令集。#[derive(FromArgs)] /// A simple calculation tool struct DemoCli { #[argh(subcommand)] subcommand: SubCommands, }
-
定义包含
Add
选项的SubCommands
结构#[derive(FromArgs, PartialEq, Debug)] #[argh(subcommand)] enum SubCommands { Add(AddOptions), }
-
为
AddOptions
添加内容#[derive(FromArgs, PartialEq, Debug)] /// Add two numbers #[argh(subcommand, name = "add")] pub struct AddOptions { /// the first number. #[argh(option)] num1: u16, /// the second number #[argh(option)] num2: u16, }
显然,你只需要在主函数中重写调用部分
match cli.subcommand {
SubCommands::Add(options) => {
add(options.num1, options.num2);
}
};
运行 cargo build && ./target/debug/argh-demo --help
来查看我们如何使用这个改进版本。
Usage: ./target/debug/argh-demo <command> [<args>]
A simple calculation tool
Options:
--help display usage information
Commands:
add Add two numbers
继续使用 1 + 2 = 3
来尝试,target / debug / argh-demo --num1 1 --num2 2
1 + 2 = 3
更好的结构
如果我们的程序有很多选项/子命令需要组织,放在一个文件里会显得很乱。想象一下像 cargo
这样的程序是如何做到的。它们在 commands
文件夹中为每个子命令都设置了单独的文件。
如果我们引入一个 sub
子命令,程序结构将看起来像这样。
├── Cargo.lock
├── Cargo.toml
├── README.md
├── src
│ ├── commands
│ │ ├── add.rs
│ │ ├── mod.rs
│ │ └── sub.rs
│ └── main.rs
由于子命令和相应的 execute
函数都应该移动到 commands
下的相应文件中,所以 main.rs
将会更加简洁
//! Just a demo for argh.
use argh::FromArgs;
mod commands;
#[derive(FromArgs)]
/// A simple calculation tool
struct DemoCli {
#[argh(subcommand)]
subcommand: SubCommands,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum SubCommands {
Add(commands::add::AddOptions),
Sub(commands::sub::SubOptions),
}
fn main() {
let cli: DemoCli = argh::from_env();
match cli.subcommand {
SubCommands::Add(options) => {
commands::add::execute(options);
}
SubCommands::Sub(options) => {
commands::sub::execute(options);
}
};
}
所以很明显,add
和 sub
模块应该暴露在 commands mod.rs
中。
pub mod add;
pub mod sub;
由于我们将选项整体传递给 execute
函数,因此需要相应地修改 add
模块
use argh::FromArgs;
#[derive(FromArgs, PartialEq, Debug)]
/// Add two numbers
#[argh(subcommand, name = "add")]
pub struct AddOptions {
/// the first number.
#[argh(option)]
num1: u16,
/// the second number
#[argh(option)]
num2: u16,
}
pub fn execute(options: AddOptions) {
println!(
"{} + {} = {}",
options.num1,
options.num2,
options.num1 + options.num2
);
}
下一步只是编写一个简单的 sub
模块
use argh::FromArgs;
#[derive(FromArgs, PartialEq, Debug)]
/// Sub two numbers
#[argh(subcommand, name = "sub")]
pub struct SubOptions {
/// the first number.
#[argh(option)]
num1: i16,
/// the second number
#[argh(option)]
num2: i16,
}
pub fn execute(options: SubOptions) {
println!(
"{} - {} = {}",
options.num1,
options.num2,
options.num1 - options.num2
);
}
像往常一样,使用 --help
选项查看用法
Usage: target/debug/argh-demo <command> [<args>]
A simple calculation tool
Options:
--help display usage information
Commands:
add Add two numbers
sub Sub two numbers
最后再次测试函数
-
target/debug/argh-demo add --num1 1 --num2 2
:1 + 2 = 3
-
target/debug/argh-demo sub --num1 1 --num2 2
:1 - 2 = -1
依赖项
~0.5–1MB
~24K SLoC