I am unable to emulate subcommands using positional options followed by unregistered_options

StackOverflow https://stackoverflow.com/questions/21358685

  •  02-10-2022
  •  | 
  •  

Question

I am trying to emulate something like this: apple --color red --count 5 orange --taste sour

Where I intend to make apple and orange as positional_option: subCommand and I intend to capture the remainder of options with values as unregistered options. Here is my sample code:

    po::options_description desc("Supported options");
     desc.add_options()
       ("subCom",po::value<string>(&sc),"")
       ;
    po::positional_options_description pos;
    pos.add("subCom",1);

    po::variables_map vm;
    po::parsed_options parsed =
       po::command_line_parser(argc, argv).options(desc).positional(pos).allow_unregistered().run();
    po::store(parsed, vm);
    po::notify(vm);

Now when I actually run this: apple --color red --count 5

I am getting the error: too many positional options. program options is considering red as a positional option instead of treating it as a value for unregistered option. Could you please suggest a work around to this problem?

Était-ce utile?

La solution

Try this (C++11, but if you wish you may to downgrade it easily)


#include <vector>
#include <string>

#include <boost/program_options.hpp>

namespace po = boost::program_options;
using namespace std;

int main(int argc, char* argv[]) {
    po::options_description visibleOpts;
    visibleOpts.add_options()
        ("help,h", "displays this help")
        ("verbose,v", po::value()->zero_tokens(), "increase debug level")
        ("silent,s", po::value()->zero_tokens(), "decrease debug level")
    ;
    po::options_description hiddenOpts("");
    vector files;
    hiddenOpts.add_options()
        ("input-file", po::value >(&files)->required());
    po::options_description opts;
    opts.add(visibleOpts).add(hiddenOpts);

    po::positional_options_description pos;
    pos.add("input-file", -1);

    // FIXME wrap this line with a proper try/catch
    po::command_line_parser clp(argc, argv);
    clp.options(visibleOpts).options(opts).positional(pos).allow_unregistered();
    po::variables_map vm;
    auto parsed = clp.run();
    po::store(parsed, vm);
    po::notify(vm);
    if (vm.count("silent"))
        cout << "silent was used" << endl;
    if (vm.count("verbose"))
        cout << "verbose was used" << endl;
    {
        vector unrecognized =
            po::collect_unrecognized(parsed.options, po::exclude_positional);
        if (!unrecognized.empty()) {
            cout << "Got " << unrecognized.size() << " unrecognized option(s):" << endl;
            for(auto uo: unrecognized)
                cout << '\t' << uo << endl;
        }
    }
    if (!files.empty()) {
        cout << "Got " << files.size() << " file(s):" << endl;
        for(auto f: files)
            cout << '\t' << f << endl;
    }
    return 0;
}

it gives me the following output:

alex@galene c++/tests/build $ ./boost_po_pos --silent --boo abcde ssss
silent was used
Got 1 unrecognized option(s):
        --boo
Got 2 file(s):
        abcde
        ssss
alex@galene c++/tests/build $ 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top