On Mon, 31 Oct 2005 boost@nogga.de wrote:
Hello,
I'm new to the boost::program_options library and tried to use it for a command pattern based software. The program is launched with the following commandline:
program command [Options] <Files>
The program can use different output formatters with --formatter={XML|binary|text}. Every command and formatter specify their own set of options.
I first tried to collect all options form the commands and formatters and parse the command line only once. This lead to the problem, that due to the different positional options information the commandline parser always threw an exception due to wrong command line formatting.
Since I couldn't find a way to add mutliple optional option groups to the parser, I moved the parsing code into my command base class and query the derived commands for the different required information, like:
class Command { public: vritual options_description GetOptionsDescription (); virtual options_description GetHiddenOptionsDescription (); virtual positional_program_options GetPositionalProgramOptions ();
virtual Run (variables_map const & vm) = 0; int Execute (std::vectorstd:.string args) { options_description desc; descr.add (GetOptionsDescription ()).add (GetHiddenOptionsDescription ());
variables_map vm; store(command_line_parser(args) .options(desc). .positional(GetPositionalProgramOptions ()) .run(), vm); notify(vm);
Run (vm); }
}
The execute function is called form the program main after the "command" has been stripped from the commandline and the concrete command was created by the factory. So far so good. This works for the different commands, but not for the formatters.
How can I parse the command line dynamically? E.g. if I encounter the "--formatter=xml" argument, a new XMLFormatter is created and the options description from this formatter are added to list of valid options?
I know, that there is the notify mechanism, but this only works after the commandline has been successfully parsed. And also the custom parsers do not solve my problem.
Any idea how to solve this issue?
How about using extra_parser ? You could so something like (assuming that there is a global variable 'desc' containing : struct select_formatter_options { options_descrition* opts ; select_formmatter_options( options_description& opts ) : opts( opts ) {} pair< string , string > operator () ( const string& arg ) { if ( opt == "--formatter=xml" ) { formatter = new XMLFormatter ; opts->add( formatter.options() ) ; } // else if etc. // The rest of the parsing can be done by the library return pair< string , string >() ; } } ; And then you do this: variables_map vm; store(command_line_parser(args) .options(desc). .positional( GetPositionalProgramOptions () ) .extra_parser( select_formatter_options( desc ) ) .run(), vm); notify(vm); I have no idea if this can really work though. And there is at least one caveat: the option "--formatter=whatever" can only have this form, not "--formatter whatever" or a short form "-f whatever" (but could be "-fwhatever" with the appropriate adjustment above). You can prevent the short option version, but Boost.Program_options allows the long option to be used with multiple tokens (e.g. "--formatter whatever"). You could reinforce that though by testing, after you call notify above, if the option was set, but if no formatter has been created. -- François Duranleau LIGUM, Université de Montréal "Voyager, c'est essayer de revenir avec quelques préjugés en moins." - Jean-Daniel Lafond