Ticket #6991: po-disallow_interspersed.patch
File po-disallow_interspersed.patch, 5.8 KB (added by , 10 years ago) |
---|
-
boost/program_options/cmdline.hpp
20 20 It's possible to introduce long options by the same character as 21 21 short options, see allow_long_disguise. 22 22 23 Finally, guessing (specifying only prefix of option) and case23 Guessing (specifying only prefix of option) and case 24 24 insensitive processing are supported. 25 26 Enabling and disabling interspersed arguments is also supported; with 27 interspersed arguments disabled, everything after the first positional 28 argument is treated as positional. 25 29 */ 26 30 enum style_t { 27 31 /// Allow "--long_name" style … … 75 79 e.g <tt>-foo=10</tt> 76 80 */ 77 81 allow_long_disguise = short_case_insensitive << 1, 82 /** Disallowing interspersed arguments, e.g. <tt>mycmd file1 --opt</tt> 83 will treat <tt>--opt</tt> as an option instead of a positional 84 argument. 85 */ 86 disallow_interspersed = allow_long_disguise << 1, 78 87 /** The more-or-less traditional unix style. */ 79 88 unix_style = (allow_short | short_allow_adjacent | short_allow_next 80 89 | allow_long | long_allow_adjacent | long_allow_next -
boost/program_options/detail/cmdline.hpp
107 107 std::vector<option> parse_disguised_long_option( 108 108 std::vector<std::string>& args); 109 109 std::vector<option> parse_terminator( 110 std::vector<std::string>& args );110 std::vector<std::string>& args, bool always_stop); 111 111 std::vector<option> handle_additional_parser( 112 112 std::vector<std::string>& args); 113 113 -
libs/program_options/test/positional_options_test.cpp
5 5 6 6 #include <boost/program_options/positional_options.hpp> 7 7 #include <boost/program_options/options_description.hpp> 8 #include <boost/program_options/variables_map.hpp> 8 9 #include <boost/program_options/parsers.hpp> 10 #include <boost/program_options/cmdline.hpp> 9 11 using namespace boost::program_options; 12 using namespace boost::program_options::command_line_style; 10 13 // We'll use po::value everywhere to workaround vc6 bug. 11 14 namespace po = boost::program_options; 12 15 … … 82 85 too_many_positional_options_error); 83 86 } 84 87 88 89 void test_interspersed() 90 { 91 options_description desc; 92 desc.add_options() 93 ("first", po::value<int>()) 94 ("second", po::value<int>()) 95 ("positionals", po::value< vector<string> >()) 96 ; 97 98 positional_options_description p; 99 p.add("positionals", -1); 100 101 vector<string> args; 102 args.push_back("--first=10"); 103 args.push_back("file1"); 104 args.push_back("--second=10"); 105 args.push_back("file2"); 106 107 // Check that --second was recognized as the second option 108 variables_map vm; 109 store(command_line_parser(args).options(desc).positional(p).run(), 110 vm); 111 notify(vm); 112 113 BOOST_CHECK_EQUAL(vm.count("first"), 1); 114 BOOST_CHECK_EQUAL(vm.count("second"), 1); 115 vector<string> positionals = vm["positionals"].as<vector<string> >(); 116 BOOST_REQUIRE(positionals.size() == 2); 117 BOOST_CHECK_EQUAL(positionals[0], "file1"); 118 BOOST_CHECK_EQUAL(positionals[1], "file2"); 119 120 // Now check that --second was NOT recognized as the second option, but 121 // as the second positional 122 style_t style = style_t(default_style | disallow_interspersed); 123 vm.clear(); 124 store(command_line_parser(args).options(desc).positional(p).style(style).run(), 125 vm); 126 notify(vm); 127 128 BOOST_CHECK_EQUAL(vm.count("first"), 1); 129 BOOST_CHECK_EQUAL(vm.count("second"), 0); 130 positionals = vm["positionals"].as<vector<string> >(); 131 BOOST_REQUIRE(positionals.size() == 3); 132 BOOST_CHECK_EQUAL(positionals[0], "file1"); 133 BOOST_CHECK_EQUAL(positionals[1], "--second=10"); 134 BOOST_CHECK_EQUAL(positionals[2], "file2"); 135 } 136 137 85 138 int main(int, char* []) 86 139 { 87 140 test_positional_options(); 141 test_interspersed(); 88 142 test_parsing(); 89 143 return 0; 90 144 } -
libs/program_options/src/cmdline.cpp
241 241 if ((m_style & allow_short) && (m_style & allow_slash_for_short)) 242 242 style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1)); 243 243 244 style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1)); 244 bool always_stop = m_style & disallow_interspersed; 245 style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1, always_stop)); 245 246 246 247 vector<option> result; 247 248 while(!args.empty()) … … 664 665 } 665 666 666 667 vector<option> 667 cmdline::parse_terminator(vector<string>& args )668 cmdline::parse_terminator(vector<string>& args, bool always_stop) 668 669 { 669 670 vector<option> result; 670 671 const string& tok = args[0]; 671 if (tok == "--" )672 if (tok == "--" || always_stop) 672 673 { 673 for(unsigned i = 1; i < args.size(); ++i) 674 // Starting at index 1 skips the --. 675 unsigned start = tok == "--" ? 1 : 0; 676 for(unsigned i = start; i < args.size(); ++i) 674 677 { 675 678 option opt; 676 679 opt.value.push_back(args[i]);