11 #include "LibCyberRadio/Common/App.h" 12 #include "LibCyberRadio/Common/Pythonesque.h" 45 int valueType,
void *valuePtr,
46 const std::string& helpArgName,
const std::string& helpText,
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);
681 int App::parseCommandLine(
int argc,
char* argv[])
683 return _optParser.
parse(argc, argv);
void allowUnknownOption(bool allow=true)
Determines whether or not the parser will allow unknown options to pass through the parser without ge...
static int TYPE_NONE
Option does not set a value.
virtual AppOption & operator=(const AppOption &opt)
Makes one AppOption object equivalent to another.
std::string shortName
Short option name, without leading hyphen.
virtual void addPreOptionText(const std::string &text)
Adds text that gets displayed before the list of options.
virtual void defineOptions(const char *argv0)
Defines which command-line options are supported by the application, as well as any help text that is...
static int TYPE_BOOLEAN
Option explicitly sets a boolean value.
virtual ~AppHelpTextFormatter()
Destroys an AppHelpTextFormatter object.
void setExecutable(const std::string &executable)
Sets the portion of the usage information where the executable name is displayed. ...
void setVersion(const std::string &version)
Sets the portion of the usage information that represents the application version.
virtual int mainLoop()
Defines the application's main processing loop.
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 setDescription(const std::string &description)
Sets the portion of the usage information where the application description is displayed.
virtual ~AppOptionParser()
Destroys an AppOptionParser object.
void setDisplayWidth(int displayWidth=75)
Sets the display width of the usage information.
AppOptionParser()
Constructs an AppOptionParser 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.
std::string version
The application version.
BASIC_LIST_CONTAINER< std::string > BasicStringList
Type representing a list of strings.
static int TYPE_INTEGER
Option sets an integer value.
App()
Constructs an App object.
Defines functionality for LibCyberRadio applications.
BasicStringList unparsedArgs
The collection of arguments that were not dealt with by the parser during option parsing.
void * valuePtr
Pointer to a variable that holds the option value.
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 setUnparsedArgText(const std::string &unparsedArgText)
Sets the portion of the usage information that represents the collection of unparsed arguments...
virtual std::string getFormattedText()
Gets the formatted help text.
virtual int run(int argc, char *argv[])
Runs the application.
virtual void addPostOptionText(const std::string &text)
Adds text that gets displayed after the list of options.
virtual void addOption(const AppOption &opt)
Adds an allowed option to the parser.
static int TYPE_DOUBLE
Option sets a double-precision floating-point value.
static int TYPE_FLOAT
Option sets a floating-point value.
AppOption()
Constructs an empty AppOption object.
bool showDefault
Show the default value in the option help text.
std::string description
The application description.
std::string helpText
Option help text.
AppHelpTextFormatter(int displayWidth=75)
Constructs an AppHelpTextFormatter object.
std::string longName
Long option name, without leading hyphens.
static int TYPE_STRING
Option sets a string value.
virtual int parse(int argc, char **argv)
Parses the command-line 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 ~AppOption()
Destroys an AppOption object.
static int TYPE_BOOLEAN_SET_FALSE
Option sets a boolean value that is True by default but becomes False if this option is specified...
Defines a command-line option that is supported by an application.
int valueType
Type of value that this option sets.
std::string helpArgName
Option argument name to display in the help text.