Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion [Program Options] terminate parsing after first positional argument
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Stuart Pook  
View profile  
 More options Jul 4 2012, 11:21 am
From: Stuart Pook <stuart8...@pook.it>
Date: Wed, 04 Jul 2012 17:21:16 +0200
Local: Wed, Jul 4 2012 11:21 am
Subject: [Boost-users] [Program Options] terminate parsing after first positional argument
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 mailing list
Boost-us...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.