You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2207 lines
77 KiB

2 years ago
  1. clipp - command line interfaces for modern C++
  2. ===========================================================
  3. [![Linux build status](https://travis-ci.org/muellan/clipp.svg?branch=master)](https://travis-ci.org/muellan/clipp) [![MSVC build status](https://ci.appveyor.com/api/projects/status/ci29ngpfks980i7g?svg=true)](https://ci.appveyor.com/project/muellan/clipp)
  4. Easy to use, powerful and expressive command line argument handling for C++11/14/17 contained in a **single header file**.
  5. - options, options+value(s), positional values, positional commands, nested alternatives, decision trees, joinable flags, custom value filters, ...
  6. - documentation generation (usage lines, man pages); error handling
  7. - lots of examples; large set of tests
  8. - ### [Quick Reference Table](#quick-reference)
  9. - ### [Overview (short examples)](#overview)
  10. - ### [Detailed Examples](#examples)
  11. - #### [Why yet another library for parsing command line arguments?](#motivation) / [Design goals](#design-goals)
  12. - #### [Requirements / Compilers](#requirements)
  13. ## Quick Intro
  14. ### Simple Use Case — Simple Setup!
  15. Consider this command line interface:
  16. ```man
  17. SYNOPSIS
  18. convert <input file> [-r] [-o <output format>] [-utf16]
  19. OPTIONS
  20. -r, --recursive convert files recursively
  21. -utf16 use UTF-16 encoding
  22. ```
  23. Here is the code that defines the positional value ```input file``` and the three options ```-r```, ```-o``` and ```-utf16```. If parsing fails, the above default man page-like snippet will be printed to stdout.
  24. ```cpp
  25. #include <iostream>
  26. #include "clipp.h"
  27. using namespace clipp; using std::cout; using std::string;
  28. int main(int argc, char* argv[]) {
  29. bool rec = false, utf16 = false;
  30. string infile = "", fmt = "csv";
  31. auto cli = (
  32. value("input file", infile),
  33. option("-r", "--recursive").set(rec).doc("convert files recursively"),
  34. option("-o") & value("output format", fmt),
  35. option("-utf16").set(utf16).doc("use UTF-16 encoding")
  36. );
  37. if(!parse(argc, argv, cli)) cout << make_man_page(cli, argv[0]);
  38. // ...
  39. }
  40. ```
  41. ### A More Complex Example:
  42. ```man
  43. SYNOPSIS
  44. finder make <wordfile> -dict <dictionary> [--progress] [-v]
  45. finder find <infile>... -dict <dictionary> [-o <outfile>] [-split|-nosplit] [-v]
  46. finder help [-v]
  47. OPTIONS
  48. --progress, -p show progress
  49. -o, --output <outfile> write to file instead of stdout
  50. -split, -nosplit (do not) split output
  51. -v, --version show version
  52. ```
  53. This CLI has three alternative commands (```make```, ```find```, ```help```), some positional value-arguments (```<wordfile>```, ```<infile>```) of which one is repeatable, a required flag with value-argument (```-dict <dictionary>```), an option with value-argument (```-o <outfile>```), one option with two alternatives (```-split```, ```-nosplit```) and two conventional options (```-v```, ```--progress```).
  54. Here is the code that defines the interface, generates the man page snippet above *and* handles the parsing result:
  55. ```cpp
  56. using namespace clipp; using std::cout; using std::string;
  57. //variables storing the parsing result; initialized with their default values
  58. enum class mode {make, find, help};
  59. mode selected = mode::help;
  60. std::vector<string> input;
  61. string dict, out;
  62. bool split = false, progr = false;
  63. auto dictionary = required("-dict") & value("dictionary", dict);
  64. auto makeMode = (
  65. command("make").set(selected,mode::make),
  66. values("wordfile", input),
  67. dictionary,
  68. option("--progress", "-p").set(progr) % "show progress" );
  69. auto findMode = (
  70. command("find").set(selected,mode::find),
  71. values("infile", input),
  72. dictionary,
  73. (option("-o", "--output") & value("outfile", out)) % "write to file instead of stdout",
  74. ( option("-split" ).set(split,true) |
  75. option("-nosplit").set(split,false) ) % "(do not) split output" );
  76. auto cli = (
  77. (makeMode | findMode | command("help").set(selected,mode::help) ),
  78. option("-v", "--version").call([]{cout << "version 1.0\n\n";}).doc("show version") );
  79. if(parse(argc, argv, cli)) {
  80. switch(selected) {
  81. case mode::make: /* ... */ break;
  82. case mode::find: /* ... */ break;
  83. case mode::help: cout << make_man_page(cli, "finder"); break;
  84. }
  85. } else {
  86. cout << usage_lines(cli, "finder") << '\n';
  87. }
  88. ```
  89. ## Quick Reference
  90. Below are a few examples that should give you an idea for how clipp works.
  91. Consider this basic setup with a few variables that we want to set using
  92. command line arguments:
  93. ```cpp
  94. int main(int argc, char* argv[]) {
  95. using namespace clipp;
  96. // define some variables
  97. bool a = false, b = false;
  98. int n = 0, k = 0;
  99. double x = 0.0, y = 0.0;
  100. std::vector<int> ids;
  101. auto cli = ( /* CODE DEFINING COMMAND LINE INTERFACE GOES HERE */ );
  102. parse(argc, argv, cli); //excludes argv[0]
  103. std::cout << usage_lines(cli, "exe") << '\n';
  104. }
  105. ```
  106. | Interface (`usage_lines`) | Code (content of `cli` parentheses )
  107. | -------------------------- | ------------------------------------
  108. | ` exe [-a] ` | ` option("-a", "--all").set(a)`
  109. | ` exe [--all] ` | ` option("--all", "-a", "--ALL").set(a)`
  110. | ` exe [-a] [-b] ` | ` option("-a").set(a), option("-b").set(b)`
  111. | ` exe -a ` | ` required("-a").set(a)`
  112. | ` exe [-a] -b ` | ` option("-a").set(a), required("-b").set(b)`
  113. | ` exe [-n <times>] ` | ` option("-n", "--iter") & value("times", n) `
  114. | ` exe [-n [<times>]] ` | ` option("-n", "--iter") & opt_value("times", n) `
  115. | ` exe -n <times> ` | ` required("-n", "--iter") & value("times", n) `
  116. | ` exe -n [<times>] ` | ` required("-n", "--iter") & opt_value("times", n) `
  117. | ` exe [-c <x> <y>]` | ` option("-c") & value("x", x) & value("y", y)`
  118. | ` exe -c <x> <y> ` | ` required("-c") & value("x", x) & value("y", y)`
  119. | ` exe -c <x> [<y>] ` | ` required("-c") & value("x", x) & opt_value("y", y)`
  120. | ` exe [-l <lines>...] ` | ` option("-l") & values("lines", ids) `
  121. | ` exe [-l [<lines>...]] ` | ` option("-l") & opt_values("lines", ids) `
  122. | ` exe [-l <lines>]... ` | ` repeatable( option("-l") & value("lines", ids) ) `
  123. | ` exe -l <lines>... ` | ` required("-l") & values("lines", ids) `
  124. | ` exe -l [<lines>...] ` | ` required("-l") & opt_values("lines", ids) `
  125. | ` exe (-l <lines>)... ` | ` repeatable( required("-l") & value("lines", ids) ) `
  126. | ` exe fetch [-a] ` | ` command("fetch").set(k,1), option("-a").set(a) `
  127. | ` exe init \| fetch [-a] ` | ` command("init").set(k,0) \| (command("fetch").set(k,1), option("-a").set(a)) `
  128. | ` exe [-a\|-b] ` | ` option("-a").set(a) \| option("-b").set(b) `
  129. | ` exe [-m a\|b] ` | ` option("-m") & (required("a").set(a) \| required("b").set(b)) `
  130. ## Overview
  131. See the [examples](#examples) section for detailed explanations of each topic.
  132. Namespace qualifiers are omitted from all examples for better readability. All entities are defined in ```namespace clipp```.
  133. #### Basic Setup
  134. ```cpp
  135. int main(int argc, char* argv[]) {
  136. using namespace clipp;
  137. auto cli = ( /* CODE DEFINING COMMAND LINE INTERFACE GOES HERE */ );
  138. parse(argc, argv, cli); //excludes argv[0]
  139. //if you want to include argv[0]
  140. //parse(argv, argv+argc, cli);
  141. }
  142. ```
  143. There are two kinds of building blocks for command line interfaces: parameters and groups. Convieniently named factory functions produce parameters or groups with the desired settings applied.
  144. #### Parameters ([flag strings](#flag-strings), [commands](#commands), [positional values](#required-positional-values), [required flags](#required-flags), [repeatable parameters](#repeatable-parameters))
  145. ```cpp
  146. bool a = false, f = false;
  147. string s; vector<string> vs;
  148. auto cli = ( // matches required positional repeatable
  149. command("push"), // exactly yes yes no
  150. required("-f", "--file").set(f), // exactly yes no no
  151. required("-a", "--all", "-A").set(a), // exactly no no no
  152. value("file", s), // any arg yes yes no
  153. values("file", vs), // any arg yes yes yes
  154. opt_value("file", s), // any arg no yes no
  155. opt_values("file", vs), // any arg no yes yes
  156. //"catch all" parameter - useful for error handling
  157. any_other(vs), // any arg no no yes
  158. //catches arguments that fulfill a predicate and aren't matched by other parameters
  159. any(predicate, vs) // predicate no no yes
  160. );
  161. ```
  162. The functions above are convenience factories:
  163. ```cpp
  164. bool f = true; string s;
  165. auto v1 = values("file", s);
  166. // is equivalent to:
  167. auto v2 = parameter{match::nonempty}.label("file").blocking(true).repeatable(true).set(s);
  168. auto r1 = required("-f", "--file").set(f);
  169. // is equivalent to:
  170. auto r2 = parameter{"-f", "--file"}.required(true).set(f);
  171. ```
  172. - a required parameter has to match at least one command line argument
  173. - a repeatable parameter can match any number of arguments
  174. - non-positional (=non-blocking) parameters can match arguments in any order
  175. - a positional (blocking) parameter defines a "stop point", i.e., until it matches all parameters following it are not allowed to match; once it matched, all parameters preceding it (wihtin the current group) will become unreachable
  176. ##### [Flags + Values](#options-with-values)
  177. If you want parameters to be matched in sequence, you can tie them together using either ```operator &``` or the grouping function ```in_sequence```:
  178. ```cpp
  179. int n = 1; string s; vector<int> ls;
  180. auto cli = (
  181. //option with required value
  182. option("-n", "--repeat") & value("times", n),
  183. //required flag with optional value
  184. required("--file") & opt_value("name", s),
  185. //option with exactly two values
  186. option("-p", "--pos") & value("x") & value("y"),
  187. //same as before v v
  188. in_sequence( option("-p", "--pos") , value("x") , value("y") ),
  189. //option with at least one value (and optionally more)
  190. option("-l") & values("lines", ls)
  191. );
  192. ```
  193. ##### [Filtering Value Parameters](#value-filters)
  194. Value parameters use a filter function to test if they are allowed to match an argument string. The default filter ```match::nonempty``` that is used by ```value```, ```values```, ```opt_value``` and ```opt_values``` will match any non-empty argument string.
  195. You can either supply other filter functions/function objects as first argument of ```value```, ```values```, etc. or use one of these built-in shorthand factory functions covering the most common cases:
  196. ```cpp
  197. string name; double r = 0.0; int n = 0;
  198. auto cli = (
  199. value("user", name), // matches any non-empty string
  200. word("user", name), // matches any non-empty alphanumeric string
  201. number("ratio", r), // matches string representations of numbers
  202. integer("times", n) // matches string representations of integers
  203. );
  204. ```
  205. Analogous to ```value```, ```opt_value```, etc. there are also functions for ```words```, ```opt_word```, etc.
  206. ##### Value Parameters With [Custom Filters](#custom-value-filters)
  207. ```cpp
  208. auto is_char = [](const string& arg) { return arg.size() == 1 && std::isalpha(arg[0]); };
  209. char c = ' ';
  210. // matches required positional repeatable
  211. value(is_char, "c", c); // one character yes yes no
  212. ```
  213. #### Groups
  214. - [group](#grouping) mutually compatible parameters with parentheses and commas:
  215. ```cpp
  216. auto cli = ( option("-a"), option("-b"), option("-c") );
  217. ```
  218. - group mutually exclusive parameters as [alternatives](#alternatives) using ```operator |``` or ```one_of```:
  219. ```cpp
  220. auto cli1 = ( value("input_file") | command("list") | command("flush") );
  221. auto cli2 = one_of( value("input_file") , command("list") , command("flush") );
  222. ```
  223. - group parameters so that they must be matched in sequence using ```operator &``` or ```in_sequence```:
  224. ```cpp
  225. double x = 0, y = 0, z = 0;
  226. auto cli1 = ( option("-pos") & value("X",x) & value("Y",y) & value("Z",z) );
  227. auto cli2 = in_sequence( option("-pos") , value("X",x) , value("Y",y) , value("Z",z) );
  228. ```
  229. Note that surrounding groups are not affected by this, so that ```-a``` and ```-b``` can be matched in any order while ```-b``` and the value ```X``` must match in sequence:
  230. ```cpp
  231. bool a = false, b = false; int x = 0;
  232. auto cli = ( option("-a").set(a), option("-b").set(b) & value("X",x) );
  233. ```
  234. - groups can be nested and combined to form arbitrarily complex interfaces (see [here](#nested-alternatives) and [here](#complex-nestings)):
  235. ```cpp
  236. auto cli = ( command("push") | ( command("pull"), option("-f", "--force") ) );
  237. ```
  238. - groups can be repeatable as well:
  239. ```cpp
  240. auto cli1 = repeatable( command("flip") | command("flop") );
  241. ```
  242. - force common prefixes on a group of flags:
  243. ```cpp
  244. int x = 0;
  245. auto cli1 = with_prefix("-", option("a"), option("b") & value("x",x), ... );
  246. // => -a -b ^unaffected^
  247. auto cli2 = with_prefix_short_long("-", "--", option("a", "all"), option("b"), ... );
  248. // => -a --all -b
  249. ```
  250. - force common suffixes on a group of flags:
  251. ```cpp
  252. int x = 0;
  253. auto cli1 = with_suffix("=", option("a") & value("x",x), ... );
  254. // => a= ^unaffected^
  255. auto cli2 = with_suffix_short_long(":", ":=", option("a", "all"), option("b"), ... );
  256. // => a: all:= b:
  257. ```
  258. - make a group of flags [joinable](#joinable-flags):
  259. ```cpp
  260. auto cli1 = joinable( option("-a"), option("-b")); //will match "-a", "-b", "-ab", "-ba"
  261. //works also with arbitrary common prefixes:
  262. auto cli2 = joinable( option("--xA0"), option("--xB1")); //will also match "--xA0B1" or "--xB1A0"
  263. ```
  264. #### Interfacing With Your Code
  265. The easiest way to connect the command line interface to the rest of your code is to bind object values or function (object) calls to parameters (see also [here](#actions)):
  266. ```cpp
  267. bool b = false; int i = 5; int m = 0; string x; ifstream fs;
  268. auto cli = (
  269. option("-b").set(b), // "-b" detected -> set b to true
  270. option("-m").set(m,2), // "-m" detected -> set m to 2
  271. option("-x") & value("X", x), // set x's value from arg string
  272. option("-i") & opt_value("i", i), // set i's value from arg string
  273. option("-v").call( []{ cout << "v"; } ), // call function (object) / lambda
  274. option("-v")( []{ cout << "v"; } ), // same as previous line
  275. option("-f") & value("file").call([&](string f){ fs.open(f); })
  276. );
  277. ```
  278. In production code one would probably use a settings class:
  279. ```cpp
  280. struct settings { bool x = false; /* ... */ };
  281. settings cmdline_settings(int argc, char* argv[]) {
  282. settings s;
  283. auto cli = ( option("-x").set(s.x), /* ... */ );
  284. parse(argc, argv, cli);
  285. return s;
  286. }
  287. ```
  288. Note that the target must either be:
  289. - a fundamental type (```int, long int, float, double, ...```)
  290. - a type that is convertible from ```const char*```
  291. - a callable entity: function, function object / lambda
  292. that either has an empty parameter list or exactly one parameter that is
  293. convertible from ```const char*```
  294. #### Generating Documentation ([see also here](#documentation-generation))
  295. Docstrings for groups and for parameters can either be set with the member function ```doc``` or with ```operator %```:
  296. ```cpp
  297. auto cli = (
  298. ( option("x").set(x).doc("sets X"),
  299. option("y").set(y) % "sets Y"
  300. ),
  301. "documented group 1:" % (
  302. option("-g").set(g).doc("activates G"),
  303. option("-h").set(h) % "activates H"
  304. ),
  305. ( option("-i").set(i) % "activates I",
  306. option("-j").set(j) % "activates J"
  307. ).doc("documented group 2:")
  308. );
  309. ```
  310. Usage Lines:
  311. ```cpp
  312. cout << usage_lines(cli, "progname") << '\n';
  313. //with formatting options
  314. auto fmt = doc_formatting{}
  315. .first_column(3)
  316. .last_column(79);
  317. cout << usage_lines(cli, "progname", fmt) << '\n';
  318. ```
  319. Detailed Documentation:
  320. ```cpp
  321. cout << documentation(cli) << '\n';
  322. //with formatting options
  323. auto fmt = doc_formatting{}
  324. .first_column(7)
  325. .doc_column(15)
  326. .last_column(99);
  327. cout << documentation(cli, fmt) << '\n';
  328. ```
  329. Man Pages:
  330. ```cpp
  331. auto cli = ( /*CODE DEFINING COMMAND LINE INTERFACE GOES HERE*/ );
  332. cout << make_man_page(cli, "progname") << '\n';
  333. //with formatting options
  334. auto fmt = doc_formatting{}
  335. .first_column(7)
  336. .doc_column(15)
  337. .last_column(99);
  338. cout << make_man_page(cli, "progname", fmt) << '\n';
  339. ```
  340. #### (Error) Event Handlers ([see here](#error-handling), [and here](#per-parameter-parsing-report))
  341. Each parameter can have event handler functions attached to it. These are invoked once for each argument that is mapped to the parameter (or once per missing event):
  342. ```cpp
  343. string file = "default.txt";
  344. auto param = required("-nof").set(file,"") |
  345. required("-f") & value("file", file)
  346. // on 2nd, 3rd, 4th,... match (would be an error in this case)
  347. .if_repeated( [] { /* ... */ } )
  348. // if required value-param was missing
  349. .if_missing( [] { /* ... */ } )
  350. // if unreachable, e.g. no flag "-f" before filename
  351. .if_blocked( [] { /* ... */ } )
  352. // if match is in conflict with other alternative "-nof"
  353. .if_conflicted( [] { /* ... */ } );
  354. ```
  355. The handler functions can also take an int, which is set to the argument index at which the event occurred first:
  356. ```cpp
  357. string file = "default.txt";
  358. auto param = required("-nof").set(file,"") |
  359. required("-f") & value("file", file)
  360. .if_repeated ( [] (int argIdx) { /* ... */ } )
  361. .if_missing ( [] (int argIdx) { /* ... */ } )
  362. .if_blocked ( [] (int argIdx) { /* ... */ } )
  363. .if_conflicted( [] (int argIdx) { /* ... */ } );
  364. ```
  365. #### Special Cases
  366. If we give ```-f -b``` or ```-b -f -a``` as command line arguments for the following CLI, an error will be reported, since the value after ```-f``` is not optional:
  367. ```cpp
  368. auto cli = ( option("-a"), option("-f") & value("filename"), option("-b") );
  369. ```
  370. This behavior is fine for most use cases.
  371. But what if we want our program to take any string as a filename, because our filenames might also collide with flag names? We can make the value parameter [greedy](#greedy-parameters) with ```operator !```. This way, the next string after ```-f``` will always be matched with highest priority as soon as ```-f``` was given:
  372. ```cpp
  373. auto cli = ( option("-a"), option("-f") & !value("filename"), option("-b") );
  374. // ^~~~~~
  375. ```
  376. Be **very careful** with greedy parameters!
  377. #### Parsing Result Analysis
  378. ```cpp
  379. auto cli = ( /* your interface here */ );
  380. auto res = parse(argc, argv, cli);
  381. if(res.any_error()) { /* ... */ }
  382. //aggregated errors
  383. if(res.unmapped_args_count()) { /* ... */ }
  384. if(res.any_bad_repeat()) { /* ... */ }
  385. if(res.any_blocked()) { /* ... */ }
  386. if(res.any_conflict()) { /* ... */ }
  387. for(const auto& m : res.missing()) {
  388. cout << "missing " << m.param() << " after index " << m.after_index() << '\n';
  389. }
  390. //per-argument mapping
  391. for(const auto& m : res) {
  392. cout << m.index() << ": " << m.arg() << " -> " << m.param();
  393. cout << " repeat #" << m.repeat();
  394. if(m.blocked()) cout << " blocked";
  395. if(m.conflict()) cout << " conflict";
  396. cout << '\n';
  397. }
  398. ```
  399. #### Writing Your Own Convenience Factories
  400. Sometimes it can make your CLI code more expressive and increase maintainability, if you create your own factory functions for making parameters:
  401. ```cpp
  402. //value that can only connect to one object with automatic default value documentation
  403. template<class Target>
  404. clipp::parameter
  405. documented_value(const std::string& name, Target& tgt, const std::string& docstr) {
  406. using std::to_string;
  407. return clipp::value(name,tgt).doc(docstr + "(default: " + to_string(tgt) + ")");
  408. }
  409. ```
  410. ```cpp
  411. //value that only matches strings without prefix '-'
  412. template<class Target, class... Targets>
  413. clipp::parameter
  414. nodash_value(std::string label, Target&& tgt, Targets&&... tgts) {
  415. return clipp::value(clipp::match::prefix_not{"-"}, std::move(label),
  416. std::forward<Target>(tgt), std::forward<Targets>(tgts)...);
  417. }
  418. ```
  419. ## Examples
  420. Note that namespace qualifiers are omitted from all examples for better readability.
  421. The repository folder "examples" contains code for most of the following examples.
  422. - [options](#options)
  423. - [coding styles](#coding-styles)
  424. - [flag strings](#flag-strings)
  425. - [groups](#grouping)
  426. - [positional values](#required-positional-values)
  427. - [options with values](#options-with-values)
  428. - [options with multiple values](#options-with-multiple-values)
  429. - [required flags](#required-flags)
  430. - [repeatable parameters](#repeatable-parameters)
  431. - [actions](#actions)
  432. - [joinable flags](#joinable-flags)
  433. - [alternatives](#alternatives)
  434. - [commands](#commands)
  435. - [nested alternatives](#nested-alternatives)
  436. - [complex nestings](#complex-nestings)
  437. - [example from docopt](#an-example-from-docopt)
  438. - [value filters](#value-filters)
  439. - [greedy parameters](#greedy-parameters)
  440. - [generalized joinable parameters](#generalized-joinable-parameters)
  441. - [custom value filters](#custom-value-filters)
  442. - [sanity checks](#sanity-checks)
  443. - [basic error handling](#basic-error-handling)
  444. - [parsing](#parsing)
  445. - [documentation generation](#documentation-generation)
  446. - [documentation filtering](#documentation-filtering)
  447. ### Options
  448. ```man
  449. SYNOPSIS
  450. switch [-a] [-b] [-c] [--hi]
  451. OPTIONS
  452. -a activates a
  453. -b activates b
  454. -c, --noc deactivates c
  455. --hi says hi
  456. ```
  457. ```cpp
  458. bool a = false, b = false, c = true; //target variables
  459. auto cli = (
  460. option("-a").set(a) % "activates a",
  461. option("-b").set(b) % "activates b",
  462. option("-c", "--noc").set(c,false) % "deactivates c",
  463. option("--hi")([]{cout << "hi!\n";}) % "says hi");
  464. if(parse(argc, argv, cli))
  465. cout << "a=" << a << "\nb=" << b << "\nc=" << c << '\n';
  466. else
  467. cout << make_man_page(cli, "switch");
  468. ```
  469. This will set ```a``` to true, if ```-a``` is found, ```b``` to true, if ```-b``` is found, ```c``` to false, if ```-c``` or ```--noc``` are found and prints "hi" if ```--hi``` is found in ```argv```. In case of parsing errors a man page will be printed.
  470. ### Coding Styles
  471. If you like it more verbose use ```set``` to set variables, ```call``` to call functions and ```doc``` for docstrings. The sequence of member function calls doesn't matter.
  472. ```cpp
  473. auto cli = (
  474. option("-b").set(b).doc("activates b"),
  475. option("-c", "--noc").set(c,false).doc("deactivates c"),
  476. option("--hi").call([]{cout << "hi!\n";}).doc("says hi") );
  477. ```
  478. #### You can also use ```operator >>``` and ```operator <<``` to define actions
  479. ```cpp
  480. auto cli = (
  481. option("-b") % "activates b" >> b,
  482. option("-c", "--noc") % "deactivates c" >> set(c,false),
  483. option("--hi") % "says hi" >> []{cout << "hi!\n";} );
  484. ```
  485. ```cpp
  486. auto cli = (
  487. option("-b") % "activates b" >> b,
  488. option("-c", "--noc") % "deactivates c" >> set(c,false),
  489. option("--hi") % "says hi" >> []{cout << "hi!\n";} );
  490. ```
  491. ```cpp
  492. auto cli = (
  493. b << option("-b") % "activates b",
  494. set(c,false) << option("-c", "--noc") % "deactivates c",
  495. []{cout << "hi!\n";} << option("--hi") % "says hi" );
  496. ```
  497. ```cpp
  498. auto cli = (
  499. "activates b" % option("-b") >> b,
  500. "deactivates c" % option("-c", "--noc") >> set(c,false),
  501. "says hi" % option("--hi") >> []{cout << "hi!\n";} );
  502. ```
  503. Note that ```%``` has a higher precedence than ```<<``` and ```>>``` which means that you either have to keep the docstrings closer to the command line parameters than the actions or use parentheses.
  504. You should also have a look at [actions](#actions) for more details.
  505. #### Step-by-step configuration of parameters:
  506. ```cpp
  507. int n = 1;
  508. auto optN = parameter{"-n", "-N", "--iterations", "--repeats"}.required(true);
  509. auto valN = parameter{match::any}
  510. .label("times")
  511. .set(n)
  512. .call([](string s) { if(!str::represents_number(s)) throw runtime_error{"invalid value for 'times'"}; })
  513. .if_missing([]{ cout << "value 'times' not found!\n"; })
  514. .doc("number of iterations (default = " + std::to_string(n) + ")");
  515. auto cli = group{};
  516. cli.push_back(std::move(optN));
  517. cli.push_back(std::move(valN));
  518. // or:
  519. auto cli = group{std::move(optN), std::move(valN)};
  520. ```
  521. ### Flag Strings
  522. There are no limitations regarding formatting and you can have an arbitrary number of flags per command line parameter.
  523. ```cpp
  524. bool onetwo = false;
  525. auto myopt = option("-1", "-2", "1", "2", ":1", ":2", "--no1", "--no2").set(onetwo);
  526. // ^----- will match any one of these strings ------^
  527. ```
  528. #### Same prefix for all flags
  529. ```cpp
  530. bool a = false, b = false;
  531. auto cli = with_prefix("-",
  532. option("a").set(a), // -a
  533. option("b").set(b) // -b
  534. );
  535. ```
  536. #### Same prefix for all flags: single vs. multiple character(s)
  537. Single-letter flags will get the first prefix, flags with more than one letter will get the second one.
  538. ```cpp
  539. bool a = false, b = false;
  540. auto cli = with_prefixes_short_long("-", "--",
  541. option("a", "all").set(a), // -a, --all
  542. option("b", "bottom").set(b) // -b, --bottom
  543. );
  544. ```
  545. #### Same suffix for all flags
  546. ```cpp
  547. bool a = false, b = false;
  548. auto cli = with_suffix(":",
  549. option("a").set(a), // a:
  550. option("b").set(b) // b:
  551. );
  552. ```
  553. #### Same suffix for all flags: single vs. multiple character(s)
  554. Single-letter flags will get the first suffix (empty in this example), flags with more than one letter will get the second one.
  555. ```cpp
  556. int a = 0, b = 0;
  557. auto cli = with_suffixes_short_long("", "=",
  558. option("a", "all") & value("A", a), // -a, --all=
  559. option("b", "bottom") & value("B", b) // -b, --bottom=
  560. );
  561. ```
  562. #### Make Sure No Flag Occurs As Prefix Of Another Flag
  563. ```cpp
  564. auto cli = ( /* your command line interface here */ );
  565. assert(cli.flags_are_prefix_free());
  566. ```
  567. Note that identical flags will not trigger an error.
  568. ### Grouping
  569. Groups can be nested (see [here](#nested-alternatives)) and have their own documentation string.
  570. The statement ```auto cli = ( ... );``` creates a group, if there are more than two parameters/groups declared inside the parentheses.
  571. ```man
  572. SYNOPSIS
  573. myprogram [x] [y] [a] [b] [-c] [-d] [-e] [-f]
  574. OPTIONS
  575. x sets X
  576. y sets Y
  577. documented group 1:
  578. a activates A
  579. b activates B
  580. documented group 2:
  581. -c activates C
  582. -d activates D
  583. -e, -f activates E or F
  584. ```
  585. ```cpp
  586. bool x = false, y = false, a = false, b = false;
  587. bool g = false, h = false, e = false, f = false;
  588. auto cli = (
  589. ( option("x").set(x) % "sets X", //simple group
  590. option("y").set(y) % "sets Y"
  591. ),
  592. ( option("a").set(a) % "activates A",
  593. option("b").set(b) % "activates B"
  594. ) % "documented group 1:" //docstring after group
  595. ,
  596. "documented group 2:" % ( //docstring before group
  597. option("-g").set(g) % "activates G",
  598. option("-h").set(h) % "activates H"
  599. ),
  600. "activates E or F" % (
  601. option("-e").set(e), //no docstrings inside group
  602. option("-f").set(f)
  603. )
  604. );
  605. cout << make_man_page(cli, "myprogram");
  606. ```
  607. The above example is in fact shorthand for this:
  608. ```cpp
  609. group cli{
  610. group{
  611. parameter{"x"}.set(x).doc("sets X"),
  612. parameter{"y"}.set(y).doc("sets Y")
  613. },
  614. group{
  615. parameter{"a"}.set(a).doc("activates A"),
  616. parameter{"b"}.set(b).doc("activates B")
  617. }.doc("documented group 1:")
  618. ,
  619. group{
  620. parameter{"-g"}.set(g).doc("activates G"),
  621. parameter{"-h"}.set(h).doc("activates H")
  622. }.doc("documented group 2:")
  623. ,
  624. group{
  625. parameter{"-e"}.set(e),
  626. parameter{"-f"}.set(f)
  627. }.doc("activates E or F")
  628. };
  629. cout << make_man_page(cli, "myprogram");
  630. ```
  631. You can of course also fill groups one-by-one:
  632. ```cpp
  633. group cli;
  634. cli.push_back(option("x").sets(x).doc("sets X"));
  635. //...
  636. ```
  637. ### Required Positional Values
  638. ```man
  639. SYNOPSIS
  640. myprogram <infile> <outfile> [-s]
  641. OPTIONS
  642. infile input filename
  643. outfile output filename
  644. -s, --split split files
  645. ```
  646. ```cpp
  647. string ifile, ofile;
  648. bool split = false;
  649. auto cli = (
  650. value("infile", ifile) % "input filename",
  651. value("outfile", ofile) % "output filename",
  652. option("-s", "--split").set(split) % "split files" );
  653. ```
  654. #### Alternative Value Mapping Style
  655. ```cpp
  656. auto cli = (
  657. value("infile") % "input filename" >> ifile,
  658. value("outfile") % "output filename" >> ofile,
  659. option("-s", "--split") % "split files" >> split );
  660. ```
  661. See [here](#coding-styles) for more on possible mapping styles.
  662. ### Options With Values
  663. Parameters can be sequenced using operator ```&``` or the function ```in_sequence```. Sequenced parameters can only be matched one after the other. This mechanism can be used to attach a value parameter to an option.
  664. ```man
  665. SYNOPSIS
  666. simplify [-n <count>] [-r <ratio>] [-m [<lines=5>]]
  667. OPTIONS
  668. -n, --count <count> number of iterations
  669. -r, --ratio <ratio> compression ratio
  670. -m <lines=5> merge lines (default: 5)
  671. ```
  672. ```cpp
  673. int n = 0;
  674. bool domerge = false;
  675. long m = 5;
  676. auto print_ratio = [](const char* r) { cout << "using ratio of " << r << '\n'; };
  677. auto cli = (
  678. (option("-n", "--count") & value("count", n)) % "number of iterations",
  679. (option("-r", "--ratio") & value("ratio", print_ratio)) % "compression ratio",
  680. (option("-m").set(domerge) & opt_value("lines=5", m)) % "merge lines (default: 5)"
  681. );
  682. ```
  683. #### Alternative Value Mapping Styles
  684. ```cpp
  685. auto cli = (
  686. (option("-n", "--count") & value("count") >> n ) % "number of iterations",
  687. (option("-r", "--ratio") & value("ratio") >> print_ratio ) % "compression ratio",
  688. (option("-m" ) & opt_value("lines=5") >> m >> domerge) % "merge lines (default: 5)"
  689. );
  690. ```
  691. ```cpp
  692. auto cli = (
  693. (option("-n", "--count") & value("count").set(n)) % "number of iterations",
  694. (option("-r", "--ratio") & value("ratio")(print_ratio)) % "compression ratio",
  695. (option("-m").set(domerge) & opt_value("lines=5").set(m)) % "merge lines (default: 5)"
  696. );
  697. ```
  698. See [here](#coding-styles) for more on coding styles.
  699. ### Options With Multiple Values
  700. Parameters can be sequenced using operator ```&``` or the function ```in_sequence```. Sequenced parameters can only be matched one after the other. This mechanism can be used to attach multiple values to an option.
  701. ```man
  702. SYNOPSIS
  703. transform <geometry file> [-translate <x> <y> <z>] [-rotate <azimuth> <polar>]
  704. ```
  705. ```cpp
  706. string infile;
  707. bool tr = false, rot = false;
  708. double x = 0, y = 0, z = 0;
  709. double phi = 0, theta = 0;
  710. auto cli = (
  711. value("geometry file", infile),
  712. option("-translate").set(tr) & value("x", x) & value("y", y) & value("z", z),
  713. option("-rotate").set(rot) & value("azimuth", phi) & value("polar", theta)
  714. );
  715. ```
  716. Note that the following interface definition is equivalent to the above. Since ```value``` is positional we can list it with ```,```, but we have to make sure that the groups of values will only be matched after the options, hence the ```&```.
  717. ```cpp
  718. auto cli = (
  719. value("geometry file", infile),
  720. option("-translate").set(tr) & ( value("x", x), value("y", y), value("z", z) ),
  721. option("-rotate").set(rot) & ( value("azimuth", phi) , value("polar", theta) )
  722. );
  723. ```
  724. ### Required Flags
  725. Required flags are usually used together with non-optional values. Note that ```-i``` and ```-o``` are not positional in the following example, i.e., the relative order in which command line arguments for ```-i```, ```-o``` and ```-r``` are provided is irrelevant.
  726. ```man
  727. SYNOPSIS
  728. myprogram [-r] -i <input dir> -o <output dir>
  729. OPTIONS
  730. -r, --recursive
  731. search in subdirectories
  732. -i, --in <input dir>
  733. path to input directory
  734. -o, --out <output dir>
  735. path to output directory
  736. ```
  737. ```cpp
  738. bool recurse = false;
  739. string inpath, outpath;
  740. auto cli = (
  741. option("-r", "--recursive").set(recurse) % "search in subdirectories",
  742. (required("-i", "--in" ) & value("input dir", inpath)) % "path to input directory",
  743. (required("-o", "--out") & value("output dir", outpath)) % "path to output directory"
  744. );
  745. ```
  746. ### Repeatable Parameters
  747. ```man
  748. SYNOPSIS
  749. simplify <file>... [-c] [-i <line>...]
  750. OPTIONS
  751. <file>... input files
  752. -c, --compress compress results
  753. -i, --ignore <line>... lines to be ignored
  754. ```
  755. ```cpp
  756. vector<string> files;
  757. vector<int> lines;
  758. bool zip = false;
  759. auto cli = (
  760. values("file", files) % "input files",
  761. option("-c", "--compress").set(zip) % "compress results",
  762. (option("-i", "--ignore") & integers("line", lines)) % "lines to be ignored"
  763. );
  764. ```
  765. The call ```values("v")``` is shorthand for ```value("v").repeatable(true)```.
  766. Note, that the value parameter ```line``` is repeatable, but the flag ```--ignore``` is not. So
  767. something like
  768. ```
  769. simplify file1 file2 --ignore 1 2 --ignore 3 4 -c
  770. ```
  771. is taken to be an error.
  772. However, it is possible if you make the group of ```--ignore``` and ```line``` itself repeatable:
  773. #### Repeatable Groups of Options with Repeatable Values
  774. ```man
  775. SYNOPSIS
  776. simplify <file>... [-c] [-i <line>...]...
  777. OPTIONS
  778. <file>... input files
  779. -c, --compress compress results
  780. -i, --ignore <line>... lines to be ignored
  781. ```
  782. ```cpp
  783. vector<string> files;
  784. vector<int> lines;
  785. bool zip = false;
  786. auto cli = (
  787. values("file", files) % "input files",
  788. option("-c", "--compress").set(zip) % "compress results",
  789. repeatable( // <-----
  790. option("-i", "--ignore") & integers("line", lines)
  791. ) % "lines to be ignored"
  792. );
  793. ```
  794. Now both the option ```--ignore``` *and* the value parameter ```value``` are repeatable. In all of the following examples ```lines``` will be set to ```{1,2,3,4}``` and ```c``` will be set to ```true```:
  795. ```
  796. simplify file1 file2 -c --ignore 1 2 3 4
  797. simplify file1 file2 --ignore 1 2 3 4 -c
  798. simplify file1 file2 --ignore 1 -c --ignore 2 3 4
  799. simplify file1 file2 --ignore 1 2 --ignore 3 4 -c
  800. simplify file1 file2 --ignore 1 --ignore 2 -c --ignore 3 --ignore 4
  801. simplify file1 file2 -c --ignore1 --ignore2 --ignore3 --ignore4
  802. ```
  803. ### Actions
  804. Actions are executed if a parameter matched an argument string in the command line arguments list. Actions are defined using the following member functions or operators:
  805. - ```parameter::call(f)``` or ```parameter::operator () (f)```: call a callable entity ```f``` (function, lambda, custom function object) for each one of the matched argument strings. If ```f``` accepts exactly one parameter that is convertible from ```const char*```, the command line argument is passed to it. If the parameter list is empty, it is simply called without argument.
  806. - ```parameter::set(target, value)```: assign a fixed value to a target object; note that the assignment ```target = value;``` must be a valid statement
  807. - ```parameter::set(target)```:
  808. - A ```bool``` target is set to true if the flag/value is present and **left unchanged otherwise**.
  809. - A target object of fundamental type ```T``` (```int```, ```long```, ```float```, ```double```, ...) will be assigned the result of converting the argument string to type ```T```.
  810. - Targets of type ```std::vector<T>``` are appended with a value for each matched argument string. Note that ```T``` must either be (explicitly) convertible from ```const char*``` or a fundamental type.
  811. - ```operator <<``` or ```operator >>``` assign arg strings to lvalues or call callable entities. Which kind of action will be performed is automatically determined through overload resolution.
  812. #### Predefined Functions
  813. ```cpp
  814. int x = 0; // equivalent to:
  815. option("-x")(set(x)) // option("-x").set(x)
  816. option("-x")(set(x,2)) // option("-x").set(x,2)
  817. option("-x")(increment(x)) // option("-x")([&]{++x;})
  818. option("-x")(decrement(x)) // option("-x")([&]{--x;})
  819. bool b = false; // equivalent to:
  820. option("-b")(flip(b)) // option("-x")([&]{b = !b;})
  821. ```
  822. #### Some Examples
  823. ```cpp
  824. bool a = false, b = false;
  825. int i = 1, n = 0, m = 0;
  826. float x = 0.0f;
  827. auto cli = ( //INFORMAL description
  828. option("-a").set(a), //if(found("-a")) a = true;
  829. option("-b") >> b, //if(found("-b")) b = true;
  830. option("--toggle").call(flip(b)), //if(found("--toggle")) flip(b);
  831. value("n").set(n), //n = std::atoi(arg);
  832. option("-i") & value("#",i), //if(found("-i arg")) i = std::atoi(arg);
  833. option("-1").set(m,1), //if(found("-1")) m = 1;
  834. option("-2").set(m,2), //if(found("-2")) m = 2;
  835. //if(found("-z")) call_lambda_with_arg("-z");
  836. option("-z").call([](const char* s) { cout << s; }),
  837. //using 'operator()' instead of 'call'
  838. //if(found("bob")) call_lambda_with_arg("bob");
  839. option("bob")([](const std::string& s) { cout << s; }),
  840. //for_each_occurence("-x arg", call_lambda_with_arg(arg));
  841. repeatable( option("-x") & value("X")([&](const char* s) { x = std::atof(s); }) ),
  842. option("--all") >> []() { cout << "found --all\n"; }
  843. >> [](const char* s) { cout << "found flag " << s << '\n'; };
  844. );
  845. ```
  846. ### Joinable Flags
  847. ```man
  848. SYNOPSIS
  849. edit <file> [-rbs] ([:vim] [:st3] [:atom] [:emacs])
  850. OPTIONS
  851. -r open read-only
  852. -b use backup file
  853. -s use swap file
  854. :vim, :st3, :atom, :emacs
  855. editor(s) to use; multiple possible
  856. ```
  857. ```cpp
  858. std::string file;
  859. bool readonly = false, usebackup = false, useswap = false;
  860. enum class editor {vim, sublime3, atom, emacs};
  861. std::vector<editor> editors;
  862. auto add = [&](editor e){ return [&]{ editors.push_back(e); }; };
  863. auto cli = (
  864. value("file", file),
  865. joinable(
  866. option("-r").set(readonly) % "open read-only",
  867. option("-b").set(usebackup) % "use backup file",
  868. option("-s").set(useswap) % "use swap file"
  869. ),
  870. joinable(
  871. option(":vim") >> add(editor::vim),
  872. option(":st3") >> add(editor::sublime3),
  873. option(":atom") >> add(editor::atom),
  874. option(":emacs") >> add(editor::emacs)
  875. ) % "editor(s) to use; multiple possible"
  876. );
  877. ```
  878. - Flags can be joined regardless of their length (second group in the example).
  879. - If the flags have a common prefix (```-``` or ```:``` in the example) it must be given at least
  880. once as leading prefix in the command line argument.
  881. - Allowed args for the first group are:
  882. ```-r```, ```-b```, ```-s```, ```-rb```, ```-br```, ```-rs```, ```-sr```,
  883. ```-sb```, ```-bs```, ```-rbs```, ```-rsb```, ...
  884. - Allowed args for the second group are:
  885. ```:vim```, ```:vim:atom```, ```:emacs:st3```, ```:vimatom```, ...
  886. #### More Examples
  887. | joinable flags | valid args |
  888. | ------------------------ | --------------------- |
  889. | ```a```, ```b``` | ```ab```, ```ba```, ```a```, ```b``` |
  890. | ```-a```, ```-b``` | ```-ab```, ```-ba```, ```-a```, ```-b```, ```-a-b```, ```-b-a``` |
  891. | ```--a```, ```--b``` | ```--ab```, ```--ba```, ```--a```, ```--b```, ```--a--b```, ```--b--a``` |
  892. | ```,a```, ```,b``` | ```,ab```, ```,ba```, ```,a```, ```,b```, ```,a,b```, ```,b,a``` |
  893. | ```Xab```, ```Xcd``` | ```Xabcd```, ```Xcdab```, ```XabXcd```, ```XcdXab```, ```Xab```, ```Xcd``` |
  894. | ```x:ab```, ```x:cd``` | ```x:abcd```, ```x:cdab```, ```x:abx:cd```, ```x:cdx:ab```, ```x:ab```, ```x:cd``` |
  895. ### Alternatives
  896. ```man
  897. SYNOPSIS
  898. find <file>... -s <expr> [any|all]
  899. OPTIONS
  900. <file>... input filenames
  901. -s <expr> string to look for
  902. any report as soon as any matches
  903. all report only if all match
  904. ```
  905. ```cpp
  906. vector<string> files;
  907. string expr;
  908. bool ifany = false, ifall = false;
  909. auto cli = (
  910. values("file", files) % "input filenames",
  911. (required("-s") & value("expr", expr)) % "string to look for",
  912. option("any").set(ifany) % "report as soon as any matches" |
  913. option("all").set(ifall) % "report only if all match"
  914. );
  915. ```
  916. If you like it more verbose you can use the function ```one_of``` instead of ```operator |```:
  917. ```cpp
  918. auto cli = (
  919. values("file", files) % "input filenames",
  920. (required("-s") & value("expr", expr)) % "string to look for",
  921. one_of( option("any").set(ifany) % "report as soon as any matches",
  922. option("all").set(ifall) % "report only if all match" )
  923. );
  924. ```
  925. #### gcc-style switches
  926. ```man
  927. SYNOPSIS
  928. format [-o <output file>] [-falign|-fnoalign)]
  929. OPTIONS
  930. -o, --out <file>
  931. output filename
  932. -falign, -fnoalign
  933. control alignment
  934. ```
  935. ```cpp
  936. string outfile = "a.out";
  937. bool align = false;
  938. auto cli = (
  939. (option("-o", "--out") & value("output file", outfile)) % "output filename",
  940. ( option("-falign" ).set(align,true) |
  941. option("-fnoalign").set(align,false) ) % "control alignment"
  942. );
  943. ```
  944. Note, that the documentation string is attached to the group of parameters for better readability.
  945. #### non-redundant prefix specification
  946. ```cpp
  947. //has the same meaning as the code above
  948. string outfile = "a.out";
  949. bool align = false;
  950. auto cli = (
  951. (option("-o", "--out") & value("output file", outfile)) % "output filename",
  952. with_prefix("-f", option("align" ).set(align,true) |
  953. option("noalign").set(align,false) ) % "control alignment"
  954. );
  955. ```
  956. #### merge alternatives with common prefixes in documentation
  957. ```man
  958. Usage: format [-o <output file>] [-f(align|noalign)]
  959. ```
  960. ```cpp
  961. auto fmt = doc_formatting{}.merge_alternative_flags_with_common_prefix(true);
  962. cout << usage_lines(cli, "format", fmt) << '\n';
  963. ```
  964. ### Commands
  965. **= positional, required flags**
  966. ```man
  967. SYNOPSIS
  968. make_doc new <filename> [-e <enc>]
  969. OPTIONS
  970. -e, --encoding 'utf8' or 'cp1252', default is UTF-8
  971. ```
  972. ```cpp
  973. std::string fname;
  974. std::string enc = "utf8";
  975. auto cli = (
  976. command("new"),
  977. value("filename", fname),
  978. option("-e", "--encoding") & value("enc", enc).doc("'utf8' or 'cp1252', default is " + enc)
  979. );
  980. ```
  981. ### Nested Alternatives
  982. ```man
  983. SYNOPSIS
  984. image-find help
  985. image-find build (new|add) <file>... [-v] [-b [<size=1024>]] [--init|--no-init]
  986. image-find query <infile> -o <outfile> [-f <format>]
  987. OPTIONS
  988. -v, --verbose
  989. print detailed report
  990. -b, --buffer [<size=1024>]
  991. sets buffer size in KiByte
  992. --init, --no-init
  993. do or don't initialize
  994. -f, --out-format <format>
  995. determine output format
  996. ```
  997. Value handling actions are omitted; see examples/nested_alternatives.cpp for a fully functional demo.
  998. ```cpp
  999. auto cli = (
  1000. command("help")
  1001. | ( command("build"),
  1002. ( command("new") | command("add")),
  1003. values("file"),
  1004. option("-v", "--verbose") % "print detailed report",
  1005. (option("-b", "--buffer") & opt_value("size=1024")) % "sets buffer size in KiByte",
  1006. ( option("--init") | option("--no-init") ) % "do or don't initialize"
  1007. )
  1008. | ( command("query"),
  1009. value("infile"),
  1010. required("-o", "--out") & value("outfile"),
  1011. (option("-f", "--out-format") & value("format")) % "determine output format"
  1012. )
  1013. );
  1014. ```
  1015. Note:
  1016. ```
  1017. doc_formatting::split_alternatives(bool) //default: true
  1018. doc_formatting::alternatives_min_split_size(int) //default: 3
  1019. ```
  1020. control if the usage is split up into several lines if any group inside an alternative exceeds a given minimum size.
  1021. ### Complex Nestings
  1022. The combination of blocking parameters, alternatives and grouping makes it possible to define interfaces with decision trees/DAGs of arbitrary complexity.
  1023. ```man
  1024. SYNOPSIS
  1025. complex_nesting [-v] [-i] (copy|move) [--all] [--replace] [-f] <files>... [-r] [-h]
  1026. complex_nesting [-v] [-i] compare (date|content) [-b] [-q] <files>... [-r] [-h]
  1027. complex_nesting [-v] [-i] merge (diff|patch) -o <outdir> [--show-conflicts] <files>... [-r] [-h]
  1028. complex_nesting [-v] [-i] merge content [--git-style] [-m <marker>] -o <outdir> [--show-conflicts] <files>... [-r] [-h]
  1029. complex_nesting [-v] [-i] list <files>... [-r] [-h]
  1030. OPTIONS
  1031. user interface options:
  1032. -v, --verbose show detailed output
  1033. -i, --interactive use interactive mode
  1034. copy mode:
  1035. --all copy all
  1036. --replace replace existing files
  1037. -f, --force don't ask for confirmation
  1038. compare mode:
  1039. -b, --binary compare files byte by byte
  1040. -q, --quick use heuristics for faster comparison
  1041. merge mode:
  1042. diff merge using diff
  1043. patch merge using patch
  1044. content merge based on content
  1045. content based merge options:
  1046. --git-style emulate git's merge behavior
  1047. <marker> merge marker symbol
  1048. <outdir> target directory for merge result
  1049. --show-conflicts show merge conflicts during run
  1050. mode-independent options:
  1051. <files>... input files
  1052. -r, --recursive descend into subdirectories
  1053. -h, --help show help
  1054. ```
  1055. Actions and target variables are omitted in the code.
  1056. ```cpp
  1057. auto copyMode = "copy mode:" % (
  1058. command("copy") | command("move"),
  1059. option("--all") % "copy all",
  1060. option("--replace") % "replace existing files",
  1061. option("-f", "--force") % "don't ask for confirmation"
  1062. );
  1063. auto compareMode = "compare mode:" % (
  1064. command("compare"),
  1065. (command("date") | command("content")),
  1066. option("-b", "--binary") % "compare files byte by byte",
  1067. option("-q", "--quick") % "use heuristics for faster comparison"
  1068. );
  1069. auto mergeAlgo = (
  1070. command("diff") % "merge using diff" |
  1071. command("patch") % "merge using patch" |
  1072. ( command("content") % "merge based on content",
  1073. "content based merge options:" % (
  1074. option("--git-style") % "emulate git's merge behavior",
  1075. option("-m", "--marker") & value("marker") % "merge marker symbol"
  1076. )
  1077. )
  1078. );
  1079. auto mergeMode = "merge mode:" % (
  1080. command("merge"),
  1081. mergeAlgo,
  1082. required("-o") & value("outdir") % "target directory for merge result",
  1083. option("--show-conflicts") % "show merge conflicts during run"
  1084. );
  1085. auto firstOpt = "user interface options:" % (
  1086. option("-v", "--verbose") % "show detailed output",
  1087. option("-i", "--interactive") % "use interactive mode"
  1088. );
  1089. auto lastOpt = "mode-independent options:" % (
  1090. values("files") % "input files",
  1091. option("-r", "--recursive") % "descend into subdirectories",
  1092. option("-h", "--help") % "show help"
  1093. );
  1094. auto cli = (
  1095. firstOpt,
  1096. copyMode | compareMode | mergeMode | command("list"),
  1097. lastOpt
  1098. );
  1099. if(parse(argc, argv, cli)) {
  1100. // program logic...
  1101. } else {
  1102. auto fmt = doc_formatting{}.doc_column(31);
  1103. cout << make_man_page(cli, argv[0], fmt) << '\n';
  1104. }
  1105. ```
  1106. You could of course write down everything as one big expression (docstrings are omitted)...:
  1107. ```cpp
  1108. auto cli = (
  1109. option("-v", "--verbose"),
  1110. option("-i", "--interactive"),
  1111. (
  1112. ( (command("copy") | command("move")),
  1113. option("--all"), option("--replace"),
  1114. option("-f", "--force")
  1115. )
  1116. | ( command("compare"),
  1117. (command("date") | command("content")),
  1118. option("-b", "--binary"), option("-q", "--quick")
  1119. )
  1120. | ( command("merge"),
  1121. (
  1122. ( command("content"),
  1123. option("--git-style"),
  1124. option("-m", "--marker") & value("marker")
  1125. )
  1126. | command("diff")
  1127. | command("patch")
  1128. ),
  1129. required("-o") & value("outdir"),
  1130. option("--show-conflicts")
  1131. )
  1132. | command("list")
  1133. ),
  1134. values("files"),
  1135. option("-r", "--recursive"),
  1136. option("-h", "--help")
  1137. );
  1138. ```
  1139. ...but it is probably more readable and maintainable if you break up the CLI definition into logical parts.
  1140. Note:
  1141. ```
  1142. doc_formatting::split_alternatives(bool) //default: true
  1143. doc_formatting::alternatives_min_split_size(int) //default: 3
  1144. ```
  1145. control whether the usage is split up into several lines if any group inside an alternative exceeds a given minimum size.
  1146. ### An Example From [docopt]
  1147. ```man
  1148. Naval Fate.
  1149. Usage:
  1150. naval_fate ship new <name>...
  1151. naval_fate ship <name> move <x> <y> [--speed= <kn>]
  1152. naval_fate ship shoot <x> <y>
  1153. naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  1154. naval_fate -h | --help
  1155. naval_fate --version
  1156. Options:
  1157. --speed= <kn> Speed in knots [default: 10].
  1158. --moored Moored (anchored) mine.
  1159. --drifting Drifting mine.
  1160. -h, --help Show this screen.
  1161. --version Show version.
  1162. ```
  1163. This code defines the command line interface, handles the parsing result and
  1164. generates the above man page snippet.
  1165. ```cpp
  1166. int x = 0, y = 0;
  1167. float speed = 0.0f;
  1168. bool drift = true;
  1169. vector<string> names;
  1170. enum class mode { none, help, shipnew, shipmove, shipshoot, mineset, minerem};
  1171. mode selected = mode::none;
  1172. //define command line interface
  1173. auto coordinates = ( value("x", x), value("y", y) );
  1174. auto shipnew = ( command("new").set(selected,mode::shipnew),
  1175. values("name", names) );
  1176. auto shipmove = (
  1177. value("name", names),
  1178. command("move").set(selected,mode::shipmove), coordinates,
  1179. option("--speed=") & value("kn",speed) % "Speed in knots [default: 10]");
  1180. auto shipshoot = ( command("shoot").set(selected,mode::shipshoot),
  1181. coordinates );
  1182. auto mines = (
  1183. command("mine"),
  1184. (command("set" ).set(selected,mode::mineset) |
  1185. command("remove").set(selected,mode::minerem) ),
  1186. coordinates,
  1187. (option("--moored" ).set(drift,false) % "Moored (anchored) mine." |
  1188. option("--drifting").set(drift,true) % "Drifting mine." )
  1189. );
  1190. auto navalcli = (
  1191. ( command("ship"), ( shipnew | shipmove | shipshoot ) )
  1192. | mines,
  1193. | command("-h", "--help").set(selected,mode::help) % "Show this screen."
  1194. | command("--version")([]{ cout << "version 1.0\n"; }) % "Show version."
  1195. );
  1196. parse(argc, argv, navalcli);
  1197. //handle results
  1198. switch(m) {
  1199. case mode::none:
  1200. break;
  1201. case mode::help: {
  1202. auto fmt = doc_formatting{}
  1203. .first_column(2).doc_column(16)
  1204. .max_flags_per_param_in_usage(4);
  1205. cout << "Naval Fate.\n\nUsage:\n"
  1206. << usage_lines(navalcli, "naval_fate", fmt)
  1207. << "\n\nOptions:\n"
  1208. << documentation(navalcli, fmt) << '\n';
  1209. }
  1210. break;
  1211. }
  1212. //...
  1213. }
  1214. ```
  1215. ### Value Filters
  1216. If a parameter doesn't have flags, i.e. it is a value-parameter, a filter function will be used to test if it matches an argument string. The default filter is ```clipp::match::nonempty``` which will match any non-empty argument string.
  1217. If you want more control over what is matched, you can use some other predefined filters or you can write your own ones (see [here](#custom-value-filters)).
  1218. ```man
  1219. Usage: exec [-n <times>] [-l <line>...] [-b <ratio>] [-f <term>]
  1220. ```
  1221. ```cpp
  1222. int n = 1;
  1223. std::vector<int> lines;
  1224. double r = 1.0;
  1225. string term, name;
  1226. auto cli = (
  1227. option("-n", "--repeat") & integer("times", n),
  1228. option("-l", "--line") & integers("#", lines),
  1229. option("-r", "--ratio) & number("ratio", r),
  1230. option("-f", "--find") & word("term", term)
  1231. );
  1232. ```
  1233. #### Predefined Filtering Value-Parameters
  1234. ```cpp
  1235. auto cli = (
  1236. value("x"), //non-empty string
  1237. word("x"), //alphanumeric string
  1238. number("x"), //string representing integer or floating point number
  1239. integer("x") //string representing integral number
  1240. );
  1241. ```
  1242. Note that there are additional functions for
  1243. - optional parameters: ```opt_value```, ```opt_word```, ...
  1244. - repeatable parameters: ```values```, ```words```, ...
  1245. - repeatable, optional parameters: ```opt_values```, ```opt_words```, ...
  1246. #### Using Filters Explicitly
  1247. Two kinds of filters are supported right now that can be passed as first argument of ```value```, ```values```, ```opt_value``` or ```opt_values``` as well as argument of the constructor ```parameter::parameter(Filter&&)```
  1248. - Predicates ```(const string&) -> bool```
  1249. which should return true if and only if an argument is an exact match.
  1250. - Substring matchers ```(const string&) -> subrange```
  1251. which in case of a match also indicate the position and length of the matched substring within a command line argument.
  1252. ```cpp
  1253. string s;
  1254. value( match::length{1,5}, "str", s);
  1255. //or using the parameter class directly
  1256. auto p = parameter{ match::length{1,5} }
  1257. .positional(true).required(true)
  1258. .label("str").set(s);
  1259. ```
  1260. There are a couple of predefined filters in ```namespace clipp::match```, but you can of course write your own ones (see [here](#custom-value-filters)).
  1261. Here is another example that makes sure we don't catch any value starting with "-" as a filename:
  1262. ```cpp
  1263. auto cli = (
  1264. option("-a")
  1265. option("-f") & value(match::prefix_not("-"), "filename"),
  1266. option("-b")
  1267. );
  1268. ```
  1269. ```cpp
  1270. namespace clipp {
  1271. namespace match {
  1272. //simple predicates
  1273. bool none (const string&);
  1274. bool any (const string&);
  1275. bool nonempty (const string&);
  1276. bool alphabetic (const string&);
  1277. bool alphanumeric (const string&);
  1278. //filters with settings and substring matching
  1279. class numbers {
  1280. explicit numbers(char decimalPoint = '.', char digitSeparator = ',', char exponentSeparator = 'e');
  1281. subrange operator () (const string& arg);
  1282. };
  1283. class integers {
  1284. explicit integers(char digitSeparator = ',');
  1285. subrange operator () (const string& arg);
  1286. };
  1287. class substring {
  1288. explicit substring(const string& str);
  1289. subrange operator () (const string& arg);
  1290. };
  1291. class prefix {
  1292. explicit prefix(const string& prefix);
  1293. subrange operator () (const string& arg);
  1294. };
  1295. class prefix_not {
  1296. explicit prefix_not(const string& prefix);
  1297. subrange operator () (const string& arg);
  1298. };
  1299. class length {
  1300. explicit length(size_t exact);
  1301. explicit length(size_t min, size_t max);
  1302. subrange operator () (const string& arg);
  1303. };
  1304. } }
  1305. ```
  1306. ### Greedy Parameters
  1307. By default, the parser tries to identify a command line argument (in that order) as
  1308. - a single flag
  1309. - a concatenation of multiple, _joinable_ flags (in any order)
  1310. - a concatenation of a _joinable_ flag sequence in the order defined in the CLI code
  1311. - a single value parameter
  1312. - a concatenation of a _joinable_ flag/value sequence in the order defined in the CLI code
  1313. - a concatenation of _joinable_ flags & values in no particular order
  1314. If no match was found, the parser tries the same list again without any restrictions imposed by blocking (positional) parameters, conflicting alternatives, etc. If this leads to any match, an error will be reported. This way, _potential_, but illegal matches can be found and, e.g., conflicting alternatives can be reported.
  1315. Consider this CLI:
  1316. ```cpp
  1317. auto cli = ( option("-a"), option("-f") & value("filename"), option("-b") );
  1318. ```
  1319. If we give ```-f -b``` or ```-b -f -a``` as command line arguments, an error will be reported, since the value after ```-f``` is not optional.
  1320. This behavior is fine for most use cases.
  1321. But what if we want our program to take any string as a filename, because our filenames might also collide with flag names? We can make the ```filename``` value parameter greedy, so that the next string after ```-f``` will always be matched with highest priority as soon as ```-f``` was given:
  1322. ```cpp
  1323. auto cli = ( option("-a"), option("-f") & greedy(value("filename")), option("-b") );
  1324. ```
  1325. or using ```operator !```:
  1326. ```cpp
  1327. auto cli = ( option("-a"), option("-f") & !value("filename"), option("-b") );
  1328. ```
  1329. Now, every string coming after an ```-f``` will be used as filename.
  1330. If we don't want just *any* kind of match accepted, but still retain a higher priority for a value parameter, we could use a [value filter](#value-filters):
  1331. ```cpp
  1332. auto cli = (
  1333. ( command("A"),
  1334. option("-f") & !value(match::prefix_not("-"), "filename"),
  1335. option("-b")
  1336. ) |
  1337. ( command("B"),
  1338. option("-x")
  1339. )
  1340. );
  1341. ```
  1342. This way, the command line arguments ```A -f B``` will set the filename to "B" and produce no conflict error between the alternative commands ```A``` and ```B``` but ```A -f -b``` will still give an error.
  1343. Note, that there is an inherent decision problem: either we want the ```filename``` value to match no matter what, or we won't get proper error handling if someone forgets to specify a filename and gives ```A -f -b``` Also, there might be interfaces where we really want to catch something like ```A -f B``` as a command conflict.
  1344. ### Generalized Joinable Parameters
  1345. Not only flags, but arbitrary combinations of flags and values can be made joinable. This feature is especially powerful if combined with repeatable groups.
  1346. Important: in order for an argument to be matched by such expressions, no parameter requirements must be violated during the matching. Also, no partial argument matches are allowed.
  1347. #### Example 1: Counting Letters
  1348. ```man
  1349. Usage: counter [a|b]...
  1350. ```
  1351. ```cpp
  1352. int as = 0, bs = 0;
  1353. auto cli = joinable( repeatable(
  1354. option("a").call([&]{++as;}) |
  1355. option("b").call([&]{++bs;})
  1356. ) );
  1357. if(parse(argc, argv, cli))
  1358. cout << "as: " << as << "\nbs: " << bs << '\n';
  1359. else
  1360. cout << "Usage:\n" << usage_lines(cli, argv[0]) << '\n';
  1361. ```
  1362. Valid input includes:
  1363. ```
  1364. $ ./counter a
  1365. $ ./counter b
  1366. $ ./counter ab
  1367. $ ./counter abba
  1368. $ ./counter a b baba
  1369. $ ./counter a babba abab abbbbba b a ba a
  1370. ...
  1371. ```
  1372. #### Example 2: Listing Numbers
  1373. ```man
  1374. Usage: numbers ([,] [<number>])...
  1375. ```
  1376. ```cpp
  1377. std::vector<double> nums;
  1378. auto cli = joinable(repeatable( option(",") , opt_number("number", nums) ));
  1379. if(parse(argc, argv, cli)) {
  1380. cout << "numbers:\n";
  1381. for(auto n : nums) cout << n << '\n';
  1382. } else {
  1383. cout << "Usage:\n" << usage_lines(cli, argv[0]) << '\n';
  1384. }
  1385. ```
  1386. Valid input includes:
  1387. ```
  1388. $ ./numbers 1
  1389. $ ./numbers 1 2 3
  1390. $ ./numbers 1 , 2
  1391. $ ./numbers 1 , 2 , 3
  1392. $ ./numbers 1, 2, 3
  1393. $ ./numbers 1 ,2 ,3
  1394. $ ./numbers 1,2
  1395. $ ./numbers 1,2,3
  1396. $ ./numbers 1.1 , 2
  1397. $ ./numbers 1,2.3,4.5
  1398. $ ./numbers 1,2,3 4.2 5,6 2 7.1,8.23,9
  1399. ```
  1400. **Warning:** Be careful with joinable and repeatable parameters! The resulting command line interface might be a lot less intuitive to use than you think. It can also be hard to get the "grammar" of complex parsing expressions right.
  1401. The following definition for example, contains a subtle pitfall:
  1402. ```cpp
  1403. auto cli = joinable(repeatable( option(",") , number("number", nums) ));
  1404. // ^^^ non-optional
  1405. ```
  1406. This will not match arguments like ```"1,"```. This is, because, if the repeat group is 'hit' by any of its child parameters, all non-optional parameters must also match within the current 'repeat cycle'. So, if the parser hits the ```","``` it expects to find a number arg as well, because it is blocking (positional) and required. Only after seeing this number can it enter the next repeat cycle. Thus, the argument will not be matched, since joined matches are only valid if no error occured. Making the number optional solves the problem.
  1407. ### Custom Value Filters
  1408. Two kinds of filters are supported right now that can be passed as first argument of ```value```, ```values```, ```opt_value``` or ```opt_values``` as well as argument of the constructor ```parameter::parameter(Filter&&)```:
  1409. - Predicates ```(const string&) -> bool```
  1410. which should return true if and only if an argument is an exact match.
  1411. - Substring matchers ```(const string&) -> subrange```
  1412. which in case of a match also indicate the position and length of the matched substring within a command line argument.
  1413. #### Simple Predicate Example
  1414. ```man
  1415. Usage: annotate auto | (label <character>)
  1416. ```
  1417. ```cpp
  1418. auto is_char = [](const string& arg) { return arg.size() == 1 && std::isalpha(arg[0]); };
  1419. char lbl = ' ';
  1420. auto cli = ( command("auto") | ( command("label"), value(is_char, "character", lbl) ) );
  1421. ```
  1422. #### Substring Matcher Example
  1423. Let's write a program that takes strings and lists all tag names (```<tag>```) contained in them:
  1424. ```man
  1425. Usage: tagnames <string>...
  1426. ```
  1427. ```cpp
  1428. //custom filter
  1429. auto tag_name = [] (const string& arg) {
  1430. if(arg.size() < 3) return subrange{}; //too short
  1431. auto i = arg.find("<");
  1432. if(i == string::npos) return subrange{}; //no tag start found
  1433. auto j = arg.find(">", i+1);
  1434. if(j == string::npos) return subrange{}; //didn't find end of tag
  1435. return subrange{i,j-i+1}; //partial match {start, length}
  1436. };
  1437. std::set<string> tags;
  1438. auto cli = joinable(
  1439. values(tag_name, "string",
  1440. [&](const string& arg){ if(arg[1] != '/') tags.insert(arg);})
  1441. );
  1442. if(parse(argc, argv, cli)) {
  1443. cout << "tag names:\n";
  1444. for(const auto& t : tags) cout << t << '\n';
  1445. } else {
  1446. cout << "Usage:\n" << usage_lines(cli, "tagnames") << '\n';
  1447. }
  1448. ```
  1449. ```
  1450. $ ./tagnames "<cee><d><e></e></d></cee>" "<a><bo></bo></a>"
  1451. tag names:
  1452. <a>
  1453. <bo>
  1454. <cee>
  1455. <d>
  1456. <e>
  1457. ```
  1458. ### Sanity Checks
  1459. Check, if no flag occurs as prefix of any other flag (identical flags will be ignored):
  1460. ```cpp
  1461. auto cli = ( /* command line interface definition */);
  1462. assert( cli.flags_are_prefix_free() );
  1463. ```
  1464. Check common prefix of all flags, like for example "-" (or "/" on Windows):
  1465. ```cpp
  1466. auto cli = ( /* command line interface definition */);
  1467. assert( cli.common_flag_prefix() == "-" );
  1468. ```
  1469. ### Basic Error Handling
  1470. Each parameter can have error handler functions/lambdas/function objects for different fail cases attached to it:
  1471. - ```if_repeated``` is raised each time an argument is mapped to a parameter regardless of that parameter's repeatability setting
  1472. - ```if_missing``` is raised if a required parameter has no argument associated with it
  1473. - ```if_conflicted``` is raised if two or more arguments are mapped to more than one parameter of a group of alternatives
  1474. - ```if_blocked``` is raised if an argument can only be mapped to a parameter that was not reachable at the time (e.g. because a positional value was expected before that parameter or the parameter was in a non-active alternative branch)
  1475. #### Example:
  1476. ```man
  1477. Usage: send <file> -t <target>... [--http|--ftp]
  1478. ```
  1479. ```cpp
  1480. string filename;
  1481. vector<string> targets;
  1482. vector<string> wrong;
  1483. bool http = true;
  1484. auto istarget = match::prefix_not("-");
  1485. auto cli = (
  1486. value("file", filename)
  1487. .if_missing([]{ cout << "You need to provide a source filename!\n"; } )
  1488. .if_repeated([](int idx){ cout << "Only one source file allowed! (index " << idx << ")\n"; } )
  1489. ,
  1490. required("-t") & values(istarget, "target", targets)
  1491. .if_missing([]{ cout << "You need to provide at least one target filename!\n"; } )
  1492. .if_blocked([]{ cout << "Target names must not be given before the source file name!\n"; })
  1493. ,
  1494. option("--http").set(http,true) |
  1495. option("--ftp").set(http,false) % "protocol, default is http"
  1496. .if_conflicted([]{ cout << "You can only use one protocol at a time!\n"; } )
  1497. ,
  1498. any_other(wrong)
  1499. );
  1500. if(parse(argc, argv, cli) && wrong.empty()) {
  1501. cout << "OK\n";
  1502. /* ... */
  1503. } else {
  1504. for(const auto& arg : wrong) cout << "'" << arg << "' is not a valid argument\n";
  1505. cout << "Usage:" << usage_lines(cli,argv[0]) << '\n';
  1506. }
  1507. ```
  1508. An error handler can either have an empty parameter list or take an ```int``` which is set to the command line argument index where the error occured first.
  1509. The catch-all parameter made by ```any_other``` is used to catch command line arguments that are not supported.
  1510. The value parameter ```target``` will only match command line arguments that do not begin with ```"-"```, so that wrongly spelled options cannot be parsed as ```target``` value.
  1511. ### Parsing
  1512. ```cpp
  1513. auto cli = (
  1514. command("make"),
  1515. value("file") % "name of file to make",
  1516. option("-f", "--force") % "overwrite existing file"
  1517. );
  1518. //excludes argv[0]
  1519. parse(argc, argv, cli);
  1520. //if you want to include argv[0]
  1521. parse(argv, argv+argc, cli);
  1522. parse({"make", "out.txt"}, cli);
  1523. auto args = std::vector<std::string> {"make", "out.txt", "-f"};
  1524. parse(args, cli);
  1525. ```
  1526. The parse functions return an object of ```parsing_result``` which can be used for detailed analysis and will (explicitly) convert to false if any error occured during parsing.
  1527. ```cpp
  1528. auto result = parse(argc, argv, cli);
  1529. auto doc_label = [](const parameter& p) {
  1530. if(!p.flags().empty()) return p.flags().front();
  1531. if(!p.label().empty()) return p.label();
  1532. return doc_string{"<?>"};
  1533. };
  1534. cout << "args -> parameter mapping:\n";
  1535. for(const auto& m : result) {
  1536. os << "#" << m.index() << " " << m.arg() << " -> ";
  1537. auto p = m.param();
  1538. if(p) {
  1539. os << doc_label(*p) << " \t";
  1540. if(m.repeat() > 0) {
  1541. os << (m.bad_repeat() ? "[bad repeat " : "[repeat ")
  1542. << m.repeat() << "]";
  1543. }
  1544. if(m.blocked()) os << " [blocked]";
  1545. if(m.conflict()) os << " [conflict]";
  1546. os << '\n';
  1547. }
  1548. else {
  1549. os << " [unmapped]\n";
  1550. }
  1551. }
  1552. cout << "missing parameters:\n";
  1553. for(const auto& m : result.missing()) {
  1554. auto p = m.param();
  1555. if(p) {
  1556. os << doc_label(*p) << " \t";
  1557. os << " [missing after " << m.after_index() << "]\n";
  1558. }
  1559. }
  1560. ```
  1561. ### Documentation Generation
  1562. Generate usage lines and documentation from parameters:
  1563. ```cpp
  1564. auto cli = ( /* command line interface definition */ );
  1565. //used default formatting
  1566. cout << "Usage:\n" << usage_lines(cli, "progname")
  1567. << "\nOptions:\n" << documentation(cli) << '\n';
  1568. ```
  1569. ... or generate an entire man page in one go:
  1570. ```cpp
  1571. auto cli = ( /* command line interface definition */ );
  1572. cout << make_man_page(cli, "progname")
  1573. .prepend_section("DESCRIPTION", " The best thing since sliced bread.")
  1574. .append_section("LICENSE", " GPL3");
  1575. ```
  1576. #### Example
  1577. ```man
  1578. DESCRIPTION
  1579. Builds a database of words from text files.
  1580. SYNOPSIS
  1581. worddb help
  1582. worddb build (new|add) <file>
  1583. worddb query -i <infile> [-p]
  1584. worddb info space
  1585. worddb info statistics (words|chars)
  1586. worddb remove (any|all) <regex>
  1587. worddb modify [-c] [-u] [-m <size>]
  1588. OPTIONS
  1589. build commands
  1590. new make new database
  1591. add append to existing database
  1592. query settings
  1593. <infile> input file
  1594. -p, --pretty-print human friendly output
  1595. database info modes
  1596. space detailed memory occupation analysis
  1597. statistics analysis
  1598. words word frequency table
  1599. chars character frequency table
  1600. remove mode
  1601. <regex> regular expression filter
  1602. modification operations
  1603. -c, --compress compress database in-memory
  1604. -u, --unique keep only unique entries
  1605. -m, --memlimit max. size in RAM
  1606. LICENSE
  1607. GPL3
  1608. ```
  1609. The full code:
  1610. ```cpp
  1611. auto cli = (
  1612. command("help") |
  1613. ( command("build"),
  1614. "build commands" %
  1615. ( command("new") % "make new database"
  1616. | command("add") % "append to existing database"
  1617. ),
  1618. value("file")
  1619. ) |
  1620. ( command("query"),
  1621. "query settings" %
  1622. ( required("-i", "--input") & value("infile") % "input file",
  1623. option("-p", "--pretty-print") % "human friendly output")
  1624. ) |
  1625. ( command("info"),
  1626. "database info modes" % (
  1627. command("space") % "detailed memory occupation analysis" |
  1628. (
  1629. command("statistics"),
  1630. "statistics analysis" % (
  1631. command("words") % "word frequency table" |
  1632. command("chars") % "character frequency table"
  1633. )
  1634. )
  1635. )
  1636. ) |
  1637. "remove mode" % (
  1638. command("remove"),
  1639. "modify" % ( command("any") | command("all") ),
  1640. value("regex") % "regular expression filter"
  1641. ) |
  1642. ( command("modify"),
  1643. "modification operations" % (
  1644. option("-c", "--compress") % "compress database in-memory",
  1645. option("-u", "--unique") % "keep only unique entries",
  1646. option("-m", "--memlimit") % "max. size in RAM" & value("size")
  1647. )
  1648. )
  1649. );
  1650. auto fmt = doc_formatting{} .first_column(4) .doc_column(28) .last_column(80);
  1651. cout << make_man_page(cli, "worddb", fmt)
  1652. .prepend_section("DESCRIPTION", " Builds a database of words from text files.")
  1653. .append_section("LICENSE", " GPL3") << '\n';
  1654. ```
  1655. #### Formatting Options
  1656. ```cpp
  1657. //all formatting options (with their default values)
  1658. auto fmt = doc_formatting{}
  1659. .first_column(8) //left border column for text body
  1660. .doc_column(20) //column where parameter docstring starts
  1661. .last_column(100) //right border column for text body
  1662. .indent_size(4) //indent of documentation lines for children of a documented group
  1663. .line_spacing(0) //number of empty lines after single documentation lines
  1664. .paragraph_spacing(1) //number of empty lines before and after paragraphs
  1665. .flag_separator(", ") //between flags of the same parameter
  1666. .param_separator(" ") //between parameters
  1667. .group_separator(" ") //between groups (in usage)
  1668. .alternative_param_separator("|") //between alternative flags
  1669. .alternative_group_separator(" | ") //between alternative groups
  1670. .surround_group("(", ")") //surround groups with these
  1671. .surround_alternatives("(", ")") //surround group of alternatives with these
  1672. .surround_alternative_flags("", "") //surround alternative flags with these
  1673. .surround_joinable("(", ")") //surround group of joinable flags with these
  1674. .surround_optional("[", "]") //surround optional parameters with these
  1675. .surround_repeat("", "...") //surround repeatable parameters with these
  1676. .surround_value("<", ">") //surround values with these
  1677. .empty_label("") //used if parameter has no flags and no label
  1678. .max_flags_per_param_in_usage(1) //max. # of flags per parameter in usage
  1679. .max_flags_per_param_in_doc(32) //max. # of flags per parameter in detailed documentation
  1680. .split_alternatives(true) //split usage into several lines for large alternatives
  1681. .alternatives_min_split_size(3) //min. # of parameters for separate usage line
  1682. .merge_alternative_flags_with_common_prefix(false) //-ab(cdxy|xy) instead of -abcdxy|-abxy
  1683. .merge_joinable_flags_with_common_prefix(true) //-abc instead of -a -b -c
  1684. .ignore_newline_chars(false) //ignore '\n' in docstrings
  1685. ;
  1686. cout << "Usage:\n" << usage_lines(cli, "progname", fmt)
  1687. << "\nOptions:\n" << documentation(cli, fmt) << '\n';
  1688. //or generate entire man page in one go
  1689. cout << make_man_page(cli, "progname", fmt)
  1690. .prepend_section("DESCRIPTION", "This program lets you format text.")
  1691. .append_section("LICENSE", "GPLv3");
  1692. ```
  1693. ### Documentation Filtering
  1694. The documentation generator class ```documentation``` can also take an additional third constructor argument that allows to filter parameters according to their properties.
  1695. ```cpp
  1696. int main(int argc, char* argv[]) {
  1697. auto cli = (
  1698. value("input file"),
  1699. option("-r", "--recursive").set(rec).doc("convert files recursively"),
  1700. option("-o") & value("output format", fmt),
  1701. option("-utf16").set(utf16).doc("use UTF-16 encoding")
  1702. );
  1703. auto fmt = doc_formatting{}.doc_column(28);
  1704. auto filter = param_filter{}.prefix("--");
  1705. cout << "Usage:\n" << usage_lines(cli, argv[0]) << "\n\n"
  1706. << "Parameters:\n" << documentation(cli, fmt, filter) << '\n';}
  1707. ```
  1708. Which results in:
  1709. ```man
  1710. Usage:
  1711. convert <input file> [-r] [-o <output format>] [-utf16]
  1712. Parameters:
  1713. -r, --recursive convert files recursively
  1714. ```
  1715. #### Parameter Filters
  1716. Any function/lambda that maps a parameter to a bool can be used as filter
  1717. predicate. CLIPP also comes with a default parameter filter class:
  1718. ```cpp
  1719. //all param_filter options (with their default values)
  1720. auto filter = param_filter{}
  1721. .prefix("") //only parameters with given prefix
  1722. .required(tri::either) //required parameters
  1723. .blocking(tri::either) //blocking/positional parameters
  1724. .repeatable(tri::either) //repeatable parameters
  1725. .has_doc(tri::yes) //parameters with/without docstrings
  1726. ;
  1727. ```
  1728. which uses a dedicated tristate type:
  1729. ```cpp
  1730. namespace clipp {
  1731. enum class tri { no, yes, either };
  1732. }
  1733. ```
  1734. ## Motivation
  1735. Well, I didn't find a library that makes building simple command line interfaces simple, yet can also be used to build complex CLIs. I really don't want to write 20 lines of boilerplate just to have 3 simple command line options. I also don't want to drag along monstrosities like boost or Qt for that. Over time, *clipp* evolved into a domain specific language (in pure C++) that I hope can at least somewhat approach the readability of [docopt] but can leverage the benefits (toolability, etc.) of C++'s type system.
  1736. #### Other libraries (Boost, POCO, Qt, adishavit/Argh, Taywee/args ... or 'getopt')
  1737. - often involve a lot of boilerplate (also for very simple use cases)
  1738. - Some libs might be okay in terms of usability, but don't let you build complex interfaces
  1739. with nested alternatives, mixed commands & options, positional values, more than 2 flags per option, etc.
  1740. - I really like ad-hoc parsers like [Argh](https://github.com/adishavit/argh) for their simplicity, but they don't generate usage / man pages and don't allow complex interfaces with error checking.
  1741. - Most libs make it really hard to figure out the resulting command line interface by looking at the code (OK, you be the judge if I did a better job at this...).
  1742. - Some libs come with a ton of dependencies (Qt, Boost). I want a single header file!
  1743. - Some libs require the separation of code related to one command/option. I find this harder to maintain than having everything related to one option in one place.
  1744. - Sometimes flag strings of commands/options have to be repeated several times over.
  1745. - Many libs come with restrictions regarding flag names, formatting, joinability, etc.
  1746. #### What about [docopt]?
  1747. I like the basic idea, but I don't like redundancy in code, especially if it involves repeating string literals. Docopt generates a command line argument parser from a "man page docstring". After parsing, you have to query a dictionary to get values or check for option presence. That means you either have to mention the same flag names twice (in the docstring *and* in the query) or you have to use string variables which makes the docstring hard to read and kind of defeats the purpose of docopt. Furthermore, the code tends to be littered with string-to-whatever conversions.
  1748. I also wanted the ability to keep *everything* related to one option/command/value together in the code which I found very useful for programs with lots of command line options. Docopt doesn't let you do that since the interface definition and the code performing any actions is always separated (unless you give up on the "beautiful doc page" idea at the heart of docopt and build your input string to the parser generator piece-by-piece).
  1749. ## Design Goals
  1750. - minimize boilerplate
  1751. - simple code for simple use cases
  1752. - good code readability (as far as C++ allows for it)
  1753. - avoid ambiguities
  1754. - eliminate repetitions
  1755. - ability to keep code related to one option/command/value together
  1756. - support many different command line interface conventions
  1757. - support different coding styles, conventions & tastes
  1758. - value semantics wherever possible
  1759. - do not break clipp's general interface and conventions in the future
  1760. ## Requirements
  1761. - requires a mostly C++11 conforming compiler
  1762. ### Compilers, clipp compiles with
  1763. - g++ 5.3.0, g++ 5.4.1, g++ 6, g++ 7
  1764. - clang++ 3.8, clang++ 3.9, clang++ 4.0, clang++ 5.0
  1765. - MSVC 14.11.25503 (compiler 19.11.25547)
  1766. ## Feedback
  1767. I would be delighted to hear from anyone who uses *clipp* in their project(s). If you find bugs or design flaws or want to suggest improvements please open an issue or submit a pull request.
  1768. ## Development
  1769. *clipp* is still very young, so I probably won't add new features any time soon and rather:
  1770. - fix bugs
  1771. - improve test cases and coverage
  1772. - add more code documentation
  1773. - clean up the code / make it more understandable
  1774. - add the ability to use other string classes
  1775. [docopt]: http://docopt.org