allow command to accept "--" separator
authorAlvaro Leiva Geisse <aleivag@fb.com>
Mon, 15 Jan 2018 22:07:55 +0000 (14:07 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 15 Jan 2018 22:33:10 +0000 (14:33 -0800)
Summary:
Currently NestedCommandLineApp does not support `--` to indicate that the following arguments should be parsed as arguments, not nested commands or options.
This diff fix that by whitelisting any argument given after "--"

Reviewed By: yfeldblum

Differential Revision: D6721144

fbshipit-source-id: 38a850b6ea803dc758c5fe65a21575e5faeac35b

folly/experimental/NestedCommandLineApp.cpp
folly/experimental/test/NestedCommandLineAppTest.cpp

index 789a8f43fb7f0c887ce430637a25db8bdefbbac8..e694f1f5d545548853db29c6042ab680c96ad4d4 100644 (file)
@@ -228,7 +228,22 @@ void NestedCommandLineApp::doRun(const std::vector<std::string>& args) {
   if (programName_.empty()) {
     programName_ = guessProgramName();
   }
   if (programName_.empty()) {
     programName_ = guessProgramName();
   }
-  auto parsed = parseNestedCommandLine(args, globalOptions_);
+
+  bool not_clean = false;
+  std::vector<std::string> cleanArgs;
+  std::vector<std::string> endArgs;
+
+  for (auto& na : args) {
+    if (na == "--") {
+      not_clean = true;
+    } else if (not_clean) {
+      endArgs.push_back(na);
+    } else {
+      cleanArgs.push_back(na);
+    }
+  }
+
+  auto parsed = parseNestedCommandLine(cleanArgs, globalOptions_);
   po::variables_map vm;
   po::store(parsed.options, vm);
   if (vm.count("help")) {
   po::variables_map vm;
   po::store(parsed.options, vm);
   if (vm.count("help")) {
@@ -258,12 +273,15 @@ void NestedCommandLineApp::doRun(const std::vector<std::string>& args) {
 
   auto cmdOptions =
     po::command_line_parser(parsed.rest).options(info.options).run();
 
   auto cmdOptions =
     po::command_line_parser(parsed.rest).options(info.options).run();
+
   po::store(cmdOptions, vm);
   po::notify(vm);
 
   auto cmdArgs = po::collect_unrecognized(cmdOptions.options,
                                           po::include_positional);
 
   po::store(cmdOptions, vm);
   po::notify(vm);
 
   auto cmdArgs = po::collect_unrecognized(cmdOptions.options,
                                           po::include_positional);
 
+  cmdArgs.insert(cmdArgs.end(), endArgs.begin(), endArgs.end());
+
   if (initFunction_) {
     initFunction_(cmd, vm, cmdArgs);
   }
   if (initFunction_) {
     initFunction_(cmd, vm, cmdArgs);
   }
index 27c698da81780154f1819dfc641fed1bb0cfd4c1..3d8e3acfabf99e672e90907af7141be832e7d618 100644 (file)
@@ -75,6 +75,7 @@ TEST(ProgramOptionsTest, Help) {
   callHelper({"--help"});
   callHelper({"--help", "foo"});
   callHelper({"--help", "bar"});
   callHelper({"--help"});
   callHelper({"--help", "foo"});
   callHelper({"--help", "bar"});
+  callHelper({"--help", "--", "bar"});
   callHelper({"help"});
   callHelper({"help", "foo"});
   callHelper({"help", "bar"});
   callHelper({"help"});
   callHelper({"help", "foo"});
   callHelper({"help", "bar"});
@@ -82,6 +83,9 @@ TEST(ProgramOptionsTest, Help) {
   // wrong command name
   callHelper({"--help", "qux"}, 1);
   callHelper({"help", "qux"}, 1);
   // wrong command name
   callHelper({"--help", "qux"}, 1);
   callHelper({"help", "qux"}, 1);
+
+  // anything after -- is parsed as arguments
+  callHelper({"--", "help", "bar"}, 1);
 }
 
 TEST(ProgramOptionsTest, DevFull) {
 }
 
 TEST(ProgramOptionsTest, DevFull) {
@@ -89,6 +93,20 @@ TEST(ProgramOptionsTest, DevFull) {
   callHelper({"--help"}, 1, full.fd());
 }
 
   callHelper({"--help"}, 1, full.fd());
 }
 
+TEST(ProgramOptionsTest, CutArguments) {
+  // anything after -- is parsed as arguments
+  EXPECT_EQ(
+      "running foo\n"
+      "foo global-foo 43\n"
+      "foo local-foo 42\n"
+      "foo arg b\n"
+      "foo arg --local-foo\n"
+      "foo arg 44\n"
+      "foo arg a\n",
+      callHelper(
+          {"foo", "--global-foo", "43", "--", "b", "--local-foo", "44", "a"}));
+}
+
 TEST(ProgramOptionsTest, Success) {
   EXPECT_EQ(
       "running foo\n"
 TEST(ProgramOptionsTest, Success) {
   EXPECT_EQ(
       "running foo\n"