Ticket #6991: po-allow_interspersed.patch

File po-allow_interspersed.patch, 7.3 KB (added by driscoll@…, 10 years ago)
  • boost/program_options/cmdline.hpp

     
    2020    It's possible to introduce long options by the same character as
    2121    short options, see allow_long_disguise.
    2222
    23     Finally, guessing (specifying only prefix of option) and case
     23    Guessing (specifying only prefix of option) and case
    2424    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.
    2529    */
    2630    enum style_t {
    2731        /// Allow "--long_name" style
     
    7579            e.g <tt>-foo=10</tt>
    7680        */
    7781        allow_long_disguise = short_case_insensitive << 1,
     82        /** Allow 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        allow_interspersed = allow_long_disguise << 1,
    7887        /** The more-or-less traditional unix style. */
    7988        unix_style = (allow_short | short_allow_adjacent | short_allow_next
    8089                      | allow_long | long_allow_adjacent | long_allow_next
    8190                      | allow_sticky | allow_guessing
    82                       | allow_dash_for_short),
     91                      | allow_dash_for_short | allow_interspersed),
    8392        /** The default style. */
    8493        default_style = unix_style
    8594    };
  • boost/program_options/detail/cmdline.hpp

     
    107107        std::vector<option> parse_disguised_long_option(
    108108            std::vector<std::string>& args);
    109109        std::vector<option> parse_terminator(
    110             std::vector<std::string>& args);
     110            std::vector<std::string>& args, bool always_stop);
    111111        std::vector<option> handle_additional_parser(
    112112            std::vector<std::string>& args);
    113113
  • libs/program_options/test/cmdline_test.cpp

     
    368368        allow_short | short_allow_adjacent
    369369        | allow_dash_for_short       
    370370        | allow_long | long_allow_adjacent
    371         | allow_guessing | allow_long_disguise);
     371        | allow_guessing | allow_long_disguise
     372        | allow_interspersed);
    372373
    373374    test_case test_cases1[] = {
    374375        {"--opt1", s_success, "opt123:"},
     
    397398    style = cmdline::style_t(
    398399        allow_short | allow_long
    399400        | allow_dash_for_short
    400         | short_allow_adjacent | long_allow_adjacent);
     401        | short_allow_adjacent | long_allow_adjacent
     402        | allow_interspersed);
    401403
    402404    test_case test_cases1[] = {
    403405        {"-f file -gx file2", s_success, "-f: file -g:x file2"},
     
    411413
    412414    style = cmdline::style_t(
    413415        allow_short | short_allow_adjacent
    414         | allow_dash_for_short);
     416        | allow_dash_for_short
     417        | allow_interspersed);
    415418
    416419    test_case test_cases2[] = {
    417420        {"-f - -gx - -- -e", s_success, "-f: - -g:x - -e"},
  • libs/program_options/test/positional_options_test.cpp

     
    55
    66#include <boost/program_options/positional_options.hpp>
    77#include <boost/program_options/options_description.hpp>
     8#include <boost/program_options/variables_map.hpp>
    89#include <boost/program_options/parsers.hpp>
     10#include <boost/program_options/cmdline.hpp>
    911using namespace boost::program_options;
     12using namespace boost::program_options::command_line_style;
    1013// We'll use po::value everywhere to workaround vc6 bug.
    1114namespace po = boost::program_options;
    1215
     
    8285                      too_many_positional_options_error);
    8386}
    8487
     88
     89void 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 & ~allow_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
    85138int main(int, char* [])
    86139{
    87140    test_positional_options();
     141    test_interspersed();
    88142    test_parsing();
    89143    return 0;
    90144}
  • libs/program_options/src/cmdline.cpp

     
    241241        if ((m_style & allow_short) && (m_style & allow_slash_for_short))
    242242            style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1));
    243243
    244         style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1));
     244        bool always_stop = !(m_style & allow_interspersed);
     245        style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1, always_stop));
    245246
    246247        vector<option> result;
    247248        while(!args.empty())
     
    664665    }
    665666
    666667    vector<option>
    667     cmdline::parse_terminator(vector<string>& args)
     668    cmdline::parse_terminator(vector<string>& args, bool always_stop)
    668669    {
    669670        vector<option> result;
    670671        const string& tok = args[0];
    671         if (tok == "--")
     672        if (tok == "--" || always_stop)
    672673        {
    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)
    674677            {
    675678                option opt;
    676679                opt.value.push_back(args[i]);