36 bool eqc(
char c , std::pair<std::string,G::GetOpt::SwitchSpec> p )
38 return p.second.c == c ;
40 bool eqn( std::string n , std::pair<std::string,G::GetOpt::SwitchSpec> p )
42 return p.second.name == n ;
47 char sep_major ,
char sep_minor ,
char escape ) :
50 parseSpec( spec , sep_major , sep_minor , escape ) ;
55 void G::GetOpt::parseSpec(
const std::string & spec ,
char sep_major ,
char sep_minor ,
char escape )
58 std::string ws_major( 1U , sep_major ) ;
61 for( Strings::iterator p = outer.begin() ; p != outer.end() ; ++p )
63 if( (*p).empty() )
continue ;
65 std::string ws_minor( 1U , sep_minor ) ;
67 if( inner.size() != 7U )
69 std::ostringstream ss ;
70 ss <<
"\"" << *p <<
"\" (" << ws_minor <<
")" ;
71 throw InvalidSpecification( ss.str() ) ;
75 addSpec( inner[1U] , inner[0U].at(0U) , inner[1U] , inner[2U] , inner[3U] , is_valued , inner[5U] , level ) ;
79 void G::GetOpt::addSpec(
const std::string & sort_key ,
char c ,
const std::string & name ,
80 const std::string & description ,
const std::string & description_extra ,
81 bool is_valued ,
const std::string & value_description ,
unsigned int level )
84 throw InvalidSpecification() ;
86 std::pair<SwitchSpecMap::iterator,bool> rc =
87 m_spec_map.insert( std::make_pair( sort_key ,
88 SwitchSpec(c,name,description,description_extra,is_valued,value_description,level) ) ) ;
91 throw InvalidSpecification(
"duplication") ;
94 bool G::GetOpt::valued(
const std::string & name )
const
96 return valued(key(name)) ;
99 bool G::GetOpt::valued(
char c )
const
101 SwitchSpecMap::const_iterator p =
102 std::find_if( m_spec_map.begin() , m_spec_map.end() , std::bind1st(std::ptr_fun(eqc),c)) ;
103 return p == m_spec_map.end() ?
false : (*p).second.valued ;
106 char G::GetOpt::key(
const std::string & name )
const
108 SwitchSpecMap::const_iterator p =
109 std::find_if( m_spec_map.begin() , m_spec_map.end() , std::bind1st(std::ptr_fun(eqn),name)) ;
110 return p == m_spec_map.end() ?
'\0' : (*p).second.c ;
115 unsigned int result = 79U ;
141 return (w != 0U && w < 50U) ? 50U : w ;
146 showUsage( stream , m_args.prefix() , args , introducerDefault() ,
147 verbose ? levelDefault() :
Level(1U) , tabDefault() , wrapDefault() , verbose ) ;
154 << usageSummary(exe,args,introducer,level,width) << std::endl
155 << usageHelp(level,tab_stop,width,
false,extra) ;
159 const std::string & introducer ,
Level level ,
size_type width )
const
161 std::string s = introducer + exe +
" " + usageSummarySwitches(level) + args ;
164 return G::Str::wrap( s ,
"" ,
" " , widthLimit(width) ) ;
174 return usageSummaryPartOne(level) + usageSummaryPartTwo(level) ;
177 bool G::GetOpt::visible( SwitchSpecMap::const_iterator p , Level level ,
bool exact )
181 ( !(*p).second.hidden && (*p).second.level == level.level ) :
182 ( !(*p).second.hidden && (*p).second.level <= level.level ) ;
185 std::string G::GetOpt::usageSummaryPartOne( Level level )
const
188 std::ostringstream ss ;
190 for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
192 if( !(*p).second.valued && visible(p,level,
false) )
197 ss << (*p).second.c ;
201 std::string s = ss.str() ;
202 if( s.length() ) s.append(
"] " ) ;
206 std::string G::GetOpt::usageSummaryPartTwo( Level level )
const
208 std::ostringstream ss ;
209 const char * sep =
"" ;
210 for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
212 if( visible(p,level,
false) )
215 if( (*p).second.name.length() )
217 ss <<
"--" << (*p).second.name ;
221 ss <<
"-" << (*p).second.c ;
223 if( (*p).second.valued )
225 std::string vd = (*p).second.value_description ;
226 if( vd.empty() ) vd =
"value" ;
227 ss <<
"=<" << vd <<
">" ;
237 bool exact ,
bool extra )
const
239 return usageHelpCore(
" " , level , tab_stop , widthLimit(width) , exact , extra ) ;
242 std::string G::GetOpt::usageHelpCore(
const std::string & prefix , Level level ,
246 for( SwitchSpecMap::const_iterator p = m_spec_map.begin() ; p != m_spec_map.end() ; ++p )
248 if( visible(p,level,exact) )
250 std::string line( prefix ) ;
252 line.append( 1U , (*p).second.c ) ;
254 if( (*p).second.name.length() )
256 line.append(
", --" ) ;
257 line.append( (*p).second.name ) ;
260 if( (*p).second.valued )
262 std::string vd = (*p).second.value_description ;
263 if( vd.empty() ) vd =
"value" ;
264 line.append(
"=<" ) ;
268 line.append( 1U ,
' ' ) ;
270 if( line.length() < tab_stop )
271 line.append( tab_stop-line.length() ,
' ' ) ;
273 line.append( (*p).second.description ) ;
275 line.append( (*p).second.description_extra ) ;
279 std::string indent( tab_stop ,
' ' ) ;
284 line.append( 1U ,
'\n' ) ;
287 result.append( line ) ;
296 for( ; i < args_in.c() ; i++ )
298 const std::string & arg = args_in.v(i) ;
306 if( isSwitchSet(arg) )
308 for(
size_type n = 1U ; n < arg.length() ; n++ )
309 processSwitch( arg.at(n) ) ;
311 else if( isOldSwitch(arg) )
313 char c = arg.at(1U) ;
314 if( valued(c) && (i+1U) >= args_in.c() )
317 processSwitch( c , args_in.v(++i) ) ;
321 else if( isNewSwitch(arg) )
323 std::string name = arg.substr( 2U ) ;
325 bool has_eq = pos_eq != std::string::npos ;
326 std::string eq_value = eqValue(name,pos_eq) ;
327 if( has_eq ) name = name.substr(0U,pos_eq) ;
329 if( valued(name) && !has_eq && (i+1U) >= args_in.c() )
330 errorNoValue( name ) ;
331 else if( valued(name) && !has_eq )
332 processSwitch( name , args_in.v(++i) ) ;
333 else if( valued(name) )
334 processSwitch( name , eq_value ) ;
336 processSwitch( name ) ;
349 size_type p = s.find_first_not_of(
"abcdefghijklmnopqrstuvwxyz0123456789-_") ;
350 return p != std::string::npos && s.at(p) ==
'=' ? p : std::string::npos ;
353 std::string G::GetOpt::eqValue(
const std::string & s ,
size_type pos )
355 return (pos+1U) == s.length() ? std::string() : s.substr(pos+1U) ;
358 bool G::GetOpt::isOldSwitch(
const std::string & arg )
const
361 ( arg.length() > 1U && arg.at(0U) ==
'-' ) &&
362 ! isNewSwitch( arg ) ;
365 bool G::GetOpt::isNewSwitch(
const std::string & arg )
const
367 return arg.length() > 2U && arg.at(0U) ==
'-' && arg.at(1U) ==
'-' ;
370 bool G::GetOpt::isSwitchSet(
const std::string & arg )
const
372 return isOldSwitch(arg) && arg.length() > 2U ;
375 void G::GetOpt::errorNoValue(
char c )
377 std::string e(
"no value supplied for -") ;
379 m_errors.push_back( e ) ;
382 void G::GetOpt::errorNoValue(
const std::string & name )
384 std::string e(
"no value supplied for --") ;
386 m_errors.push_back( e ) ;
389 void G::GetOpt::errorUnknownSwitch(
char c )
391 std::string e(
"invalid option: -") ;
393 m_errors.push_back( e ) ;
396 void G::GetOpt::errorUnknownSwitch(
const std::string & name )
398 std::string e(
"invalid option: --") ;
400 m_errors.push_back( e ) ;
403 void G::GetOpt::processSwitch(
const std::string & name )
407 errorUnknownSwitch( name ) ;
414 errorNoValue( name ) ;
418 m_map.insert( std::make_pair(c,std::make_pair(
false,std::string())) ) ;
421 void G::GetOpt::processSwitch(
const std::string & name ,
const std::string & value )
425 errorUnknownSwitch( name ) ;
430 m_map.insert( std::make_pair(c,std::make_pair(
true,value)) ) ;
433 void G::GetOpt::processSwitch(
char c )
437 errorUnknownSwitch( c ) ;
447 m_map.insert( std::make_pair(c,std::make_pair(
false,std::string())) ) ;
450 void G::GetOpt::processSwitch(
char c ,
const std::string & value )
453 errorUnknownSwitch( c ) ;
455 m_map.insert( std::make_pair(c,std::make_pair(
true,value)) ) ;
465 SwitchMap::const_iterator p = m_map.find( c ) ;
466 return p != m_map.end() ;
472 SwitchMap::const_iterator p = m_map.find( c ) ;
473 return p != m_map.end() ;
479 SwitchMap::const_iterator p = m_map.find( c ) ;
480 Value value_pair = (*p).second ;
481 return value_pair.second ;
487 return value( key(name) ) ;
497 for( SwitchMap::const_iterator p = m_map.begin() ; p != m_map.end() ; ++p )
499 char c = (*p).first ;
500 Value v = (*p).second ;
501 bool valued = v.first ;
502 std::string value = v.second ;
504 SwitchSpecMap::const_iterator q = std::find_if( m_spec_map.begin() , m_spec_map.end() ,
505 std::bind1st(std::ptr_fun(eqc),c)) ;
506 std::string name = q == m_spec_map.end() ? std::string() : (*q).second.name ;
508 stream << prefix <<
"-" << c ;
510 stream <<
",--" << name ;
512 stream <<
" = \"" << value <<
"\"" ;
513 stream << std::endl ;
519 return m_errors.size() != 0U ;
524 showErrors( stream , m_args.prefix() ) ;
529 for( Strings::const_iterator p = m_errors.begin() ; p != m_errors.end() ; ++p )
531 stream << prefix_1 << prefix_2 << *p << std::endl ;
539 m_args.removeAt(1U,n-1U) ;
543 bool G::GetOpt::valid(
const std::string & name )
const
545 return valid( key(name) ) ;
548 bool G::GetOpt::valid(
char c )
const
550 return !! std::count_if( m_spec_map.begin() , m_spec_map.end() , std::bind1st(std::ptr_fun(eqc),c)) ;
bool contains(char switch_letter) const
Returns true if the command line contains the given switch.
static std::string get(const std::string &name, const std::string &default_)
Returns the environment variable value or the given default.
void showErrors(std::ostream &stream, std::string prefix_1, std::string prefix_2=std::string(": ")) const
A convenience function which streams out each errorList() item to the given stream, prefixed with the given prefix(es).
Strings errorList() const
Returns the list of errors.
static unsigned int toUInt(const std::string &s, bool limited=false)
Converts string 's' to an unsigned int.
std::list< std::string > Strings
A std::list of std::strings.
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.
static void splitIntoFields(const std::string &in, Strings &out, const std::string &seperators, char escape= '\0', bool discard_bogus_escapes=true)
Splits the string into fields.
bool hasErrors() const
Returns true if there are errors.
std::vector< std::string > StringArray
A std::vector of std::strings.
std::string::size_type size_type
A std::size_t type.
void show(std::ostream &stream, std::string prefix) const
For debugging.
std::string value(const std::string &switch_name) const
Returns the value related to the given value-based switch.
GetOpt(const Arg &arg, const std::string &spec, char sep_major= '|', char sep_minor= '/', char escape= '\\')
Constructor taking a Arg reference and a specification string.
static size_type tabDefault()
Returns a default tab-stop.
Arg args() const
Returns all the non-switch command-line arguments.
std::string usageHelp(Level level=levelDefault(), size_type tab_stop=tabDefault(), size_type wrap_width=wrapDefault(), bool level_exact=false, bool extra=true) const
Returns a multi-line string giving help on each switch.
static size_type wrapDefault()
Returns a default word-wrapping width.
static Level levelDefault()
Returns the default level.
A class which holds a represention of the argc/argv command line array, and supports simple command-l...
std::string::size_type size_type
std::string usageSummary(const std::string &exe, const std::string &args, const std::string &introducer=introducerDefault(), Level level=levelDefault(), size_type wrap_width=wrapDefault()) const
Returns a one-line usage summary, as "usage:
".
static std::string introducerDefault()
Returns "usage: ".
Used by G::GetOpt for extra type safety.
std::string usageSummarySwitches(Level level=levelDefault()) const
Returns the one-line summary of switches.
void showUsage(std::ostream &stream, const std::string &exe, const std::string &args, const std::string &introducer=introducerDefault(), Level level=levelDefault(), size_type tab_stop=tabDefault(), size_type wrap_width=wrapDefault(), bool extra=true) const
Streams out multi-line usage text using usageSummary() and usageHelp().