diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a1a17d..a066720d 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 533b23ee..402d5efb 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 b4efebdb..f41d948e 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 00000000..6d570e1b --- /dev/null +++ b/examples/inter_argument_order.cpp @@ -0,0 +1,48 @@ +#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 bae90197..f4729cda 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -81,6 +81,9 @@ class App { /// This is faster and cleaner than storing just a list of strings and reparsing. This may contain the -- separator. missing_t missing_; + /// This is a list of pointers to options with the orignal parse order + std::vector