pettersson
pettersson

Reputation: 327

Boost::program_options how to parse multiple multi_tokens

is it possible to parse multiple mulit-token parameters with the same name?

Like: program.exe --param a b c --param foo bar ?

I only could get it to work like this: program.exe --param "a b c" --param "foo bar" but then I have to split the parameter myself.

[...]
options.add_options()("param", po::value<vector<string>>()->multitoken()               
    , "description")
[...]

thanks for any hints

Upvotes: 1

Views: 219

Answers (1)

sehe
sehe

Reputation: 393114

I think you want a combination of composing and multi-token:

Live On Coliru

#include <boost/program_options.hpp>
#include <fmt/ranges.h>
namespace po = boost::program_options;
using strings = std::vector<std::string>;

int main(int argc, char** argv) {
    po::options_description opts;
    opts.add_options()("param",
                       po::value<strings>()
                           ->multitoken()
                           ->composing()
                           ->default_value({}, "")
                           ->implicit_value({}, ""),
                       "you know the drill");

    po::variables_map vm;
    store(parse_command_line(argc, argv, opts), vm);

    if (vm.contains("param")) {
        fmt::print("Params: {}\n", vm["param"].as<strings>());
    }
}

Which prints e.g.:

+ ./a.out
Params: []
+ ./a.out --param
Params: []
+ ./a.out --param a b
Params: ["a", "b"]
+ ./a.out --param a b --param c d
Params: ["a", "b", "c", "d"]

Note, if you don't want to allow --param without a value, remove the implicit_value: Live On Coliru

UPDATE

To the comment:

You can always use the parser section of the library, inspecting the parsed_options instance:

// using parsed-options to see "source" material:
auto parsed = parse_command_line(argc, argv, opts);
for (auto& po : parsed.options) {
    auto key = po.position_key == -1 //
        ? po.string_key
        : '#' + std::to_string(po.position_key);

    fmt::print("Option {}: {}\n", key, po.value);
}

// original logic:
store(parsed, vm);

if (vm.contains("param")) {
    fmt::print("Effective combined params: {}\n", vm["param"].as<strings>());
}

See it Live On Coliru, printing:

+ ./a.out
Effective combined params: []
+ ./a.out --param
Option param: []
Effective combined params: []
+ ./a.out --param a b
Option param: ["a", "b"]
Effective combined params: ["a", "b"]
+ ./a.out --param a b --param c d
Option param: ["a", "b"]
Option param: ["c", "d"]
Effective combined params: ["a", "b", "c", "d"]

Upvotes: 1

Related Questions