If a non-positional argument doesn't get the number of required values,
a generic "Too few arguments" error is generated, without its name, when
it is not the last argument (but if it is the last argument, we get its
name)
This bug [1] causes GCC to emit a wrong warning when adding a short
string literal to a std::string. Wrapping the literal in a std::string
doesn't have a large impact and avoids the warning.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105329
Also fixes the incompatibility between store_into and scan and action:
when the three methods above were called, being all based on the
(unique) action, the last one would overwrite the previous ones.
This issue was making the parser strictly dependant on the order
of the scan/store_into/action calls making them mutually exclusive.
The argparse.hpp copy inside GDAL has caused Coverity Scan to emit a
(false-positive) warning about x not being initialized.
```
________________________________________________________________________________________________________
*** CID 1544814: Uninitialized variables (UNINIT)
/gdal/apps/argparse/argparse.hpp: 257 in gdal_argparse::details::do_from_chars<unsigned char, (int)10>(std::basic_string_view<char, std::char_traits<char>>)()
251 if (ec == std::errc::invalid_argument) {
252 throw std::invalid_argument{"pattern '" + std::string(s) + "' not found"};
253 }
254 if (ec == std::errc::result_out_of_range) {
255 throw std::range_error{"'" + std::string(s) + "' not representable"};
256 }
>>> CID 1544814: Uninitialized variables (UNINIT)
>>> Using uninitialized value "x".
```
Let's initialize it to 0 to make the analyzer happy
- Display mutually exclusive arguments as ``[[-a]|[-b]]`` in usage
- Add ... trailer to repeatable arguments in usage: ``[-x]...``
- Implement the following enhancements:
By default usage is reported on a single line.
The ``ArgumentParser::set_usage_max_line_width(width)`` method can be used
to display the usage() on multiple lines, by defining the maximum line width.
It can be combined with a call to ``ArgumentParser::set_usage_break_on_mutex()``
to ask grouped mutually exclusive arguments to be displayed on a separate line.
``ArgumentParser::add_usage_newline()`` can also be used to force the next
argument to be displayed on a new line in the usage output.
The following snippet
```cpp
argparse::ArgumentParser program("program");
program.set_usage_max_line_width(80);
program.set_usage_break_on_mutex();
program.add_argument("--quite-long-option-name").flag();
auto &group = program.add_mutually_exclusive_group();
group.add_argument("-a").flag();
group.add_argument("-b").flag();
program.add_argument("-c").flag();
program.add_argument("--another-one").flag();
program.add_argument("-d").flag();
program.add_argument("--yet-another-long-one").flag();
program.add_argument("--will-go-on-new-line").flag();
program.add_usage_newline();
program.add_argument("--new-line").flag();
std::cout << program.usage() << std::endl;
```
will display:
```console
Usage: program [--help] [--version] [--quite-long-option-name]
[[-a]|[-b]]
[-c] [--another-one] [-d] [--yet-another-long-one]
[--will-go-on-new-line]
[--new-line]
```
Furthermore arguments can be separated into several groups by calling
``ArgumentParser::add_group(group_name)``. Only optional arguments should
be specified after the first call to add_group().
```cpp
argparse::ArgumentParser program("program");
program.set_usage_max_line_width(80);
program.add_argument("-a").flag().help("help_a");
program.add_group("Advanced options");
program.add_argument("-b").flag().help("help_b");
```
will display:
```console
Usage: program [--help] [--version] [-a]
Advanced options:
[-b]
```