diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a1a17..a066720 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## Version 1.1 (in progress) +* Added `app.parse_order()` with original parse order + ## Version 1.0 * Cleanup using `clang-tidy` and `clang-format` * Small improvements to Timers, easier to subclass Error diff --git a/README.md b/README.md index 533b23e..402d5ef 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ On the command line, options can be given as: * `--file=filename` (equals) Extra positional arguments will cause the program to exit, so at least one positional option with a vector is recommended if you want to allow extraneous arguments. -If you set `.allow_extras()` on the main `App`, the parse function will return the left over arguments instead of throwing an error. +If you set `.allow_extras()` on the main `App`, the parse function will return the left over arguments instead of throwing an error. You can access a vector of pointers to the parsed options in the original order using `parse_order()`. If `--` is present in the command line, everything after that is positional only. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b4efebd..f41d948 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -17,3 +17,4 @@ endfunction() add_cli_exe(simple simple.cpp) add_cli_exe(subcommands subcommands.cpp) add_cli_exe(groups groups.cpp) +add_cli_exe(inter_argument_order inter_argument_order.cpp) diff --git a/examples/inter_argument_order.cpp b/examples/inter_argument_order.cpp new file mode 100644 index 0000000..8056523 --- /dev/null +++ b/examples/inter_argument_order.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) { + CLI::App app; + + std::vector foos; + auto foo = app.add_option("--foo,-f", foos); + + std::vector bars; + auto bar = app.add_option("--bar", bars); + + app.add_flag("--z,--x"); // Random other flags + + // Standard parsing lines (copy and paste in) + try { + app.parse(argc, argv); + } catch (const CLI::ParseError &e) { + return app.exit(e); + } + + // I perfer using the back and popping + std::reverse(std::begin(foos), std::end(foos)); + std::reverse(std::begin(bars), std::end(bars)); + + std::vector> keyval; + for(auto option : app.parse_order()) { + if(option == foo) { + keyval.emplace_back("foo", foos.back()); + foos.pop_back(); + } + if(option == bar) { + keyval.emplace_back("bar", bars.back()); + bars.pop_back(); + } + } + + // Prove the vector is correct + std::string name; + int value; + + for(auto& tuple : keyval) { + std::tie(name, value) = tuple; + std::cout << name << " : " << value << std::endl; + } +} + + diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index 8a17c80..d5ed30d 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -254,7 +254,7 @@ class App { variable.emplace_back(); retval &= detail::lexical_cast(a, variable.back()); } - return variable.size() > 0 && retval; + return (!variable.empty()) && retval; }; Option *opt = add_option(name, fun, description, defaulted);