|
Boost Users : |
Subject: [Boost-users] [Program Options] terminate parsing after first positional argument
From: Stuart Pook (stuart8763_at_[hidden])
Date: 2012-07-04 11:21:16
Hello,
How can I tell Boost Program Options to stop parsing the arguments as soon as it finds a positional argument?
I'd like to be able to parse the argument list "-v chmod -R -v 600 foo" as having one argument for my program (-v) and the rest as a std::vector of std::string (including the -v).
In the attached program I have tried 2 different approaches. The first uses multitoken with the arguments "--command date -u -v", it fails because "-u" isn't known.
The second uses collect_unrecognized with "chmod -R -v 600", it doesn't work because -v is interpreted by boost and doesn't end up in the vector.
As someone said back in 2005, perhaps I'm trying to write xargs:
http://thread.gmane.org/gmane.comp.lib.boost.user/9529/focus=9641
I know that I can ask my users to write
a.out -v -- chmod -R -v 600 foo
but I don't want to do that. I want them to write "a.out -v chmod -R -v 600 foo". The first positional argument should should tell boost to stop processing.
Another slightly different question. If I have a multitoken option that takes doubles how can I get it to accept negative values? If I give my program "--floats 1 8 -4 6" where --floats starts a multitoken option that accepts double, I get an exception saying that "-4" is an unknown option.
thanks
Stuart
This is what my test program gives me with boost 1.50:
argv: dd --command date -u -v
unrecognised option '-u'
Allowed options:
-v [ --verbose ] verbose
--command arg command to run
2nd try
argv: dd chmod -R -v 600
I'm verbose
v: chmod -R 600
3rd try
argv: dd --floats 1 8 -4 6
unrecognised option '-4'
Allowed options:
-v [ --verbose ] verbose
-f [ --floats ] arg numbers
and my program (formatted to fit in 80 characters)
#include <boost/program_options.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <iostream>
namespace po = boost::program_options;
#define nelements(a) (sizeof (a) / sizeof (a)[0])
void print(char const * * b, char const * * e)
{
std::cout << "argv: ";
std::copy(b, e, std::ostream_iterator<char const *>(std::cout, " "));
std::cout << std::endl;
}
int main(int argc, char ** argv)
{
{
bool verbose;
std::vector<std::string> command;
po::options_description desc("Allowed options");
desc.add_options()
("verbose,v",
po::bool_switch(&verbose)->default_value(false), "verbose")
("command", po::value<std::vector<std::string> >(&command)
->multitoken(), "command to run")
;
char const * args[] = { "dd", "--command", "date", "-u", "-v", 0 };
print(args, args + nelements(args) - 1);
po::variables_map vm;
try
{
po::store(po::command_line_parser(nelements(args) - 1, args)
.options(desc).run(), vm);
po::notify(vm);
if (verbose)
std::cout << "I'm verbose\n";
std::cout << "command: ";
boost::copy(command,
std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
}
catch (boost::program_options::unknown_option & x)
{
std::cerr << x.what() << "\n" << desc << "\n";
}
}
std::cout << "2nd try\n";
{
bool verbose;
po::options_description desc("Allowed options");
desc.add_options()
("verbose,v",
po::bool_switch(&verbose)->default_value(false), "verbose")
;
char const * args[] = { "dd", "chmod", "-R", "-v", "600", 0 };
print(args, args + nelements(args) - 1);
po::variables_map vm;
po::parsed_options parsed =
po::command_line_parser(nelements(args) - 1, args).
options(desc).allow_unregistered().run();
try
{
po::store(parsed, vm);
}
catch (boost::program_options::unknown_option & x)
{
std::cerr << x.what() << "\n" << desc << "\n";
exit(2);
}
po::notify(vm);
if (verbose)
std::cout << "I'm verbose\n";
std::cout << "v: ";
std::vector<std::string> v = po::collect_unrecognized(
parsed.options,
po::include_positional);
boost::copy(v, std::ostream_iterator<std::string>(std::cout, " "));
std::cout << std::endl;
}
std::cout << "3rd try\n";
{
bool verbose;
std::vector<double> f;
po::options_description all("Allowed options");
all.add_options()
("verbose,v",
po::bool_switch(&verbose)->default_value(false), "verbose")
("floats,f",
po::value<std::vector<double> >(&f)->multitoken(), "numbers")
;
char const * args[] = { "dd", "--floats", "1", "8", "-4", "6", 0 };
print(args, args + nelements(args) - 1);
po::variables_map vm;
try
{
po::store(po::command_line_parser(nelements(args) - 1, args)
.options(all).run(), vm);
po::notify(vm);
if (verbose)
std::cout << "I'm verbose\n";
std::cout << "floats: ";
boost::copy(f, std::ostream_iterator<double>(std::cout, " "));
std::cout << std::endl;
}
catch (boost::program_options::unknown_option & x)
{
std::cerr << x.what() << "\n" << all << "\n";
}
}
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net