// Copyright (C) 2005 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_CMD_LINE_PARSER_PRINt_1_
#define DLIB_CMD_LINE_PARSER_PRINt_1_
#include "cmd_line_parser_kernel_abstract.h"
#include "../algs.h"
#include "../string.h"
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <memory>
namespace dlib
{
template <
typename clp_base
>
class cmd_line_parser_print_1 : public clp_base
{
public:
void print_options (
std::basic_ostream<typename clp_base::char_type>& out
) const;
void print_options (
) const
{
print_options(std::cout);
}
};
template <
typename clp_base
>
inline void swap (
cmd_line_parser_print_1<clp_base>& a,
cmd_line_parser_print_1<clp_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename clp_base
>
void cmd_line_parser_print_1<clp_base>::
print_options (
std::basic_ostream<typename clp_base::char_type>& out
) const
{
typedef typename clp_base::char_type ct;
typedef std::basic_string<ct> string;
typedef typename string::size_type size_type;
typedef std::basic_ostringstream<ct> ostringstream;
try
{
size_type max_len = 0;
this->reset();
// this loop here is just the bottom loop but without the print statements.
// I'm doing this to figure out what len should be.
while (this->move_next())
{
size_type len = 0;
len += 3;
if (this->element().name().size() > 1)
{
++len;
}
len += this->element().name().size();
if (this->element().number_of_arguments() == 1)
{
len += 6;
}
else
{
for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i)
{
len += 7;
if (i+1 > 9)
++len;
}
}
len += 3;
if (len < 33)
max_len = std::max(max_len,len);
}
// 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,std::shared_ptr<ostringstream> > groups;
this->reset();
while(this->move_next())
{
if (!groups[this->element().group_name()])
groups[this->element().group_name()].reset(new ostringstream);
}
this->reset();
while (this->move_next())
{
ostringstream& sout = *groups[this->element().group_name()];
size_type len = 0;
sout << _dT(ct,"\n -");
len += 3;
if (this->element().name().size() > 1)
{
sout << _dT(ct,"-");
++len;
}
sout << this->element().name();
len += this->element().name().size();
if (this->element().number_of_arguments() == 1)
{
sout << _dT(ct," <arg>");
len += 6;
}
else
{
for (unsigned long i = 0; i < this->element().number_of_arguments(); ++i)
{
sout << _dT(ct," <arg") << i+1 << _dT(ct,">");
len += 7;
if (i+1 > 9)
++len;
}
}
sout << _dT(ct," ");
len += 3;
while (len < max_len)
{
++len;
sout << _dT(ct," ");
}
const unsigned long ml = static_cast<unsigned long>(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)
sout << wrap_string(this->element().description(),0,ml);
else
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,std::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");
this->reset();
}
catch (...)
{
this->reset();
throw;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CMD_LINE_PARSER_PRINt_1_