argagg
/tmp/slackrepo/SBo/slackrepo.SdRaog/build_argagg/argagg-0.4.6/doc/root.md
Go to the documentation of this file.
1 Argument Aggregator {#mainpage}
2 ===================
3 
4 This is the Doxygen documentation for Argument Aggregator, a simple C++11 argument parser.
5 
6 To use just create an argagg::parser object. However, the struct doesn't provide any explicit methods for defining flags. Instead we define the flags using initialization lists.
7 
8  argagg::parser argparser {{
9  { "help", {"-h", "--help"},
10  "shows this help message", 0},
11  { "delim", {"-d", "--delim"},
12  "delimiter (default: ,)", 1},
13  { "num", {"-n", "--num"},
14  "number", 1},
15  }};
16 
17 An option is specified by four things: the name of the option, the strings that activate the option (flags), the option's help message, and the number of arguments the option expects.
18 
19 With the parser defined you actually parse the arguments by calling the argagg::parser::parse() method. If there are any problems then an exception is thrown.
20 
21  argagg::parser_results args;
22  try {
23  args = argparser.parse(argc, argv);
24  } catch (const std::exception& e) {
25  std::cerr << e.what() << std::endl;
26  return EXIT_FAILURE;
27  }
28 
29 You can check if an option shows up in the command line arguments by accessing the option by name from the parser results and using the implicit boolean conversion. You can write out a simplistic option help message by streaming the argagg::parser instance itself.
30 
31  if (args["help"]) {
32  std::cerr << argparser;
33  // -h, --help
34  // shows this help message
35  // -d, --delim
36  // delimiter (default: ,)
37  // -n, --num
38  // number
39  return EXIT_SUCCESS;
40  }
41 
42 That help message is only for the flags. If you want a usage message it's up to you to provide it.
43 
44  if (args["help"]) {
45  std::cerr << "Usage: program [options] ARG1 ARG2" << std::endl
46  << argparser;
47  // Usage: program [options] ARG1 ARG2
48  // -h, --help
49  // shows this help message
50  // -d, --delim
51  // delimiter (default: ,)
52  // -n, --num
53  // number
54  return EXIT_SUCCESS;
55  }
56 
57 A special output stream, argagg::fmt_ostream, is provided that will run the usage and help through `fmt` for nice word wrapping (see `./examples/joinargs.cpp` for a better example).
58 
59  if (args["help"]) {
60  argagg::fmt_ostream fmt(std::cerr);
61  fmt << "Usage: program [options] ARG1 ARG2" << std::endl
62  << argparser;
63  return EXIT_SUCCESS;
64  }
65 
66 Generally argagg tries to do a minimal amount of work to leave most of the control with the user.
67 
68 If you want to get an option argument but fallback on a default value if it doesn't exist then you can use the argagg::option_results::as() API and provide a default value.
69 
70  auto delim = args["delim"].as<std::string>(",");
71 
72 If you don't mind being implicit an implicit conversion operator is provided allowing you to write simple assignments.
73 
74  int x = 0;
75  if (args["num"]) {
76  x = args["num"];
77  }
78 
79 Finally, you can get all of the positional arguments as an std::vector using the argagg::parser_results::pos member. You can alternatively convert individual positional arguments using the same conversion functions as the option argument conversion methods.
80 
81  auto y = 0.0;
82  if (args.pos.size() > 0) {
83  y = args.as<double>(0);
84  }
85 
86 One can also specify `--` on the command line in order to treat all following arguments as not options.
87 
88 For a more detailed treatment take a look at the examples or test cases.
89 
90 Mental Model
91 ------------
92 
93 The parser just returns a structure of pointers to the C-strings in the original `argv` array. The @ref argagg::parser::parse() method returns a @ref argagg::parser_results object which has two things: position arguments and option results. The position arguments are just a @ref std::vector of `const char*`. The option results are a mapping from option name (@ref std::string) to @ref argagg::option_results objects. The @ref argagg::option_results objects are just an @ref std::vector of @ref argagg::option_result objects. Each instance of an @ref argagg::option_result represents the option showing up on the command line. If there was an argument associated with it then the @ref argagg::option_result::arg member will *not* be `nullptr`.
94 
95 Consider the following command:
96 
97  gcc -g -I/usr/local/include -I. -o test main.o foo.o -L/usr/local/lib -lz bar.o -lpng
98 
99 This would produce a structure like follows, written in psuedo-YAML, where each string is actually a `const char*` pointing to some part of a string in the original `argv` array:
100 
101  parser_results:
102  program: "gcc"
103  pos: ["main.o", "foo.o", "bar.o"]
104  options:
105  version:
106  debug:
107  all:
108  - arg: null
109  include_path:
110  all:
111  - arg: "/usr/local/include"
112  - arg: "."
113  library_path:
114  all:
115  - arg: "/usr/local/lib"
116  library:
117  all:
118  - arg: "z"
119  - arg: "png"
120  output:
121  all:
122  - arg: "test"
123 
124 Conversion to types occurs at the very end when the `as<T>()` API is used. Up to that point `argagg` is just dealing with C-strings.
125 
126 Installation
127 ------------
128 
129 There is just a single header file (`argagg.hpp`) so you can copy that whereever you want. If you want to properly install it you can use the CMake script. The CMake script exists primarily to build the tests and documentation, but an install target for the header is provided.
130 
131 The standard installation dance using CMake and `make` is as follows:
132 
133  mkdir build
134  cd build
135  cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
136  make install
137  ctest -V # optionally run tests
138 
139 Override [`CMAKE_INSTALL_PREFIX`](https://cmake.org/cmake/help/v2.8.12/cmake.html#variable:CMAKE_INSTALL_PREFIX) to change the installation location. By default (on UNIX variants) it will install to `/usr/local` resulting in the header being copied to `/usr/local/include/argagg/argagg.hpp`.
140 
141 If you have [Doxygen](http://www.stack.nl/~dimitri/doxygen/) it should build and install documentation as well.
142 
143 There are no dependencies other than the standard library.
144 
145 Edge Cases
146 ----------
147 
148 There are some interesting edge cases that show up in option parsing. I used the behavior of `gcc` as my target reference in these cases.
149 
150 ### Greedy Arguments
151 
152 Remember that options that require arguments will greedily process arguments.
153 
154 Say we have the following options: `-a`, `-b`, `-c`, and `-o`. They all don't accept arguments except `-o`. Below is a list of permutations for short flag grouping and the results:
155 
156 - `-abco foo`: `-o`'s argument is `foo`
157 - `-aboc foo`: `-o`'s argument is `c`, `foo` is a positional argument
158 - `-aobc foo`: `-o`'s argument is `bc`, `foo` is a positional argument
159 - `-oabc foo`: `-o`'s argument is `abc`, `foo` is a positional argument
160 
161 For whitespace delimited arguments the greedy processing means the next argument element (in `argv`) will be treated as an argument for the previous option, regardless of whether or not it looks like a flag or some other special entry. That means you get behavior like below:
162 
163 - `--output=foo -- --bar`: `--output`'s argument is `foo`, `--bar` is a positional argument
164 - `--output -- --bar`: `--output`'s argument is `--`, `--bar` is treated as a flag
165 - `--output --bar`: `--output`'s argument is `--bar`