Hi, Volodya. About month ago, while working on Boost.Test issues I was faced with the need for the more or less full featured command line argument parser. I recall that you were working on one and took a look on some of your preliminary code in vault area. And ... was really disappointed. I do not believe that any "solid" design could fit for variety of different needs/expectations that exist. One big class with many many options/styles does not look like good design decision. I was not able to look into deep details with your current submission, but from what I view even if it better it still has similar design. While we are at it I could make 2 remarks about your submission: a) None of 5 compiler configurations installed on my XP could not compile it. b) see separate post regarding you config file design with is also unsatisfactory IMO. So I made my move and implemented my own solution, that I will be call: CLA framework. It's still missing some bits and pieces, particularly docs is not started yet. But I will present it as an alternative to your submission. (Though I may not be able to work on this within following month due to extreme load with other activities). Here is short description of my design. Rationale. While working on this design I was trying to concentrate on: 1. Usability 2. Flexibility 3. Usability 4. Flexibility 5. Minimal dependencies (specifically on other boost libs) 6. Clarity/simplicity All types are kept simple and defined in namespace boost::cla.
Terminology: Parameter - format parameter defined by programmer for it's program Argument - actual argument supplied by the end used to the program Option - boolean parameter cla::parser Class cla::parser is core class in a framework. It's definition looks like this: template<typename LookupPolicy> class parser : public LookupPolicy { typedef typename LookupPolicy::policy_base_parameter policy_base_parameter; public: parser& register_parameter( policy_base_parameter const& parameter ); template<typename Modifier> parser& accept_modifier( Modifier const& m ) iterator first_argument() const; iterator last_argument() const; std::string const& error_msg() const; bool is_valid() const; bool parse( int& argc, char** argv ); }; template<typename LookupPolicy, typename Parameter_or_Modifier> inline parser<LookupPolicy>& operator<<( parser<LookupPolicy>& p, Parameter_or_Modifier const& rhs ); This is in fact almost hollow class that in most part forward real work to the policy. It's main purpose to define framework interface and store the arguments. (What is the deal with modifiers see below). cla::parser design similar the Pluggable Factory Design pattern and implemented close to my implementation of the pattern in vault area. Lookup policy Lookup policy is in a sense an algorithm for parsing the arguments from the input provided. Each specific lookup policy could incur what type of the parameters/modifiers it's supports. Currently framework itself present following lookup policies; key_lookup_policy - each parameter is identified by unique key positional_lookup policy - each parameter is identified by position in input dual_lookup_policy - each parameter is identified by dual (most probably long/short) key getopt_lookup_policy - getopt style option parsing (with sticky options) simple_xml_lookup_policy - as a prove of concept lookup policy that allows to parse parameters passed in XML format See below for details how one of them is implemented Parameters definition. So, how the programmer will define parameters. Here an example: cla::parser<cla::key_lookup_policy<> > cla_parser; cla_parser << cla::named_parameter<>( "arg1" ) << cla::optional << cla::handler<std::string>( &arg1_handler ) << cla::named_parameter<std::list<int> >( "arg2" ) << cla::required << cla::named_option( "debug" ) << cla::required << cla::default_value( false ) << cla::place_to( is_debug ); Parameter definition format is defined by cla::parser class and always looks like this: <parser> [<< lookup policy modifiers] [<< parameter [<< parameter modifiers]]*; You could define as many parameters as you want. Allowed types of the parameters are defined by the lookup policy (you will need to see the code to see how it's working). Any policy may define and support any modifiers (modifier is similar to iostream manipulator concept). For example key_lookup_policy supports ignore_mismatch modifier, in which case lookup algorithm will ignore the errors in input and skip them. Any parameter type could also define modifiers. Some of the modifiers are supported by all parameters. For example: optional, requires, description( string ) Note again that any custom policy could define it's own parameters and modifiers Argument access. The framework provide several ways to access the parsed argument values 1. Through first_argument/last_argument interface. It will work if parameter will create typed formal argument (inherited from typed_argument<T> ) It will look like this: cla::parser<...>::iterator it = parser.first_argument(); cla::argument* arg = *it long value = cla::get_value<long>( arg ); 2. Most parameter types supports cla::place_to modifier that allows to set the argument value directly to the variable supplied. 3. Most parameter types supports cla::handler modifier that allows to set specific handler (any handler with predefined interface) for any parameter parsing event. That allows to implement event driven parameters parsing. 4. Since parser is publicly inherited from LookupPolicy it could always extend it's interface. Particularly key_lookup_policy add operator[] access with key argument. You will need to use cla::get_value then to get the value. Public interfaces Even though I was trying to minimize the dependencies. class framework may still be a burden to include in many compilation units. In case if one wants to access cla::parser in different (from where it was created/parsed) file, lookup policies supports public virtual interface that defined in one header with no dependencies. So including namely this one header is enough in most case to get an access to the argument values. Key lookup policy design class template key_lookup_policy defined like this: template<typename KeyPolicy = default_key_policy<> > class key_lookup_policy : public KeyPolicy, public key_based_interface { public: argument const* operator[]( std::string arg_name ) const; protected: // lookup policy implementation typedef named_parameter_base policy_base_parameter; void register_parameter( policy_base_parameter const& parameter ); policy_base_parameter const* locate_parameter( raw_argv_traverser& ); // support for modifiers void accept_modifier( separator ); void accept_modifier( prefix ); void accept_modifier( ignore_mismatch ); void accept_modifier( mismatch_handler ); }; This class is parameterized with Key policy that encapsulate logic with Key identification, key prefix and key/value separator. This policy allows to set arbitrary string/char as allowed prefix/separator (or even several of them), may successfully skip mismatched tokens and more. Usage/Help cla::parser also supply usage and help methods. First one supposed to give usage information, second - detailed information about all parameters. To define the usage/help format programmer could supply Usage/HelpFormattter implementation. Hope this overview gave you some idea how the framework will work. Any comments appreciated, Gennadiy. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost