diff --git a/include/CLI/App.hpp b/include/CLI/App.hpp index bae90197..8b3e29fb 100644 --- a/include/CLI/App.hpp +++ b/include/CLI/App.hpp @@ -57,6 +57,9 @@ class App { /// If true, allow extra arguments (ie, don't throw an error). bool allow_extras_{false}; + /// If true, return immediatly on an unrecognised option (implies allow_extras) + bool prefix_command_{false}; + /// This is a function that runs when complete. Great for subcommands. Can throw. std::function callback_; @@ -149,6 +152,12 @@ class App { return this; } + /// Do not parse anything after the first unrecongnised option and return + App *prefix_command(bool allow = true) { + prefix_command_ = allow; + return this; + } + /// Ignore case. Subcommand inherit value. App *ignore_case(bool value = true) { ignore_case_ = value; @@ -849,7 +858,7 @@ class App { return val.first != detail::Classifer::POSITIONAL_MARK; }); - if(num_left_over > 0 && !allow_extras_) + if(num_left_over > 0 && !(allow_extras_ || prefix_command_)) throw ExtrasError("[" + detail::rjoin(args, " ") + "]"); } } @@ -959,7 +968,15 @@ class App { else { args.pop_back(); missing()->emplace_back(detail::Classifer::NONE, positional); + + if(prefix_command_) { + for(std::string positional : args) { + missing()->emplace_back(detail::Classifer::NONE, args.back()); + args.pop_back(); + } + } } + } /// Parse a subcommand, modify args and continue diff --git a/tests/SubcommandTest.cpp b/tests/SubcommandTest.cpp index ef363abf..c2753705 100644 --- a/tests/SubcommandTest.cpp +++ b/tests/SubcommandTest.cpp @@ -231,6 +231,19 @@ TEST_F(TApp, BadSubcomSearch) { EXPECT_THROW(app.get_subcommand(two), CLI::OptionNotFound); } +TEST_F(TApp, PrefixProgram) { + + app.prefix_command(); + + app.add_flag("--simple"); + + args = {"--simple", "other", "--simple", "--mine"}; + auto ret_args = run(); + + EXPECT_EQ(ret_args, std::vector({"--mine", "--simple", "other"})); + +} + struct SubcommandProgram : public TApp { CLI::App *start;