11#include "LibCyberRadio/Common/App.h"
12#include "LibCyberRadio/Common/Pythonesque.h"
97 _displayWidth = displayWidth;
107 _preOptionText.push_back(text);
111 const std::string& text)
115 _options.push_back(option);
116 _optionText.push_back(text);
117 if ( (
int)option.length() > _maxOptionWidth )
118 _maxOptionWidth = option.length();
125 _postOptionText.push_back(text);
130 std::ostringstream oss, ossTmp;
132 for (BasicStringListIterator it = _preOptionText.begin(); it != _preOptionText.end();
135 oss << wordWrappedText(*it, _displayWidth, 0);
138 for (BasicStringListIterator ito = _options.begin(), itt = _optionText.begin();
139 ito != _options.end();
144 ossTmp << std::left << std::setw(_maxOptionWidth) << *ito
145 << std::setw(0) <<
" "
146 << std::setw(0) << *itt;
147 oss << wordWrappedText(ossTmp.str(), _displayWidth, _maxOptionWidth + 2);
150 for (BasicStringListIterator it = _postOptionText.begin(); it != _postOptionText.end();
153 oss << wordWrappedText(*it, _displayWidth, 0);
158 std::string AppHelpTextFormatter::wordWrappedText(
const std::string& text,
int width,
162 std::string hangingIndentText(hangingIndent,
' ');
164 for (BasicStringListIterator itl = textLines.begin(); itl != textLines.end(); itl++)
166 if ( itl == textLines.begin() )
168 std::string::size_type curPos = 0;
171 for (BasicStringListIterator itw = words.begin(); itw != words.end(); itw++)
174 if ( curPos + 1 + itw->length() > (std::string::size_type)width )
181 ret.append(hangingIndentText);
182 curPos = hangingIndentText.length();
186 curPos += itw->length();
194 curPos += itw->length() + 1;
201 ret.append( wordWrappedText(*itl, width, hangingIndent) );
204 if ( textLines.size() == 0 )
216 _allowUnknownOption =
false;
221 "Print this help text",
false);
224 "Print version information and exit",
false);
249 _optionList.push_back( opt );
253 const std::string& longName,
254 int valueType,
void *valuePtr,
255 const std::string& helpArgName,
const std::string& helpText,
259 helpArgName, helpText, showDefault) );
264 _allowUnknownOption = allow;
269 _description = description;
274 _displayWidth = displayWidth;
279 _epilogText = epilogText;
284 _executable = executable;
289 _unparsedArgText = unparsedArgText;
302 struct option longOptions[_optionList.size() + 1];
303 for (
int i = 0; i < (int)_optionList.size(); i++)
307 if ( _optionList[i].shortName.length() == 1 )
309 shargs.append(_optionList[i].shortName);
310 if ( optionValueArg(_optionList[i].valueType) )
312 longOptions[i].val = (int)_optionList[i].shortName[0];
317 longOptions[i].val = 32768+i;
319 longOptions[i].name = _optionList[i].longName.c_str();
320 longOptions[i].has_arg = optionValueArg(_optionList[i].valueType);
321 longOptions[i].flag = (
int*)0;
324 longOptions[_optionList.size()].name = (
char*)0;
325 longOptions[_optionList.size()].has_arg = 0;
326 longOptions[_optionList.size()].flag = (
int*)0;
327 longOptions[_optionList.size()].val = 0;
329 std::cerr <<
"[DBG] Short option list: " << shargs << std::endl;
337 opt = getopt_long( argc, argv,
339 (
const struct option *)longOptions,
344 std::cerr <<
"Option parsed: " << opt <<
" (" << (char)opt <<
")" << std::endl;
351 if ( !_allowUnknownOption )
356 ret = handleOptionReturn(opt, optarg ? optarg :
"");
358 std::cerr <<
"ERROR: Improperly formatted argument!" << std::endl;
365 if ( (ret == 0) && (optind < argc) )
367 while (optind < argc)
374 int AppOptionParser::handleOptionReturn(
int opt,
const std::string& optarg)
379 int our_optindex = -1;
385 for (
int i = 0; i < (int)_optionList.size(); i++)
387 if ( (_optionList[i].shortName.length() == 1) &&
388 (_optionList[i].shortName[0] == (
char)opt) )
399 our_optindex = opt - 32768;
402 if ( our_optindex != -1 )
404 if ( _optionList[our_optindex].longName ==
"version" )
406 std::cerr << _description <<
", Version " << _version << std::endl;
409 else if ( _optionList[our_optindex].longName ==
"help" )
414 else if ( _optionHelpers.count(_optionList[our_optindex].valueType) > 0 )
416 ret = (this->*_optionHelpers[_optionList[our_optindex].valueType])(our_optindex, optarg);
426 void AppOptionParser::printUsage()
428 std::ostringstream ossPre, ossPost;
429 AppHelpTextFormatter fmtr(_displayWidth);
430 ossPre << _description <<
", Version " << _version <<
"\n\n" <<
"Usage:\n" << _executable;
431 if ( _optionList.size() > 0 )
432 ossPre <<
" [options]";
433 if ( _unparsedArgText.length() > 0 )
434 ossPre <<
" " << _unparsedArgText;
436 if ( _optionList.size() > 0 )
438 ossPre <<
"Options:\n\n";
439 std::string opt, optText;
440 for (
int i = 0; i < (int)_optionList.size(); i++)
443 if ( _optionList[i].shortName.length() == 1 )
446 opt.append(_optionList[i].shortName);
447 if ( optionValueArg(_optionList[i].valueType) > no_argument )
450 opt.append(_optionList[i].helpArgName);
453 if ( _optionList[i].longName.length() > 0 )
458 opt.append(_optionList[i].longName);
459 if ( optionValueArg(_optionList[i].valueType) > no_argument )
462 opt.append(_optionList[i].helpArgName);
469 optText = _optionList[i].helpText;
470 optText.append( getDefault(_optionList[i]) );
471 fmtr.addOptionText(opt, optText);
474 if ( _epilogText.length() > 0 )
475 ossPost <<
"\n" << _epilogText <<
"\n";
476 fmtr.addPreOptionText(ossPre.str());
477 fmtr.addPostOptionText(ossPost.str());
479 std::cerr << fmtr.getFormattedText() << std::endl;
482 int AppOptionParser::optionValueArg(
int valueType)
484 int ret = no_argument;
487 ret = required_argument;
491 std::string AppOptionParser::getDefault(
const AppOption& opt)
493 std::ostringstream oss;
499 if ( opt.showDefault && (opt.valuePtr != (
void*)0) )
504 iptr = (
int *)opt.valuePtr;
509 fptr = (
float *)opt.valuePtr;
514 dptr = (
double *)opt.valuePtr;
519 sptr = (std::string *)opt.valuePtr;
525 bptr = (
bool *)opt.valuePtr;
526 oss << (*bptr ?
"True" :
"False") <<
".";
536 int AppOptionParser::handleOptionNone(
int optindex,
const std::string& optarg)
541 int AppOptionParser::handleOptionInt(
int optindex,
const std::string& optarg)
544 if ( _optionList[optindex].valuePtr != (
void*)0 )
547 int *vptr = (
int *)_optionList[optindex].valuePtr;
548 int tmp = (int)strtol(optarg.c_str(), &endptr, 10);
549 if ( *endptr ==
'\0' )
557 int AppOptionParser::handleOptionFloat(
int optindex,
const std::string& optarg)
560 if ( _optionList[optindex].valuePtr != (
void*)0 )
563 float *vptr = (
float *)_optionList[optindex].valuePtr;
564 float tmp = (float)strtod(optarg.c_str(), &endptr);
565 if ( *endptr ==
'\0' )
573 int AppOptionParser::handleOptionDouble(
int optindex,
const std::string& optarg)
576 if ( _optionList[optindex].valuePtr != (
void*)0 )
579 double *vptr = (
double *)_optionList[optindex].valuePtr;
580 double tmp = strtod(optarg.c_str(), &endptr);
581 if ( *endptr ==
'\0' )
589 int AppOptionParser::handleOptionString(
int optindex,
const std::string& optarg)
592 if ( _optionList[optindex].valuePtr != (
void*)0 )
594 std::string *vptr = (std::string *)_optionList[optindex].valuePtr;
600 int AppOptionParser::handleOptionBool(
int optindex,
const std::string& optarg)
603 if ( _optionList[optindex].valuePtr != (
void*)0 )
605 std::string val = optarg;
606 bool *vptr = (
bool *)_optionList[optindex].valuePtr;
607 std::transform(val.begin(), val.end(), val.begin(), ::tolower);
608 if ( (val ==
"true") || (val ==
"yes") || (val ==
"on") || (val ==
"1") )
610 else if ( (val ==
"false") || (val ==
"no") || (val ==
"off") || (val ==
"0") )
618 int AppOptionParser::handleOptionBooleanSetTrue(
int optindex,
const std::string& optarg)
621 if ( _optionList[optindex].valuePtr != (
void*)0 )
623 bool *vptr = (
bool *)_optionList[optindex].valuePtr;
629 int AppOptionParser::handleOptionBooleanSetFalse(
int optindex,
const std::string& optarg)
632 if ( _optionList[optindex].valuePtr != (
void*)0 )
634 bool *vptr = (
bool *)_optionList[optindex].valuePtr;
655 int ret = parseCommandLine(argc, argv);
665 _optParser.setVersion(
version);
666 _optParser.setExecutable(argv0);
667 _optParser.setUnparsedArgText(
"");
668 _optParser.setEpilogText(
"");
681 int App::parseCommandLine(
int argc,
char* argv[])
683 return _optParser.
parse(argc, argv);
virtual void addPostOptionText(const std::string &text)
Adds text that gets displayed after the list of options.
AppHelpTextFormatter(int displayWidth=75)
Constructs an AppHelpTextFormatter object.
virtual ~AppHelpTextFormatter()
Destroys an AppHelpTextFormatter object.
virtual void addPreOptionText(const std::string &text)
Adds text that gets displayed before the list of options.
virtual void addOptionText(const std::string &option, const std::string &text)
Adds an option and its help text to the list of options.
virtual std::string getFormattedText()
Gets the formatted help text.
void setEpilogText(const std::string &epilogText)
Sets the epilog portion of the usage information; that is, the part that comes after the list of supp...
void allowUnknownOption(bool allow=true)
Determines whether or not the parser will allow unknown options to pass through the parser without ge...
void setExecutable(const std::string &executable)
Sets the portion of the usage information where the executable name is displayed.
void setDescription(const std::string &description)
Sets the portion of the usage information where the application description is displayed.
virtual void addOption(const AppOption &opt)
Adds an allowed option to the parser.
AppOptionParser()
Constructs an AppOptionParser object.
virtual ~AppOptionParser()
Destroys an AppOptionParser object.
BasicStringList unparsedArgs
The collection of arguments that were not dealt with by the parser during option parsing.
void setDisplayWidth(int displayWidth=75)
Sets the display width of the usage information.
void setUnparsedArgText(const std::string &unparsedArgText)
Sets the portion of the usage information that represents the collection of unparsed arguments.
void setVersion(const std::string &version)
Sets the portion of the usage information that represents the application version.
virtual int parse(int argc, char **argv)
Parses the command-line options.
Defines a command-line option that is supported by an application.
std::string shortName
Short option name, without leading hyphen.
bool showDefault
Show the default value in the option help text.
static int TYPE_NONE
Option does not set a value.
static int TYPE_DOUBLE
Option sets a double-precision floating-point value.
std::string longName
Long option name, without leading hyphens.
virtual ~AppOption()
Destroys an AppOption object.
static int TYPE_INTEGER
Option sets an integer value.
static int TYPE_BOOLEAN_SET_TRUE
Option sets a boolean value that is False by default but becomes True if this option is specified.
void * valuePtr
Pointer to a variable that holds the option value.
int valueType
Type of value that this option sets.
virtual AppOption & operator=(const AppOption &opt)
Makes one AppOption object equivalent to another.
static int TYPE_BOOLEAN_SET_FALSE
Option sets a boolean value that is True by default but becomes False if this option is specified.
static int TYPE_BOOLEAN
Option explicitly sets a boolean value.
AppOption()
Constructs an empty AppOption object.
static int TYPE_FLOAT
Option sets a floating-point value.
static int TYPE_STRING
Option sets a string value.
std::string helpArgName
Option argument name to display in the help text.
std::string helpText
Option help text.
std::string description
The application description.
virtual int mainLoop()
Defines the application's main processing loop.
virtual int run(int argc, char *argv[])
Runs the application.
std::string version
The application version.
virtual void defineOptions(const char *argv0)
Defines which command-line options are supported by the application, as well as any help text that is...
App()
Constructs an App object.
static BasicStringList Split(const std::string &str, const std::string &sep, int maxsplit=INT_MAX)
Splits the given string into a list of string tokens.
Defines functionality for LibCyberRadio applications.
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.