|
Boost : |
From: Rozental, Gennadiy (gennadiy.rozental_at_[hidden])
Date: 2003-05-27 15:29:42
>> > 2. Layered design.
> > IMO All of my
> > concerns are unfortunate consequences of the way you designed your
> > library. IMO there should be one typed storage for the parsed
> arguments
> > (instead of 3 like you have) linked with formal parameters
description.
> You are not correct. There are two storage mechanism for parsed data.
> First
> ('options_and_arguments') stores *only* strings. Second
> ('variables_map')
> stores typed values. So, there's one typed storage.
1. You store something inside class cmdline
2. You store strings in options_and_arguments
3. You store typed values in variables_map
In my opinion 2 places are redundant. You should only have one.
> > Plus second layer managing composition of parameter originated by
> > different sources.
> That's 'variables_map'.
But variables map is part of first layer, it's store typed arguments. And it
almost
does not have any functionality I expect to see on this second layer
dedicated to combinind parameters from different sources.
> >> > b. Force same style for all parameters in command line (I could
>not
>>> > define /h --my_long_param)
>>>
>>> Do you need it in practice?
>>
>> Why not. Maybe different modules require parameters in different
>style.
>
>I feel this to be artifical example, and would not be surprised if no
>user
>of program_options will ever want it. And if it wants... custom parsers
>can be used.
But this is part of functionaly you supply out of the box. And now i need ot
rewrite it.
You keep repeating: "use custom parser". I wonder why would I need this
framework then.
>>> desc.add_options()
>>> // first argument is options name
>>> // second argument is parameter name
>>> // third argument is description
>>> ("output", "file", "output file")
>>> ....
>>> ;
>>>
>>> This means that one comment line is added for first argument, and
>then
>>> you can very conveniently specify option name.
>>
>> Poor maintenance programmer looked on this code and spread hands
>puzzled:
>> What is option name and what is parameter name???? Which one should I
>use
>> to identify argument? Where the value assigned? What is default value?
>
>Sorry, but this kind of questions can be answered only in docs.
Sorry. But this is not good enough for me.
In my terms above would look like this:
parameter<std::string>( "output" )
<< place_to( output_file_name )
<< default_value( "/tmp/abc" )
<< description( "output file name" )
You do not need to know anything in addition about how parser works.
Moreover it's unifies and easily extendable to adopt different modifers.
>> class cmdline access methods:
>> option_name()
>> option_index()
>> raw_option_name();
>> option_value();
>> option_values();
>> argument();
>> arguments();
>>
>> You obviously struggle from need to provide on one hand container
>> interface, on the other iterator one.
>> Plus instead of N methods returning
>> properties of option there should be one that returns foe example
>'option'
>> structure.
>... which 'option' structure would contain the same set of methods?
>Let's
>consider the needs of 'cmdline' clients. You have
> cmdline cmd(....);
> while(++cmd) {
> if (cmd.at_option()) {
> ...
> }
> }
>
>With iterators, that would become
>
> for(cmdline_iterator i(...), e; i != e; ++i) {
> if (i->is_option()) {
>
>
>Wait! Again, what's 'value_type'. Some imaginary 'option_or_argument'
>class?
>boost::variant? boost::any? Yep, that would be an interator, but you
>gain
>nothing. It will be only input iterator, and with such a specialized
>'value_type', that to use that iterator, you need to known that you're
>dealing with command line --- there's no place for genericity.
>
>I'd probably buy your argument if you'd say that one can devise class
>'option' and make command line parser, config file parser and something
>else parser iterator, with 'option' as the value type. That would be
>nice,
>but it can't be done. cmdline has addition 'raw_option_name' member
>function, and config_file cannot return arguments. The interfaces are a
>bit
>different.
In my design I provide rnadom access iterator to the storage of parsed
arguments of
type cla::argument. And I could use whatever generic algorithm I like with
it.
Why does anybody need raw_option_name()?
Also it's beyond my understanding why we need at_option, at_argument. May be
it's because I still could not get what meaning you use for these terms in
this context.
I parsed argc/argv, stored typed argument. Now I only need ot get the value
out of argument I identifued somehow (by name, or index, or order -
whatever)
> my_prog --service name=>Repository ...
>
> Here parameter name is service name, separator is string "=>", value
is
> 'Repository'.
> Nope. It's not supported by cmdline class.
And you would not be able to support it within the bounds of your design.
>> > 9. Multi-pass parsing support
> If that's not sufficient (which I doubt), I can think of a more general
> solution. Basically, 'cmdline' class can allow unregistered options.
> With
> a bit of tweaking, it can return unparsed tokens.
There is a solution. But it's not trivial. And not in a bound ot your
current design.
>> If you're use error codes, you'd have
>> to check it after calling each function.
>
> No. I would not. In majority of the cases I do not bother whether any
> intermediate step fails, parsing or validation fails. Whatever
happened
> during CLA declaration, parsing and validation I just want to get a
> notification about an error during CLA parsing procedure and have and
> access to the error message. IOW it would look like this:
>
> > cla::parser p;
> > p << parameter<int>( "name" )
> > ....
> > if( ! p.parse(argc,argv) ) {
> > cout << p.error_msg() << endl;
> > p.usage();
> > return 1;
> > }
>
> I don't see here handling of response files or config files... if you
> were
> to add it, would you write the same "if" block a couple of times?
I may have several if spatements:
if( cla_parser.parse(...) ) ...
if( config_file.parse(...) ) ...
...
It's not worse than several catch clauses. Try/catch seems redundant when
used right aroung the function that throw an exception.
>> > Moreover in many interfaces library assumes existence on long
name,
>> > short
>> > name, which may not be the case even with name based parameter
>> > identification.
>>
>> I don't understand what you mean here.
>
> > I may not have long name, but only short one, like with old getopt
> had.
> It's not a problem. You'd still use the long name for identification
> purposes, but disable long names in command line.
I don't get it. What long name would I use if it only have short name.
> > I may not have short name but only long one, like the style I am
> > personally prefer.
> What's problem with this case? It's supported out-of-box.
What would you return when user call short name method?
>> > 15. External parsers support.
> > I do not want to store parsed values inside the parser at all. Instead
> I
> > want to register for every parameter callback function.
> That's another example I don't see any use for. What will those callback
> functions do. Can you given some more details why it might be needed?
Let say I have method set_trace_level that manage tracing level for you
application.
What I need is in my terms look like this:
parameter<int>( "trace_level" )
<< default_value( 0 )
<< handler( set_trace_level )
<< description( "specifies the trace level for the application" )
Now when argc/argv parsed argument value is not stored into list of parsed
argument. Instead
handler function call and parsed value passed.
I may have different parsers for all my parameters.
> - Volodya
Gennadiy.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk