Commit 251266dc authored by Davis King's avatar Davis King

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.
parent 34f28d4a
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#ifndef DLIB_CMD_LINE_PARSER_KERNEl_1_ #ifndef DLIB_CMD_LINE_PARSER_KERNEl_1_
#define DLIB_CMD_LINE_PARSER_KERNEl_1_ #define DLIB_CMD_LINE_PARSER_KERNEl_1_
#include "cmd_line_parser_kernel_abstract.h"
#include "../algs.h" #include "../algs.h"
#include <string> #include <string>
#include <sstream> #include <sstream>
...@@ -148,6 +149,9 @@ namespace dlib ...@@ -148,6 +149,9 @@ namespace dlib
const std::basic_string<charT>& name ( const std::basic_string<charT>& name (
) const { return name_; } ) const { return name_; }
const std::basic_string<charT>& group_name (
) const { return group_name_; }
const std::basic_string<charT>& description ( const std::basic_string<charT>& description (
) const { return description_; } ) const { return description_; }
...@@ -207,6 +211,7 @@ namespace dlib ...@@ -207,6 +211,7 @@ namespace dlib
// data members // data members
std::basic_string<charT> name_; std::basic_string<charT> name_;
std::basic_string<charT> group_name_;
std::basic_string<charT> description_; std::basic_string<charT> description_;
sequence2 options; sequence2 options;
unsigned long number_of_arguments_; unsigned long number_of_arguments_;
...@@ -258,6 +263,13 @@ namespace dlib ...@@ -258,6 +263,13 @@ namespace dlib
unsigned long number_of_arguments = 0 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<charT>& option ( const cmd_line_parser_option<charT>& option (
const string_type& name const string_type& name
) const; ) const;
...@@ -301,6 +313,7 @@ namespace dlib ...@@ -301,6 +313,7 @@ namespace dlib
map options; map options;
sequence argv; sequence argv;
bool have_parsed_line; bool have_parsed_line;
string_type group_name;
// restricted functions // restricted functions
cmd_line_parser_kernel_1(cmd_line_parser_kernel_1&); // copy constructor cmd_line_parser_kernel_1(cmd_line_parser_kernel_1&); // copy constructor
...@@ -668,6 +681,22 @@ namespace dlib ...@@ -668,6 +681,22 @@ namespace dlib
return options.is_in_domain(name); return options.is_in_domain(name);
} }
// ----------------------------------------------------------------------------------------
template <
typename charT,
typename map,
typename sequence,
typename sequence2
>
void cmd_line_parser_kernel_1<charT,map,sequence,sequence2>::
set_group_name (
const string_type& group_name_
)
{
group_name = group_name_;
}
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
template < template <
...@@ -687,6 +716,7 @@ namespace dlib ...@@ -687,6 +716,7 @@ namespace dlib
try try
{ {
temp->name_ = name; temp->name_ = name;
temp->group_name_ = group_name;
temp->description_ = description; temp->description_ = description;
temp->number_of_arguments_ = number_of_arguments; temp->number_of_arguments_ = number_of_arguments;
void* t = temp; void* t = temp;
......
...@@ -24,8 +24,9 @@ namespace dlib ...@@ -24,8 +24,9 @@ namespace dlib
or wchar_t) or wchar_t)
INITIAL VALUE INITIAL VALUE
parsed_line() == false - parsed_line() == false
option_is_defined(x) == false, for all values of x - option_is_defined(x) == false, for all values of x
- get_group_name() == ""
ENUMERATION ORDER ENUMERATION ORDER
The enumerator will enumerate over all the options defined in *this The enumerator will enumerate over all the options defined in *this
...@@ -243,6 +244,7 @@ namespace dlib ...@@ -243,6 +244,7 @@ namespace dlib
- #option(name).count() == 0 - #option(name).count() == 0
- #option(name).description() == description - #option(name).description() == description
- #option(name).number_of_arguments() == number_of_arguments - #option(name).number_of_arguments() == number_of_arguments
- #option(name).group_name() == get_group_name()
throws throws
- std::bad_alloc - std::bad_alloc
if this exception is thrown then the add_option() function has no if this exception is thrown then the add_option() function has no
...@@ -314,6 +316,28 @@ namespace dlib ...@@ -314,6 +316,28 @@ namespace dlib
it will have no effect on the state of #*this. 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 // Input Validation Tools
// ------------------------------------------------------------- // -------------------------------------------------------------
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <map>
#include "../smart_pointers.h"
namespace dlib namespace dlib
{ {
...@@ -59,10 +61,11 @@ namespace dlib ...@@ -59,10 +61,11 @@ namespace dlib
typedef std::basic_string<ct> string; typedef std::basic_string<ct> string;
typedef typename string::size_type size_type; typedef typename string::size_type size_type;
typedef std::basic_ostringstream<ct> ostringstream;
try try
{ {
out << _dT(ct,"Options:");
size_type max_len = 0; size_type max_len = 0;
this->reset(); this->reset();
...@@ -99,6 +102,16 @@ namespace dlib ...@@ -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<string,shared_ptr<ostringstream> > 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 ...@@ -107,49 +120,72 @@ namespace dlib
while (this->move_next()) while (this->move_next())
{ {
ostringstream& sout = *groups[this->element().group_name()];
size_type len = 0; size_type len = 0;
out << _dT(ct,"\n -"); sout << _dT(ct,"\n -");
len += 3; len += 3;
if (this->element().name().size() > 1) if (this->element().name().size() > 1)
{ {
out << _dT(ct,"-"); sout << _dT(ct,"-");
++len; ++len;
} }
out << this->element().name(); sout << this->element().name();
len += this->element().name().size(); len += this->element().name().size();
if (this->element().number_of_arguments() == 1) if (this->element().number_of_arguments() == 1)
{ {
out << _dT(ct," <arg>"); sout << _dT(ct," <arg>");
len += 6; len += 6;
} }
else else
{ {
for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i) for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i)
{ {
out << _dT(ct," <arg") << i+1 << _dT(ct,">"); sout << _dT(ct," <arg") << i+1 << _dT(ct,">");
len += 7; len += 7;
if (i+1 > 9) if (i+1 > 9)
++len; ++len;
} }
} }
out << " "; sout << _dT(ct," ");
len += 3; len += 3;
while (len < max_len) while (len < max_len)
{ {
++len; ++len;
out << " "; sout << _dT(ct," ");
} }
const unsigned long ml = static_cast<unsigned long>(max_len); const unsigned long ml = static_cast<unsigned long>(max_len);
// now print the description but make it wrap around nicely if it // now print the description but make it wrap around nicely if it
// is to long to fit on one line. // is to long to fit on one line.
if (len <= max_len) if (len <= max_len)
out << wrap_string(this->element().description(),0,ml); sout << wrap_string(this->element().description(),0,ml);
else 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<string,shared_ptr<ostringstream> >::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"); out << _dT(ct,"\n\n");
this->reset(); this->reset();
......
...@@ -39,6 +39,14 @@ namespace dlib ...@@ -39,6 +39,14 @@ namespace dlib
- returns the name of this option - 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 ( virtual const string_type& description (
) const = 0; ) const = 0;
/*! /*!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment