|
1 | 1 | # cmdline |
2 | 2 |
|
3 | | -C++23 命令行解析库,风格参考 clap。模块化设计,单 import,无裸指针 API。 |
4 | | - |
5 | | -- **C++23** 模块 |
6 | | -- **类型命名**:`ParsedArgs`(解析结果)、`OptionValue`(选项取值) |
7 | | -- **解析 API**:`parse(argc, argv)`、`parse_from(span<string>)`、`parse_from(string_view)`,支持多种输入 |
8 | | -- **子命令分发**:`on_run(lambda)` + `dispatch(parsed)`,也可分离构建后自行根据 `subcommand_name()` 分发 |
9 | | -- **全局选项**、`get_flag()` / `get_one()`、`std::expected` 解析结果 |
10 | | - |
11 | | -## 快速开始 |
12 | | - |
13 | | -```cpp |
14 | | -import std; |
15 | | -import cmdline; |
16 | | - |
17 | | -int main(int argc, char* argv[]) { |
18 | | - using namespace cmdline; |
19 | | - |
20 | | - auto app = App("myapp") |
21 | | - .version("1.0.0") |
22 | | - .about("My CLI") |
23 | | - .arg(Arg("input").help("Input file").required()) |
24 | | - .opt(Opt("verbose").short_name('v').long_opt("verbose").help("Verbose")) |
25 | | - .opt(Opt("config").long_opt("config").takes_value().value_name("FILE")); |
26 | | - |
27 | | - auto result = app.parse(argc, argv); |
28 | | - if (!result) { |
29 | | - if (result.error() == "help requested" || result.error() == "version requested") |
30 | | - return 0; |
31 | | - std::println("Error: {}", result.error()); |
32 | | - return 1; |
33 | | - } |
34 | | - const ParsedArgs& parsed = *result; |
35 | | - if (parsed.get_flag("verbose")) { /* ... */ } |
36 | | - if (auto c = parsed.get_one("config")) std::println("Config: {}", *c); |
37 | | - std::println("Input: {}", parsed.arg(0)); |
38 | | - return 0; |
39 | | -} |
40 | | -``` |
41 | | -
|
42 | | -## 多种输入 |
43 | | -
|
44 | | -```cpp |
45 | | -// C 风格 |
46 | | -auto result = app.parse(argc, argv); |
47 | | -
|
48 | | -// 字符串列表 |
49 | | -std::vector<std::string> args = {"myapp", "add", "python", "3.12"}; |
50 | | -auto result = app.parse_from(args); |
51 | | -
|
52 | | -// 单条命令行字符串(按空格/引号拆分) |
53 | | -auto result = app.parse_from("myapp add python 3.12 --yes"); |
54 | | -``` |
55 | | - |
56 | | -## 绑定分发(on_run + dispatch) |
57 | | - |
58 | | -子命令推荐用字符串链式:`.subcommand("name").about("...").arg(...).on_run(...)`;也可传入完整 `App` 对象。 |
59 | | - |
60 | | -```cpp |
61 | | -App app("demo"); |
62 | | -app.opt(Opt("yes").long_opt("yes").global().help("Auto confirm")) |
63 | | - .subcommand("add") |
64 | | - .about("Add a target") |
65 | | - .arg(Arg("target").required()) |
66 | | - .arg(Arg("version").required()) |
67 | | - .on_run([](const ParsedArgs& args) { |
68 | | - std::println("add: {}@{}", args.get_one("target").value_or(""), args.get_one("version").value_or("")); |
69 | | - }) |
70 | | - .subcommand("remove") |
71 | | - .about("Remove") |
72 | | - .arg(Arg("target").required()) |
73 | | - .on_run([](const ParsedArgs& args) { std::println("remove: {}", args.arg(0)); }); |
74 | | - |
75 | | -auto result = app.parse(argc, argv); |
76 | | -if (result) app.dispatch(*result); |
77 | | -``` |
78 | | -
|
79 | | -## 分离模式(自行分发) |
80 | | -
|
81 | | -```cpp |
82 | | -auto result = app.parse(argc, argv); |
83 | | -if (!result) return 1; |
84 | | -const ParsedArgs& parsed = *result; |
85 | | -if (parsed.has_subcommand()) { |
86 | | - auto sub = parsed.subcommand(); |
87 | | - if (sub && parsed.subcommand_name() == "add") { |
88 | | - const ParsedArgs& sub_args = sub->get(); |
89 | | - // ... |
90 | | - } |
91 | | -} |
92 | | -``` |
93 | | - |
94 | | -## 构建 |
| 3 | +C++23 命令行解析库,API 见名知意,单 import。 |
95 | 4 |
|
96 | 5 | ```bash |
97 | 6 | cd cmdline && xmake -P . |
98 | 7 | xmake run basic |
99 | | -xmake run with_dispatch -- add python 3.12 |
100 | | -xmake run parse_from_string |
| 8 | +xmake -y run cmdline_test # 测试(-y 自动安装 gtest) |
101 | 9 | ``` |
102 | 10 |
|
103 | | -测试需 Google Test,使用 **`xmake -y`** 可自动安装依赖(如 gtest)并编译: |
104 | | - |
105 | | -```bash |
106 | | -xmake -y # 自动确认并安装 gtest,编译全部(含测试) |
107 | | -xmake -y run cmdline_test # 编译并运行测试 |
108 | | -``` |
109 | | - |
110 | | -## CI |
111 | | - |
112 | | -GitHub Actions 在 `push` / `pull_request` 到 `main` 或 `master` 时自动构建并测试(见 [.github/workflows/ci.yml](.github/workflows/ci.yml)): |
113 | | - |
114 | | -- 安装 xmake(package 缓存)、build-essential |
115 | | -- 通过 [Xlings](https://d2learn.org/xlings-install.sh) 安装 GCC 15.1(C++23 模块) |
116 | | -- `xmake -y` 构建(含 gtest) |
117 | | -- `xmake run cmdline_test` 跑测试 |
118 | | -- 跑示例 `with_dispatch` 做冒烟检查 |
119 | | - |
120 | | -## API 概要 |
121 | | - |
122 | | -| 类型/方法 | 说明 | |
123 | | -|-----------|------| |
124 | | -| `App` | 根或子命令;`.version()`, `.author()`, `.about()`, `.arg()`, `.opt()`, `.subcommand(name\|App)`, `.on_run()`, `.parse()`, `.parse_from()`, `.dispatch()`, `.print_help()` | |
125 | | -| `Arg` | 位置参数;`.help()`, `.required()`, `.default_value()` | |
126 | | -| `Opt` | 选项;`.short_name()`, `.long_opt()`, `.help()`, `.takes_value()`, `.value_name()`, `.multiple()`, `.global()` | |
127 | | -| `ParsedArgs` | 解析结果;`.get_flag()`, `.get_one()`, `.opt()`, `.opt_or_empty()`, `.arg()`, `.arg_count()`, `.has_subcommand()`, `.subcommand_name()`, `.subcommand()` | |
128 | | -| `OptionValue` | 单个选项取值;`.value()`, `.value_or()`, `.is_set()` | |
129 | | - |
130 | | -解析返回 `std::expected<ParsedArgs, std::string>`。`-h`/`--help` 或 `--version` 时 error 为 `"help requested"` / `"version requested"`,可据此退出 0。 |
| 11 | +详见 [docs/api.md](docs/api.md)。 |
0 commit comments