28 const std::string &desc,
29 const std::string &defaultValue)
34 _defaultValue(defaultValue),
41 const std::string &desc,
42 const std::string &defaultValue)
47 _defaultValue(defaultValue),
50 for (
const auto &name : names) {
61 bool haveName =
false;
62 for (
size_t i = 0; i < _names.size(); i++) {
63 if (_names.at(i) == name) {
69 _names.push_back(name);
82 for (
const auto &
n : _names) {
114 _defaultValue = value;
119 return _defaultValue;
124 _values.push_back(value);
129 if (index > _values.size() || _values.empty()) {
132 return _values.at(index);
156 : _flags(flags), _name(), _commandName(), _desc(), _descExtra(), _usageText(), _helpText(),
157 _options(), _subParsers()
163 : _flags(flags), _name(name), _commandName(), _desc(), _descExtra(), _usageText(), _helpText(),
164 _options(), _subParsers()
180 _flags = other._flags;
182 _commandName = other._commandName;
184 _descExtra = other._descExtra;
185 _usageText = other._usageText;
186 _helpText = other._helpText;
187 _options = other._options;
189 for (
SubParserMapConstIter iter = other._subParsers.begin(); iter != other._subParsers.end(); ++iter) {
194 void AJACommandLineParser::init()
215 for (
auto &sp : _subParsers) {
220 for (
auto &opt : _options) {
228 if (!_commandName.empty()) {
235 iter != _options.end(); ++iter) {
238 std::ostringstream oss;
245 if (++count < names.size()) {
249 oss <<
"] " <<
"set? " << (
IsSet(name) ?
"true" :
"false") <<
" value = " << o.
Value();
250 std::cout << oss.str() << std::endl;
257 for (
const auto &opt : _options) {
258 for (
const auto &
n : opt.Names()) {
269 for (
const auto &arg : _positionalArgs) {
279 return _positionalArgs;
284 for (
const auto &o : _options) {
285 for (
const auto &
n : o.Names()) {
297 const std::string &name = p->
Name();
298 if (_subParsers.find(name) == _subParsers.end()) {
308 AJAStringList::const_iterator iter = args.begin();
311 for (SubParserMap::iterator spIter = _subParsers.begin(); spIter != _subParsers.end(); ++spIter) {
313 if (*iter == spIter->first) {
314 _commandName = *iter;
317 if (spIter->second !=
NULL) {
318 if (!spIter->second->Parse(args)) {
319 std::cerr <<
"Error parsing args with sub-parser: " << spIter->second->Name() << std::endl;
330 if (!_name.empty() && *iter != _name) {
335 bool havePositionalArgs =
false;
336 for (; iter != args.end(); iter++) {
337 const std::string &arg = *iter;
340 havePositionalArgs =
true;
344 if (havePositionalArgs) {
345 _positionalArgs.push_back(arg);
349 if (hasOptionPrefix(arg)) {
352 std::string optValue;
357 argStr = arg.substr(2, arg.length());
358 }
else if (singleDash) {
359 argStr = arg.substr(1, arg.length());
361 if (hasAssignmentOperator(argStr)) {
362 size_t assignPos = argStr.find_first_of(
kAssignChar);
363 optName = argStr.substr(0, assignPos);
364 optValue = argStr.substr(assignPos+1, argStr.length());
378 for (
size_t c = 1; c < arg.length(); c++) {
379 subStr = arg.substr(c, 1);
381 setOption(subStr,
true);
385 for (
size_t c = arg.length(); c > 1; c--) {
386 subStr = arg.substr(1, c-1);
389 size_t count = (arg.length()-1)-optName.length();
390 optValue = arg.substr(optName.length()+1, count);
393 std::cerr <<
"Unknown arg: " << subStr << std::endl;
403 if (optValue.empty()) {
404 auto nextIter = iter;
406 if (nextIter != args.end()) {
407 std::string nextArg = *(nextIter++);
408 if (!hasOptionPrefix(nextArg)) {
416 if (!optValue.empty()) {
417 setOptionValue(optName, optValue);
419 setOption(optName,
true);
421 std::cerr <<
"Unknown arg: " << optName << std::endl;
429 {std::cout <<
HelpText();
return false;}
433 {std::cout <<
UsageText();
return false;}
440 if (argc == 0 || argv ==
NULL) {
444 for (
int i = 0; i < argc; i++) {
445 argList.push_back(std::string(argv[i]));
447 return Parse(argList);
452 if (argc == 0 || argv ==
NULL) {
456 for (
int i = 0; i < argc; i++) {
457 argList.push_back(std::string(argv[i]));
459 return Parse(argList);
464 if (!_commandName.empty()) {
467 return sp->
IsSet(name);
486 if (!values.empty()) {
499 if (!_commandName.empty()) {
507 val = opt.
Value(index);
519 if (!_commandName.empty()) {
541 if (*wantIter == *nameIter) {
553 _options.push_back(option);
561 for (
size_t i = 0; i < options.size(); i++) {
570 return options.size() ? (okCount == options.size() ?
true :
false) :
false;
581 helpOpt.
SetDesc(
"Print the help text");
592 usageOpt.
SetDesc(
"Print the usage text");
598 if (!_commandName.empty()) {
610 if (!_commandName.empty()) {
616 _usageText = usageText;
622 if (!_commandName.empty()) {
629 std::string usageText;
630 if (!_usageText.empty()) {
631 usageText = _usageText;
633 usageText = generateUsageText();
640 if (!_commandName.empty()) {
646 _helpText = helpText;
652 if (!_commandName.empty()) {
659 std::string helpText;
660 if (_helpText.empty()) {
661 helpText = generateHelpText();
663 helpText = _helpText;
668 std::string AJACommandLineParser::generateHelpText()
const
670 std::ostringstream oss;
673 oss <<
"Usage: " << exePath;
674 if (!_name.empty()) {
677 oss <<
" [OPTION...]" << std::endl;
680 size_t longestSize = 0;
682 it != _options.end(); ++it) {
684 size_t namesLength = 0;
686 const std::string &name = *sIter;
687 namesLength += name.length();
689 if (name.length() == 1) {
696 namesLength += ((names.size()*2)-2);
697 if (namesLength > longestSize) {
698 longestSize = namesLength;
704 it != _options.end(); ++it) {
705 oss << std::setw(2) << std::right;
707 size_t nameCount = 0;
708 size_t namesLength = 0;
710 const std::string &name = *sIter;
711 namesLength += name.length();
712 if (name.length() == 1) {
719 if (++nameCount < names.size()) {
723 namesLength += ((names.size()*2)-2);
724 oss << std::setw((longestSize-namesLength) + it->Desc().length() + 8);
725 oss << it->Desc() << std::endl;
731 std::string AJACommandLineParser::generateUsageText()
const
733 std::ostringstream oss;
736 oss <<
"Usage: " << exePath;
737 if (!_name.empty()) {
742 std::ostringstream usages;
743 bool haveHelp =
false;
744 bool haveUsage =
false;
745 for (
const auto &opt : _options) {
746 if (opt.HaveName(
"?")) {
748 }
else if (opt.HaveName(
"usage")) {
751 auto names = opt.Names();
753 for (
size_t ndx = 0; ndx < names.size(); ndx++) {
754 auto name = names.at(ndx);
755 bool isShortName = name.length() == 1;
758 usages <<
'-' << name;
760 usages <<
"--" << name;
762 if (ndx < names.size()-1) {
766 usages <<
']' << std::endl;
772 usages <<
"\t[" <<
"-?|--help]" << std::endl;
775 usages <<
"\t[" <<
"--usage]" << std::endl;
778 if (!abbrev.empty()) {
782 oss <<
" [-" << abbrev <<
"]" << std::endl;
784 oss << usages.str() << std::endl;
786 if (!_subParsers.empty()) {
787 oss <<
'\n' <<
"commands: " << std::endl;
788 for (
const auto &sp : _subParsers) {
790 oss <<
"\t " << sp.second->Name() << std::endl;
802 bool AJACommandLineParser::hasOptionPrefix(
const std::string &name)
807 bool AJACommandLineParser::hasAssignmentOperator(
const std::string &arg)
810 return assignPos != std::string::npos;
813 bool AJACommandLineParser::setOptionValue(
const std::string &name,
const std::string &value)
815 if (!
value.empty()) {
816 for (
size_t i = 0; i < _options.size(); i++) {
821 _options[i].AddValue(value);
830 bool AJACommandLineParser::setOption(
const std::string &name,
bool isSet)
832 for (
size_t i = 0; i < _options.size(); i++) {
837 _options[i].MarkSet(isSet);