回上级页面

命令行界面

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" {
            hm.insert("tangle", &args[x + 1]);
            break;
        }
    }
    println!("{}", hm["tangle"]);
}

上述代码使用了 Rust 标准库中的 Hash 表容器,我第一次用,幸无挫折。

clap 库

Rust 的第三方库 clap 为命令行参数解析提供了更为完善且友好的支持,但不幸的是,clap 演进幅度太大,新版本不兼容老版本,导致一些介绍 clap 2 的教程不适于 clap 4。我有心尝试 clap 4,但该版本要求 rustc 版本不能小于 1.7.0。我机器(Linux Mint)上的 rustc 最新版本是 1.66.1,不能满足要求,也不想太折腾,待日后再更新此节。

C 版本

用 C 语言编写命令行程序,可以手动解析,若需要 Hash 表存储解析结果,可使用 GLib 库提供的 GHashTable 结构及相关函数。

GLib 提供的命令行参数解析器以及 GNU Autotools(不妨将其理解为 Rust 的 Cargo) ,能实现与 Rust clap 库相当的功能,且在此基础上借助 GNU gettext 工具可实现命令行界面的国际化,详见拙文「如何写一个 GNU 风格的命令行程序」。

小结

在命令行程序参数解析方面,clap 库较 GLib 优越之处在于它支持以 YAML 格式文件的形式定义参数,从而使得程序代码更为简约,颇类似于一些 GUI 库支持以 XML 文件的形式定义图形界面。