2023 年 08 月 24 日
程序的功能略微复杂一些,在其运行时,通常需要用户提供一些信息。最简单的程序是命令行程序,其运行时所需信息的提供方式是命令行参数。rzeo 是拥有一些参数的命令行程序。例如以下命令
$ rzeo --tangle foo.rz --output foo.c
可从 foo.rz 文件中提取 C 程序代码并将其存于文件 foo.c。现在,我尚未实现 rzeo,但是并不妨碍写一个空壳的 rzeo,使之能够像上述命令那般运行。
Rust 标准库提供了std::env::args
函数可用于获取命令行程序的参数列表,例如
use std::env;
fn main() {
for x in env::args() {
println!("{}", x);
}
}
或
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
for x in args {
println!("{}", x);
}
}
皆可在终端显示命令行程序名及其所有参数。
命令行参数可采用键值对结构——Hash 表予以表示。对参数列表多次扫描,将目标结果存入 Hash 表便可实现参数解析。例如,对以下命令行:
$ rzeo --tangle foo.rz --output foo.c
获参数 --tangle
与其值 foo.rz
的过程如下:
use std::env;
use std::collections::HashMap;
fn main() {
let args: Vec<String> = env::args().collect();
let mut hm = HashMap::new();
for x in 1 .. args.len() {
if args[x] == "--tangle" {
.insert("tangle", &args[x + 1]);
hmbreak;
}
}
println!("{}", hm["tangle"]);
}
上述代码使用了 Rust 标准库中的 Hash 表容器,我第一次用,幸无挫折。
Rust 的第三方库 clap 为命令行参数解析提供了更为完善且友好的支持,但不幸的是,clap 演进幅度太大,新版本不兼容老版本,导致一些介绍 clap 2 的教程不适于 clap 4。我有心尝试 clap 4,但该版本要求 rustc 版本不能小于 1.7.0。我机器(Linux Mint)上的 rustc 最新版本是 1.66.1,不能满足要求,也不想太折腾,待日后再更新此节。
用 C 语言编写命令行程序,可以手动解析,若需要 Hash 表存储解析结果,可使用 GLib 库提供的 GHashTable 结构及相关函数。
GLib 提供的命令行参数解析器以及 GNU Autotools(不妨将其理解为 Rust 的 Cargo) ,能实现与 Rust clap 库相当的功能,且在此基础上借助 GNU gettext 工具可实现命令行界面的国际化,详见拙文「如何写一个 GNU 风格的命令行程序」。
在命令行程序参数解析方面,clap 库较 GLib 优越之处在于它支持以 YAML 格式文件的形式定义参数,从而使得程序代码更为简约,颇类似于一些 GUI 库支持以 XML 文件的形式定义图形界面。