English | 中文
Commander-CPP 是一个仿照 commander.js 实现的 C++ 命令行解析库。它提供了简洁的链式 API,用于定义命令、选项和参数,支持子命令、默认值、多值选项等功能。
- 🎯 链式 API 设计,简洁易用
- 📦 单头文件,无外部依赖
- 🔧 支持选项(单值、多值、布尔值)
- 📝 支持参数(必需参数、可选参数、多值参数)
- 🌲 支持子命令和嵌套命令
- ⚙️ 支持默认值
- 📖 自动生成帮助信息
- 🔍 详细的错误处理和日志系统
- 🎨 支持选项别名和组合(如
-abc)
将 commander_cpp.hpp 文件复制到您的项目中,并在代码中包含它:
#include "commander_cpp.hpp"
#include "commander_cpp.hpp" using namespace COMMANDER_CPP; int main(int argc, char **argv) { Command("example") .version("1.0.0") ->description("一个示例命令行应用") ->option("-n --name <name>", "你的名字") ->action([](Vector<Variant> args, Map<String, Variant> opts) { if (opts.find("name") != opts.end()) { std::cout << "Hello, " << std::get<String>(opts["name"]) << "!" << std::endl; } else { std::cout << "Hello, World!" << std::endl; } }) .parse(argc, argv); return 0; }
运行示例:
$ ./example -n Alice Hello, Alice! $ ./example --help Usage: example [options] 一个示例命令行应用 Options: -V, --version out put version number. -n, --name <name> 你的名字 -h, --help
选项使用 - 或 -- 前缀,支持以下格式:
--option- 布尔选项-o --option- 带别名的布尔选项--option <value>- 必需值的选项--option [value]- 可选值的选项--option <values...>- 多值选项(至少一个)--option [values...]- 多值选项(可选)
参数不使用前缀,支持以下格式:
<arg>- 必需参数[arg]- 可选参数<args...>- 多值必需参数[args...]- 多值可选参数
Command("app") .option("-s --single <value>", "单值选项") ->option("-m --multi <values...>", "多值选项") ->option("-b --boolean", "布尔选项") ->option("-n --number <num>", "数字选项", 42) // 带默认值 ->action([](Vector<Variant> args, Map<String, Variant> opts) { // 获取单值选项 if (opts.find("single") != opts.end()) { auto value = std::get<String>(opts["single"]); std::cout << "Single: " << value << std::endl; } // 获取多值选项 if (opts.find("multi") != opts.end()) { auto values = std::get<std::vector<VariantBase>>(opts["multi"]); for (const auto &val : values) { std::cout << std::get<String>(val) << " "; } std::cout << std::endl; } // 获取布尔选项 if (opts.find("boolean") != opts.end()) { std::cout << "Boolean enabled" << std::endl; } });
使用示例:
$ ./app -s value1
$ ./app --single value1
$ ./app -m file1.txt file2.txt file3.txt
$ ./app -b
$ ./app -bs value1 # 组合选项Command("copy") .argument("<from>", "源文件") ->argument("[to]", "目标文件", "default.txt") // 带默认值 ->action([](Vector<Variant> args, Map<String, Variant> opts) { auto from = std::get<String>(args[0]); std::cout << "From: " << from << std::endl; if (args.size() > 1) { auto to = std::get<String>(args[1]); std::cout << "To: " << to << std::endl; } });
使用示例:
$ ./copy source.txt $ ./copy source.txt target.txt
Command cmd("git"); cmd.version("1.0.0") ->description("Git 命令行工具") // 添加一个子命令,返回子命令指针,继续链式调用时,是向子命令添加选项或参数 ->command("add <files...>", "添加文件到暂存区") ->option("-f --force", "强制添加") ->action([](Vector<Variant> args, Map<String, Variant> opts) { auto files = std::get<std::vector<VariantBase>>(args[0]); std::cout << "Adding files..." << std::endl; for (const auto &file : files) { std::cout << " " << std::get<String>(file) << std::endl; } }); // 添加另一个子命令 cmd.command("commit", "提交更改") ->option("-m --message <msg>", "提交信息") ->action([](Vector<Variant> args, Map<String, Variant> opts) { if (opts.find("message") != opts.end()) { auto msg = std::get<String>(opts["message"]); std::cout << "Commit: " << msg << std::endl; } });
使用示例:
$ ./git add file1.txt file2.txt
$ ./git add -f file.txt
$ ./git commit -m "Initial commit"Commander-CPP 自动识别并转换以下类型:
Command("types") .option("-i --int <num>", "整数") ->option("-d --double <num>", "浮点数") ->option("-b --bool <val>", "布尔值") ->option("-s --string <text>", "字符串") ->action([](Vector<Variant> args, Map<String, Variant> opts) { // 自动类型转换 auto intVal = std::get<int>(opts["int"]); // 42 auto doubleVal = std::get<double>(opts["double"]); // 3.14 auto boolVal = std::get<bool>(opts["bool"]); // true/false auto strVal = std::get<String>(opts["string"]); // "text" });
使用示例:
$ ./types -i 42 -d 3.14 -b true -s helloclass CustomLogger : public Logger { public: virtual Logger *error(const String &msg) override { std::cerr << "[ERROR] " << msg << std::endl; return this; } virtual Logger *warn(const String &msg) override { std::cerr << "[WARN] " << msg << std::endl; return this; } virtual Logger *debug(const String &msg) override { std::cout << "[DEBUG] " << msg << std::endl; return this; } virtual Logger *print(const String &msg) override { std::cout << msg << std::endl; return this; } }; int main(int argc, char **argv) { CustomLogger logger; Command("app", &logger) .option("-v --verbose", "详细输出") ->parse(argc, argv); return 0; }
支持短选项组合(类似 tar -xzvf):
Command("app") .option("-a --option-a", "选项 A") ->option("-b --option-b", "选项 B") ->option("-c --option-c <value>", "选项 C") ->action([](Vector<Variant> args, Map<String, Variant> opts) { if (opts.find("option-a") != opts.end()) { std::cout << "A enabled" << std::endl; } if (opts.find("option-b") != opts.end()) { std::cout << "B enabled" << std::endl; } });
使用示例:
$ ./app -ab # 同时启用 A 和 B $ ./app -abc value # 启用 A、B,并为 C 设置值
基于 main.cpp 中的集成测试,这是一个完整的待办事项应用示例:
#include "commander_cpp.hpp" using namespace COMMANDER_CPP; int main(int argc, char **argv) { Command cmd("todo"); cmd.version("1.0.0") ->description("待办事项管理工具") // 添加子命令 ->command("add <todos...>", "添加待办事项") ->option("-d --done", "标记为已完成") ->option("-p --priority", "设置为高优先级") ->action([](Vector<Variant> args, Map<String, Variant> opts) { auto todos = std::get<std::vector<VariantBase>>(args[0]); for (const auto &todo : todos) { std::cout << "Added: " << std::get<String>(todo); if (opts.find("done") != opts.end()) { std::cout << " [DONE]"; } if (opts.find("priority") != opts.end()) { std::cout << " [HIGH]"; } std::cout << std::endl; } }); cmd.command("rm", "删除待办事项") ->argument("<index...>", "待办事项索引") ->option("-l --level <value>", "删除级别") ->action([](Vector<Variant> args, Map<String, Variant> opts) { auto indices = std::get<std::vector<VariantBase>>(args[0]); for (const auto &idx : indices) { std::cout << "Removed: " << std::get<String>(idx) << std::endl; } }); cmd.parse(argc, argv); return 0; }
使用示例:
$ ./todo add "学习 C++" "写代码" -p Added: 学习 C++ [HIGH] Added: 写代码 [HIGH] $ ./todo rm 1 2 Removed: 1 Removed: 2 $ ./todo --help Usage: todo [options] 待办事项管理工具 Options: -V, --version out put version number. -h, --help Commands: add [options] <todos...> 添加待办事项 rm [options] <index...> 删除待办事项
项目包含完整的测试套件(见 src/main.cpp),覆盖以下场景:
| 测试用例 | 描述 |
|---|---|
| VersionTest | 验证版本信息输出 |
| DescriptionTest | 验证帮助信息生成 |
| OptionTest | 测试单值和多值选项解析 |
| ArgumentTest | 测试必需和可选参数 |
| SubCommandTest | 测试子命令功能 |
| DefaultValueTest | 测试默认值机制 |
| MultiValueOptionTest | 测试多值选项解析 |
| ErrorHandlingTest | 测试错误处理 |
| ComplexOptionTest | 测试选项组合 |
| IntegratedTest | 集成测试 |
运行测试:
$ xmake
$ ./build/macosx/arm64/debug/commander-cpp
$ ./build/macosx/arm64/debug/commander-cpp -i # 显示详细信息项目使用 xmake 构建:
# 安装 xmake $ brew install xmake # 构建项目 $ xmake # 运行测试 $ xmake run commander-cpp
commander-cpp/
├── src/
│ ├── commander_cpp.hpp # 核心库(单头文件)
│ └── main.cpp # 测试用例
├── build/ # 构建输出
├── xmake.lua # 构建配置
└── README.md # 本文档
- 支持 C++17 或更高版本
- 支持配置文件读取
欢迎提交 Issue 和 Pull Request!
MIT License