|
Boost : |
From: Vladimir Prus (ghost_at_[hidden])
Date: 2007-03-20 03:25:52
Tom Bachmann wrote:
Hi Tom,
> [I hope I'm on the right list..]
You are!
> I have been trying to extend Boost.Program_options, and I found this
> very hard. I'd like to let you know of the problems I'm experiancing.
>
> Basically, I am writing a relatively long-running program, with lots of
> options. I want to be able to change these options at run-time, for
> doing so, I want to create a "preferences" window or such, and (of
> course) I want to reuse the options description I already created to
> parse the command line and config file options.
This is an interesting direction!
> 1 change the values of options in a variables_map
>
> The only way to do this (as far as I can see) is the private interface
> that the store function uses. I currently do
>
> const_cast<boost::program_options::variable_value&> (vm[opt -> long_name
> ()]).value () = val;
>
> which is neither clean nor complete (the internal reference to
> value_semantic is not updated, but this should not be necessary anyway,
> I think).
> The easiest fix would be to add a public interface to change the value
> of an option in a variables map, by making op[] return a non-const
> reference. I'm not sure if code should be added to call semantic ->
> notify automically.
Yep, I guess we need non-const-returning[] for sure. We probably should
have variable_value overload operator=, and call semantic->notify. Do
you think disallowing assignements that change value type is OK? Say,
if you try to assign int to value of type double, you get exception.
> 2 find out the type of an option
>
> This is not strictly necessary, but I'd be nice to e.g show a checkbox
> for bool options, a spin button for numeric options, and an entry field
> for other options. I currently infer the type by querying the Boost.Any
> that holds the option, potentially after applying the default value.
> This is not foolproof, however, because it fails for options that have
> no default value and that have not been set before.
Technically speaking, the value_semantic base class does not require an
option to have any type at all. At the same time, in 100% of known cases
the type for an option is known. Perhaps I can either add 'type' method
to value_semantics that returns type_info* and may return NULL, or just
make it return type_info& and demand that all options have a fixed type.
Will either of those approaches work for you?
> 3 convert from an option value to some screen representation
>
> This is not strictly necessary either, but it'd be nice to show the user
> the current value of an option ;).
Heh!
> This is some sort of "backward parse"
> and can be easily put into the value_semantic class. Afterall, this is
> already done, when converting the default value into a string. It is,
> however, not strictly something one would usually expect from the
> value_semantic class. Currently I take the type information I already
> have (see 2), cast to the respective type and then convert using
> Boost.Lexical_cast. This is quiet cumbersome, because I need to know
> every possible type in advance and (automatically) instantiate code for
> every such type and dynamically dispatch to the right code (this is the
> main reason I created the dispatcher mentioned in another mail of mine).
One another approach is make variable_value record original tokens it
was constructed from. This correlates with your point (1) above --
perhaphs after UI was changed, value_semantics->parse should be called
to get new boost::any and the parsed tokens should be stored in variable_value.
> 4 find out what options in a po::options_description are members of what
> option groups
>
> This is necessary to group the options in multiple tabs. Again, there
> are only private interfaces to access the information.
The problem here is that when you add one options_description to
another options description, the original object is not retained, so
it's not simple to have "parent pointer". It might be possible to
have "parent group name" field in an option. Would that be too cumbersome
to construct UI hierarchy grouping options by string parent name?
> And I have a (unrelated) suggestion for an improvement: add an auxiliary
> functor for validating. Often there are certain conditions imposed on
> the options, e.g. a numeric option has to be in some interval or such.
> This checking can be done once after parsing, but it'd be cleaner to
> directly incorporate it. One could encode all the information in the
> type, but that'd be ugly. Using Boost.Lambda, I could imagine a syntax
> like:
>
> po::checked_value<int> (_1 > 0 && _1 < 5)
>
> instead of
>
> po::value<checked_val<int, bounds_checker<int, 1, 4> > > ()
Sigh. This is on todo list, but I haven't had any time for that.
- Volodya
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk