35 parseSpec( spec , sep_major , sep_minor , escape ) ;
36 std::sort( m_names.begin() , m_names.end() ) ;
39 void G::Options::parseSpec(
const std::string & spec ,
char sep_major ,
char sep_minor ,
char escape )
43 outer_part.reserve( 40U ) ;
44 std::string ws_major( 1U , sep_major ) ;
48 for( StringArray::iterator p = outer_part.begin() ; p != outer_part.end() ; ++p )
51 if( (*p).empty() )
continue ;
53 inner_part.reserve( 7U ) ;
54 std::string ws_minor( 1U , sep_minor ) ;
56 if( inner_part.size() != 7U )
58 std::ostringstream ss ;
59 ss <<
"\"" << *p <<
"\" (" << ws_minor <<
")" ;
60 throw InvalidSpecification( ss.str() ) ;
63 unsigned int value_multiplicity =
G::Str::toUInt( inner_part[4U] ) ;
65 std::string short_form = inner_part[0] ;
66 char c = short_form.empty() ?
'\0' : short_form.at(0U) ;
68 addSpec( inner_part[1U] , c , inner_part[2U] ,
69 inner_part[3U] , value_multiplicity , inner_part[5U] , level ) ;
73 void G::Options::addSpec(
const std::string & name ,
char c ,
74 const std::string & description ,
const std::string & description_extra ,
75 unsigned int value_multiplicity ,
const std::string & value_description ,
unsigned int level )
77 std::pair<Map::iterator,bool> rc = m_map.insert( std::make_pair( name ,
78 Option(c,name,description,description_extra,value_multiplicity,value_description,level) ) ) ;
80 throw InvalidSpecification(
"duplication") ;
81 m_names.push_back( name ) ;
86 return valued( lookup(c) ) ;
91 Map::const_iterator p = m_map.find( name ) ;
92 return p == m_map.end() ?
false : ( (*p).second.value_multiplicity > 0U ) ;
97 return valid(name) && !valued(name) ;
102 return multivalued( lookup(c) ) ;
107 Map::const_iterator p = m_map.find( name ) ;
108 return p == m_map.end() ?
false : ( (*p).second.value_multiplicity > 1U ) ;
113 Map::const_iterator p = m_map.find( name ) ;
114 if( p == m_map.end() )
return false ;
117 ( !(*p).second.hidden && (*p).second.level == level.level ) :
118 ( !(*p).second.hidden && (*p).second.level <= level.level ) ;
123 return m_map.find(name) != m_map.end() ;
128 for( Map::const_iterator p = m_map.begin() ; c !=
'\0' && p != m_map.end() ; ++p )
130 if( (*p).second.c == c )
131 return (*p).second.name ;
133 return std::string() ;
145 unsigned int result = 79U ;
154 size_t G::Options::widthFloor(
size_t w )
156 return (w != 0U && w < 50U) ? 50U : w ;
174 std::string G::Options::usageSummaryPartOne( Level level )
const
177 std::ostringstream ss ;
179 for( StringArray::const_iterator name_p = m_names.begin() ; name_p != m_names.end() ; ++name_p )
181 Map::const_iterator spec_p = m_map.find( *name_p ) ;
182 if( (*spec_p).second.c !=
'\0' && !valued(*name_p) && visible(*name_p,level,
false) )
187 ss << (*spec_p).second.c ;
191 std::string s = ss.str() ;
192 if( s.length() ) s.append(
"] " ) ;
196 std::string G::Options::usageSummaryPartTwo( Level level )
const
198 std::ostringstream ss ;
199 const char * sep =
"" ;
200 for( StringArray::const_iterator name_p = m_names.begin() ; name_p != m_names.end() ; ++name_p )
202 if( visible(*name_p,level,
false) )
204 Map::const_iterator spec_p = m_map.find( *name_p ) ;
206 if( (*spec_p).second.name.length() )
208 ss <<
"--" << (*spec_p).second.name ;
212 G_ASSERT( (*spec_p).second.c !=
'\0' ) ;
213 ss <<
"-" << (*spec_p).second.c ;
215 if( (*spec_p).second.value_multiplicity > 0U )
217 std::string vd = (*spec_p).second.value_description ;
218 if( vd.empty() ) vd =
"value" ;
219 ss <<
"=<" << vd <<
">" ;
231 return usageHelpCore(
" " , level , layout , exact , extra ) ;
234 std::string G::Options::usageHelpCore(
const std::string & prefix , Level level ,
235 Layout layout ,
bool exact ,
bool extra )
const
238 for( StringArray::const_iterator name_p = m_names.begin() ; name_p != m_names.end() ; ++name_p )
240 if( visible(*name_p,level,exact) )
242 Map::const_iterator spec_p = m_map.find( *name_p ) ;
243 std::string line( prefix ) ;
244 if( (*spec_p).second.c !=
'\0' )
247 line.append( 1U , (*spec_p).second.c ) ;
248 if( (*spec_p).second.name.length() )
249 line.append(
", " ) ;
251 if( (*spec_p).second.name.length() )
253 line.append(
"--" ) ;
254 line.append( (*spec_p).second.name ) ;
257 if( (*spec_p).second.value_multiplicity > 0U )
259 std::string vd = (*spec_p).second.value_description ;
260 if( vd.empty() ) vd =
"value" ;
261 line.append(
"=<" ) ;
265 line.append( 1U ,
' ' ) ;
267 if( !layout.separator.empty() )
268 line.append( layout.separator ) ;
269 else if( line.length() < layout.column )
270 line.append( layout.column-line.length() ,
' ' ) ;
272 line.append( (*spec_p).second.description ) ;
274 line.append( (*spec_p).second.description_extra ) ;
278 std::string indent = layout.indent.empty() ? std::string(layout.column,
' ') : layout.indent ;
279 line =
G::Str::wrap( line ,
"" , indent , layout.width ) ;
283 line.append( 1U ,
'\n' ) ;
286 result.append( line ) ;
293 const std::string & introducer ,
Level level ,
Layout layout ,
bool extra )
const
296 << usageSummary(exe,args,introducer,level,layout.
width) << std::endl
297 << usageHelp(level,layout,
false,extra) ;
301 const std::string & introducer ,
Level level ,
size_t width )
const
303 std::string s = introducer + exe +
" " + usageSummaryPartOne(level) + usageSummaryPartTwo(level) + (args.empty()||args.at(0U)==
' '?
"":
" ") + args ;
304 std::string indent( 2U ,
' ' ) ;
305 return width == 0U ? s :
G::Str::wrap( s ,
"" , indent , widthFloor(width) ) ;
310 G::Options::Option::Option(
char c_ ,
const std::string & name_ ,
const std::string & description_ ,
311 const std::string & description_extra_ ,
unsigned int value_multiplicity_ ,
312 const std::string & vd_ ,
unsigned int level_ ) :
315 description(description_) ,
316 description_extra(description_extra_) ,
317 value_multiplicity(value_multiplicity_) ,
318 hidden(description_.empty()||level_==0U) ,
319 value_description(vd_) ,
static std::string get(const std::string &name, const std::string &default_)
Returns the environment variable value or the given default.
bool valid(const std::string &) const
Returns true if the long-form option name is valid.
bool unvalued(const std::string &option_name) const
Returns true if the given option name is valid and takes no value.
static Level levelDefault()
Returns the default level.
static std::string wrap(std::string text, const std::string &prefix_first_line, const std::string &prefix_subsequent_lines, size_type width=70U)
Does word-wrapping.
Describes the layout for G::Options output.
bool multivalued(char) const
Returns true if the short-form option can have multiple values.
std::vector< std::string > StringArray
A std::vector of std::strings.
static size_t widthDefault()
Returns a default, non-zero word-wrapping width, reflecting the size of the standard output where pos...
Used by G::Options for extra type safety.
std::string usageHelp(Level level=levelDefault(), Layout layout=layoutDefault(), bool level_exact=false, bool extra=true) const
Returns a multi-line string giving help on each option.
std::string lookup(char c) const
Converts from short-form option character to the corresponding long-form name.
static unsigned int toUInt(const std::string &s)
Converts string 's' to an unsigned int.
static std::string introducerDefault()
Returns the string "usage: ".
std::string usageSummary(const std::string &exe, const std::string &args, const std::string &introducer=introducerDefault(), Level level=levelDefault(), size_t wrap_width=widthDefault()) const
Returns a one-line (or line-wrapped) usage summary, as "usage: <exe> <options> <args>".
static Layout layoutDefault()
Returns a default column layout.
size_t width
overall width for wrapping, or zero for no newlines
bool valued(char) const
Returns true if the short-form option character is valid.
bool visible(const std::string &name, Level, bool exact) const
Returns true if the option is visible at the given level.
const StringArray & names() const
Returns the sorted list of long-form option names.
Options()
Default constructor for no options.
void showUsage(std::ostream &stream, const std::string &exe, const std::string &args=std::string(), const std::string &introducer=introducerDefault(), Level level=levelDefault(), Layout layout=layoutDefault(), bool extra=true) const
Streams out multi-line usage text using usageSummary() and usageHelp().
static void splitIntoFields(const std::string &in, StringArray &out, const std::string &seperators, char escape= '\0', bool remove_escapes=true)
Splits the string into fields.