C++命令行解析库CLI11介绍
本篇文章主要提炼自github上CLI11的官方文档,取出自己感兴趣的内容,记录下来方便以后使用
简单介绍
CLI11是一个基于C++开发的命令行解析库,目前最新版本1.9
其优点:
- 使用很方便,只需要
#include <CLI11.hpp>
,当然也可以使用cmake编译版本 - 跨平台,支持广泛(不需要C++11以上的版本支持)
- 支持subcommand;支持重复options
关于编译
g++ -std=c++11 xx.cpp -I path_with_CLI11 -o app
(path_with_CLI11是一个路径,其内有CLI11.hpp, app是编译后的可执行程序名)
运行:
需要提示信息的时候运行./app -h
一个简单的例子
1 |
|
只接受一个可选参数-p
CLI::App 是与库的所有交互的基础
CLI11_PARSE 宏内部执行app.parse(argc,argv)对命令行参数解析,出错时抛出ParseError,然后捕获异常,打印错误信息并退出程序
主要功能
位置参数
即必须参数,使用方法是add_xxx方法的第一个参数如”-a” 把”-“ 去掉,换成有意义的名字,如”outputDir”
位置参数就是没有这些参数就无法运行,没有默认值;多个位置参数按定义顺序传递
flags
命令行输入只填flag名字就行,不接受参数;函数为add_flag,有以下三种类型:
- boolean flags绑定flag -f 到布尔变量my_flag,默认是flase,如果用户输入了-f 则为true
1
2bool my_flag;
app.add_flag("-f", my_flag, "Optional description"); - integer flags同样的绑定,范围变成整数
1
2int my_flag;
app.add_flag("-f", my_flag, "Optional description"); pure flags
1
CLI::Option* my_flag = app.add_flag("-f", "Optional description");
使用my_flag->count()来确定值是true/false,默认为0则false,大于等于1次则true;也可以bool(*my_flag)来使用
所有add_ 格式的函数都返回CLI::Option类型,因此可以*链式调用,使代码更简约
- 其他
有callback flags,add_flag_function()可以打印每个参数输入了多少次
每个add_*方法的第一个参数,即指定的命令参数,可以有多个名字,逗号分隔即可,如”-a,—alpha,-b”;另外一个比较有用的是->ignore_case() 方法,忽略大小写,方便用户输入
多个参数可以组合如”-i -a -b”等价于”-iab”
options
与flags区别就是接受参数;函数为add_option
基本形式:
1 | int int_option = 0; |
其行为:绑定选项-i到int_option,解析其后的数据转换为整型,类型不对会失败;如果没有此选项则使用初始值
可接受类型包括:整型/浮点/字符串/vector/函数
vectors of options
接受多个值,直到下一个值不合法;也可以用->expected(N)指定需要几个值
如果出现重复option,会进行组合,即”-v 1 2 -v 3 4”等同于”-v 1 2 3 4”(新版本才支持此功能)
修改option属性
链式使用,当作装饰器,可以同时添加多个装饰
列举几个可能会常用到的:
- ->required() 必须指定
- ->expected(N) 参数个数
- ->check(type)
- CLI::ExistingFile 检查文件是否存在
- CLI::ExistingDirectory 目录是否存在
- CLI::NonexistentPath 需要目录不存在
- CLI::Range(min,max) 指定范围
特殊选项:
- sets
使用集合来限定输入范围;如果输入不在集合范围内,会打印提示信息1
2int val;
app.add_set("--even", val, {0,2,4,6,8}); - complex number 复数,可接受1-2个参数,不给默认是0
1
2std::complex<float> val;
app.add_complex("--cplx", val); - optional 可选参数
- windows风格 /a /f …
Validators 验证器
验证器有两种形式
- transform 变异? 接受string,返回修改过的string
- check 非变异?
- 接受const string,返回修改过的string
- struct CLI::Validator的子类
常用check来检查路径/文件是否存在,以及输入是否在一个range内
subcommand 子命令
子命令就是包含了一系列选项的一个关键字,如git commit/clone 这里面的commit clone后面还可以跟各种选项,他们就是git程序的子命令
子命令的类类型和App相同,因此可以任意嵌套
关于App的功能
- 使用它来创建options
- 设置页脚,在-h下面展示,比如显示下个性签名 app.footer(“xx”)
- 设置帮助信息
添加子命令
CLI::App* sub = app.add_subcommand("sub", "This is a subcommand");
第一个参数就是子命令的名字,第二个参数是描述
检查子命令是否被使用
- if(*sub) …
- if(sub->parsed()) …
- if(app.got_subcommand(sub)) …
- if(app.got_subcommand(“sub”)) …
设置必须的子命令个数,只传一个参数则限定了个数
app.require_subcommand(/ min / 0, / max / 1);
特殊模式
- allow_extras() 允许出现多余的option而不报错,多余的值保存到.remaining()
- fallthrough 将subcommand未匹配的option转给parnet command解析(默认不会fallthrough)
- prefix command 遇到未知option时停止解析,即使其他未知选项可以匹配,也将被忽略
实例
编写个实例,把subcommand flag 各种option,check等常用功能都演示一遍
代码:
1 | //把CLI11.hpp放到当前目录下 |
编译:g++ -std=c++11 run.cpp -o myapp
用的gcc4.8
运行:
-h 查看提示
给正确的参数
给错误参数
其他
配置文件
允许读写配置文件
格式化帮助信息
允许定制自己的帮助打印信息
app.get_formatter() 获取当前格式
- column_width(width) 设置列的宽度
- lable(key, value) 将lable设置一个不同的值
- 例子
1
2app.get_formatter()->column_width(40);
app.get_formatter()->label("REQUIRED", "(MUST HAVE)");
subclassing
部分的替换格式
高级主题
环境变量
作用是,如果命令行参数没有给定,则从环境变量中获取,如果存在的话
1 | std::string opt; |
option之间的依赖/互斥关系
a->nees(b) a依赖b
a->excludes(c) a与c不共存
自定义
custom option callbacks
custom converters