From 251266dce86dcf3ecdbdcbf4682a4e1216887ac2 Mon Sep 17 00:00:00 2001 From: Davis King Date: Wed, 12 Dec 2012 20:53:50 -0500 Subject: [PATCH] Added a group name feature to the command line parser. Now it is possible to make print_options() print related options so that they are grouped together. --- .../cmd_line_parser_kernel_1.h | 30 ++++++++++ .../cmd_line_parser_kernel_abstract.h | 28 +++++++++- .../cmd_line_parser/cmd_line_parser_print_1.h | 56 +++++++++++++++---- dlib/interfaces/cmd_line_parser_option.h | 8 +++ 4 files changed, 110 insertions(+), 12 deletions(-) diff --git a/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h b/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h index 82c01489f..4b38b1c88 100644 --- a/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h +++ b/dlib/cmd_line_parser/cmd_line_parser_kernel_1.h @@ -3,6 +3,7 @@ #ifndef DLIB_CMD_LINE_PARSER_KERNEl_1_ #define DLIB_CMD_LINE_PARSER_KERNEl_1_ +#include "cmd_line_parser_kernel_abstract.h" #include "../algs.h" #include #include @@ -148,6 +149,9 @@ namespace dlib const std::basic_string& name ( ) const { return name_; } + const std::basic_string& group_name ( + ) const { return group_name_; } + const std::basic_string& description ( ) const { return description_; } @@ -207,6 +211,7 @@ namespace dlib // data members std::basic_string name_; + std::basic_string group_name_; std::basic_string description_; sequence2 options; unsigned long number_of_arguments_; @@ -258,6 +263,13 @@ namespace dlib unsigned long number_of_arguments = 0 ); + void set_group_name ( + const string_type& group_name + ); + + string_type get_group_name ( + ) const { return group_name; } + const cmd_line_parser_option& option ( const string_type& name ) const; @@ -301,6 +313,7 @@ namespace dlib map options; sequence argv; bool have_parsed_line; + string_type group_name; // restricted functions cmd_line_parser_kernel_1(cmd_line_parser_kernel_1&); // copy constructor @@ -668,6 +681,22 @@ namespace dlib return options.is_in_domain(name); } +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename map, + typename sequence, + typename sequence2 + > + void cmd_line_parser_kernel_1:: + set_group_name ( + const string_type& group_name_ + ) + { + group_name = group_name_; + } + // ---------------------------------------------------------------------------------------- template < @@ -687,6 +716,7 @@ namespace dlib try { temp->name_ = name; + temp->group_name_ = group_name; temp->description_ = description; temp->number_of_arguments_ = number_of_arguments; void* t = temp; diff --git a/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h b/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h index c377f8a5a..8461ffb26 100644 --- a/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h +++ b/dlib/cmd_line_parser/cmd_line_parser_kernel_abstract.h @@ -24,8 +24,9 @@ namespace dlib or wchar_t) INITIAL VALUE - parsed_line() == false - option_is_defined(x) == false, for all values of x + - parsed_line() == false + - option_is_defined(x) == false, for all values of x + - get_group_name() == "" ENUMERATION ORDER The enumerator will enumerate over all the options defined in *this @@ -243,6 +244,7 @@ namespace dlib - #option(name).count() == 0 - #option(name).description() == description - #option(name).number_of_arguments() == number_of_arguments + - #option(name).group_name() == get_group_name() throws - std::bad_alloc if this exception is thrown then the add_option() function has no @@ -314,6 +316,28 @@ namespace dlib it will have no effect on the state of #*this. !*/ + string_type get_group_name ( + ) const; + /*! + ensures + - returns the current group name. This is the group new options will be + added into when added via add_option(). + - The group name of an option is used by print_options(). In particular, + it groups all options with the same group name together and displays them + under a title containing the text of the group name. This allows you to + group similar options together in the output of print_options(). + - A group name of "" (i.e. the empty string) means that no group name is + set. + !*/ + + void set_group_name ( + const string_type& group_name + ); + /*! + ensures + - #get_group_name() == group_name + !*/ + // ------------------------------------------------------------- // Input Validation Tools // ------------------------------------------------------------- diff --git a/dlib/cmd_line_parser/cmd_line_parser_print_1.h b/dlib/cmd_line_parser/cmd_line_parser_print_1.h index 7748e37d3..3ff30b0df 100644 --- a/dlib/cmd_line_parser/cmd_line_parser_print_1.h +++ b/dlib/cmd_line_parser/cmd_line_parser_print_1.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include "../smart_pointers.h" namespace dlib { @@ -59,10 +61,11 @@ namespace dlib typedef std::basic_string string; typedef typename string::size_type size_type; + typedef std::basic_ostringstream ostringstream; + try { - out << _dT(ct,"Options:"); size_type max_len = 0; this->reset(); @@ -99,6 +102,16 @@ namespace dlib } + // Make a separate ostringstream for each option group. We are going to write + // the output for each group to a separate ostringstream so that we can keep + // them grouped together in the final output. + std::map > groups; + this->reset(); + while(this->move_next()) + { + if (!groups[this->element().group_name()]) + groups[this->element().group_name()].reset(new ostringstream); + } @@ -107,49 +120,72 @@ namespace dlib while (this->move_next()) { + ostringstream& sout = *groups[this->element().group_name()]; + size_type len = 0; - out << _dT(ct,"\n -"); + sout << _dT(ct,"\n -"); len += 3; if (this->element().name().size() > 1) { - out << _dT(ct,"-"); + sout << _dT(ct,"-"); ++len; } - out << this->element().name(); + sout << this->element().name(); len += this->element().name().size(); if (this->element().number_of_arguments() == 1) { - out << _dT(ct," "); + sout << _dT(ct," "); len += 6; } else { for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i) { - out << _dT(ct," "); + sout << _dT(ct," "); len += 7; if (i+1 > 9) ++len; } } - out << " "; + sout << _dT(ct," "); len += 3; while (len < max_len) { ++len; - out << " "; + sout << _dT(ct," "); } const unsigned long ml = static_cast(max_len); // now print the description but make it wrap around nicely if it // is to long to fit on one line. if (len <= max_len) - out << wrap_string(this->element().description(),0,ml); + sout << wrap_string(this->element().description(),0,ml); else - out << "\n" << wrap_string(this->element().description(),ml,ml); + sout << _dT(ct,"\n") << wrap_string(this->element().description(),ml,ml); + } + + // Only print out a generic Options: group name if there is an unnamed option + // present. + if (groups.count(string()) == 1) + out << _dT(ct,"Options:"); + + // Now print everything out + typename std::map >::iterator i; + for (i = groups.begin(); i != groups.end(); ++i) + { + // print the group name if we have one + if (i->first.size() != 0) + { + if (i != groups.begin()) + out << _dT(ct,"\n\n"); + out << i->first << _dT(ct,":"); + } + + // print the options in the group + out << i->second->str(); } out << _dT(ct,"\n\n"); this->reset(); diff --git a/dlib/interfaces/cmd_line_parser_option.h b/dlib/interfaces/cmd_line_parser_option.h index 19a259029..5861cf26a 100644 --- a/dlib/interfaces/cmd_line_parser_option.h +++ b/dlib/interfaces/cmd_line_parser_option.h @@ -39,6 +39,14 @@ namespace dlib - returns the name of this option !*/ + virtual const string_type& group_name ( + ) const = 0; + /*! + ensures + - returns the name of the group this option is in. If no group was set for + this option then this function returns "". + !*/ + virtual const string_type& description ( ) const = 0; /*!