48 class CommandLineParserArgumentDescription
51 CommandLineParserArgumentDescription(
const string &longArg,
52 const string &longArgPrefix,
53 const string &shortArg,
54 const string &shortArgPrefix,
56 const string &argHelp,
57 const string &argLabel,
63 string &groupDescription)
65 LongArgPrefix(longArgPrefix),
67 ShortArgPrefix(shortArgPrefix),
71 ArgGroupDescription(groupDescription),
72 IgnoreRest(ignoreRest),
73 NumberOfParametersToProcess(0),
74 Deprecated(deprecated),
76 DefaultValue(defaultValue),
86 NumberOfParametersToProcess = 1;
91 NumberOfParametersToProcess = 0;
96 NumberOfParametersToProcess = -1;
101 NumberOfParametersToProcess = 1;
106 NumberOfParametersToProcess = 1;
113 NumberOfParametersToProcess = 1;
120 NumberOfParametersToProcess = 1;
125 NumberOfParametersToProcess = 1;
130 std::cout <<
"Type not supported: " <<
static_cast<int>(type);
134 ~CommandLineParserArgumentDescription() {}
135 bool addParameter(
const string &value);
140 string LongArgPrefix;
142 string ShortArgPrefix;
146 string ArgGroupDescription;
148 int NumberOfParametersToProcess;
158 bool CommandLineParserArgumentDescription::addParameter(
const string &value)
169 if (value.compare(
"true") == 0)
181 list.push_back(value);
187 list.push_back(value);
194 stringstream ss(value);
202 stringstream ss(value);
232 string CommandLineParserArgumentDescription::helpText()
236 string shortAndLongArg;
237 if (!this->ShortArg.empty())
239 shortAndLongArg =
" ";
240 shortAndLongArg += this->ShortArgPrefix;
241 shortAndLongArg += this->ShortArg;
244 if (!this->LongArg.empty())
246 if (this->ShortArg.empty())
247 shortAndLongArg.append(
" ");
249 shortAndLongArg.append(
", ");
251 shortAndLongArg += this->LongArgPrefix;
252 shortAndLongArg += this->LongArg;
255 text = text + shortAndLongArg +
", " + this->ArgHelp;
258 text +=
" (optional)";
260 if (!this->DefaultValue.Empty())
262 text = text +
", (default: " + this->DefaultValue.ToString() +
")";
273 class mitkCommandLineParser::ctkInternal
276 ctkInternal() :
Debug(false), FieldWidth(0), StrictMode(false) {}
278 CommandLineParserArgumentDescription *argumentDescription(
const string &argument);
280 vector<CommandLineParserArgumentDescription *> ArgumentDescriptionList;
281 map<string, CommandLineParserArgumentDescription *> ArgNameToArgumentDescriptionMap;
282 map<string, vector<CommandLineParserArgumentDescription *>> GroupToArgumentDescriptionListMap;
284 StringContainerType UnparsedArguments;
285 StringContainerType ProcessedArguments;
288 string::size_type FieldWidth;
292 string DisableQSettingsLongArg;
293 string DisableQSettingsShortArg;
301 CommandLineParserArgumentDescription *mitkCommandLineParser::ctkInternal::argumentDescription(
const string &argument)
303 string unprefixedArg = argument;
305 if (!LongPrefix.empty() && argument.compare(0, LongPrefix.size(), LongPrefix) == 0)
308 if (argument == LongPrefix && !ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix) == 0)
310 unprefixedArg = argument.substr(ShortPrefix.size(), argument.size());
314 unprefixedArg = argument.substr(LongPrefix.size(), argument.size());
317 else if (!ShortPrefix.empty() && argument.compare(0, ShortPrefix.size(), ShortPrefix) == 0)
319 unprefixedArg = argument.substr(ShortPrefix.size(), argument.size());
321 else if (!LongPrefix.empty() && !ShortPrefix.empty())
326 if (ArgNameToArgumentDescriptionMap.count(unprefixedArg))
328 return this->ArgNameToArgumentDescriptionMap[unprefixedArg];
339 this->Internal =
new ctkInternal();
340 this->Category = string();
341 this->Title = string();
342 this->Contributor = string();
343 this->Description = string();
344 this->ParameterGroupName =
"Parameters";
345 this->ParameterGroupDescription =
"Parameters";
351 delete this->Internal;
358 this->Internal->UnparsedArguments.clear();
359 this->Internal->ProcessedArguments.clear();
360 this->Internal->ErrorString.clear();
362 for (
unsigned int i = 0; i < Internal->ArgumentDescriptionList.size(); i++)
364 CommandLineParserArgumentDescription *desc = Internal->ArgumentDescriptionList.at(i);
365 desc->Value =
us::Any(desc->ValueType);
366 if (!desc->DefaultValue.Empty())
368 desc->Value = desc->DefaultValue;
372 bool ignoreRest =
false;
373 CommandLineParserArgumentDescription *currentArgDesc =
nullptr;
374 vector<CommandLineParserArgumentDescription *> parsedArgDescriptions;
375 for (
unsigned int i = 1; i < arguments.size(); ++i)
377 string argument = arguments.at(i);
379 if (this->Internal->Debug)
381 std::cout <<
"Processing" << argument;
383 if (!argument.compare(
"--xml") || !argument.compare(
"-xml") || !argument.compare(
"--XML") ||
384 !argument.compare(
"-XML"))
386 this->generateXmlOutput();
387 return map<string, us::Any>();
393 if (this->Internal->Debug)
395 std::cout <<
" Skipping: IgnoreRest flag was been set";
397 this->Internal->UnparsedArguments.push_back(argument);
402 if (!(argument.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix) == 0 ||
403 argument.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix) == 0))
405 if (this->Internal->StrictMode)
407 this->Internal->ErrorString =
"Unknown argument ";
408 this->Internal->ErrorString += argument;
412 if (this->Internal->Debug)
414 std::cout <<
" Skipping: It does not start with the defined prefix";
416 this->Internal->UnparsedArguments.push_back(argument);
421 bool alreadyProcessed =
false;
422 for (
auto alreadyHandledArgument : Internal->ProcessedArguments)
423 if (argument.compare(alreadyHandledArgument) == 0)
425 alreadyProcessed =
true;
429 if (alreadyProcessed)
431 if (this->Internal->StrictMode)
433 this->Internal->ErrorString =
"Argument ";
434 this->Internal->ErrorString += argument;
435 this->Internal->ErrorString +=
" already processed !";
439 if (this->Internal->Debug)
441 std::cout <<
" Skipping: Already processed !";
447 currentArgDesc = this->Internal->argumentDescription(argument);
453 if (currentArgDesc->Deprecated)
455 std::cout <<
"Deprecated argument " << argument <<
": " << currentArgDesc->ArgHelp;
459 parsedArgDescriptions.push_back(currentArgDesc);
462 this->Internal->ProcessedArguments.push_back(currentArgDesc->ShortArg);
463 this->Internal->ProcessedArguments.push_back(currentArgDesc->LongArg);
464 int numberOfParametersToProcess = currentArgDesc->NumberOfParametersToProcess;
465 ignoreRest = currentArgDesc->IgnoreRest;
466 if (this->Internal->Debug && ignoreRest)
468 std::cout <<
" IgnoreRest flag is True";
472 if (numberOfParametersToProcess == 0)
474 currentArgDesc->addParameter(
"true");
476 else if (numberOfParametersToProcess > 0)
478 string missingParameterError =
"Argument %1 has %2 value(s) associated whereas exacly %3 are expected.";
479 for (
int j = 1; j <= numberOfParametersToProcess; ++j)
481 if (i + j >= arguments.size())
490 return map<string, us::Any>();
492 string parameter = arguments.at(i + j);
493 if (this->Internal->Debug)
495 std::cout <<
" Processing parameter" << j <<
", value:" << parameter;
497 if (this->argumentAdded(parameter))
506 return map<string, us::Any>();
508 if (!currentArgDesc->addParameter(parameter))
518 return map<string, us::Any>();
522 i = i + numberOfParametersToProcess;
524 else if (numberOfParametersToProcess == -1)
526 if (this->Internal->Debug)
528 std::cout <<
" Proccessing StringList ...";
531 while (j + i < arguments.size())
533 if (this->argumentAdded(arguments.at(j + i)))
535 if (this->Internal->Debug)
537 std::cout <<
" No more parameter for" << argument;
541 string parameter = arguments.at(j + i);
543 if (parameter.compare(0, Internal->LongPrefix.size(), Internal->LongPrefix) == 0 ||
544 parameter.compare(0, Internal->ShortPrefix.size(), Internal->ShortPrefix) == 0)
550 if (this->Internal->Debug)
552 std::cout <<
" Processing parameter" << j <<
", value:" << parameter;
554 if (!currentArgDesc->addParameter(parameter))
564 return map<string, us::Any>();
574 if (this->Internal->StrictMode)
576 this->Internal->ErrorString =
"Unknown argument ";
577 this->Internal->ErrorString += argument;
581 if (this->Internal->Debug)
583 std::cout <<
" Skipping: Unknown argument";
585 this->Internal->UnparsedArguments.push_back(argument);
594 map<string, us::Any> parsedArguments;
596 int obligatoryArgs = 0;
597 vector<CommandLineParserArgumentDescription *>::iterator it;
598 for (it = Internal->ArgumentDescriptionList.begin(); it != Internal->ArgumentDescriptionList.end(); ++it)
600 CommandLineParserArgumentDescription *desc = *it;
606 int parsedObligatoryArgs = 0;
607 for (it = parsedArgDescriptions.begin(); it != parsedArgDescriptions.end(); ++it)
609 CommandLineParserArgumentDescription *desc = *it;
612 if (!desc->LongArg.empty())
618 key = desc->ShortArg;
622 parsedObligatoryArgs++;
624 std::pair<string, us::Any> elem;
626 elem.second = desc->Value;
627 parsedArguments.insert(elem);
630 if (obligatoryArgs > parsedObligatoryArgs)
632 parsedArguments.clear();
636 return parsedArguments;
645 for (
int i = 0; i < argc; ++i)
646 arguments.push_back(argv[i]);
648 return this->parseArguments(arguments, ok);
654 return this->Internal->ErrorString;
660 return this->Internal->UnparsedArguments;
665 const string &shortarg,
667 const string &argLabel,
668 const string &argHelp,
674 if (longarg.empty() && shortarg.empty())
680 bool added = (this->Internal->ArgNameToArgumentDescriptionMap.count(longarg) != 0);
686 added = (this->Internal->ArgNameToArgumentDescriptionMap.count(shortarg) != 0);
692 auto argDesc =
new CommandLineParserArgumentDescription(longarg,
693 this->Internal->LongPrefix,
695 this->Internal->ShortPrefix,
704 ParameterGroupDescription);
706 std::string::size_type argWidth = 0;
707 if (!longarg.empty())
709 this->Internal->ArgNameToArgumentDescriptionMap[longarg] = argDesc;
710 argWidth += longarg.size() + this->Internal->LongPrefix.size();
712 if (!shortarg.empty())
714 this->Internal->ArgNameToArgumentDescriptionMap[shortarg] = argDesc;
715 argWidth += shortarg.size() + this->Internal->ShortPrefix.size() + 2;
720 if (argWidth > this->Internal->FieldWidth)
722 this->Internal->FieldWidth = argWidth;
725 this->Internal->ArgumentDescriptionList.push_back(argDesc);
726 this->Internal->GroupToArgumentDescriptionListMap[this->Internal->CurrentGroup].push_back(argDesc);
731 const string &shortarg,
732 const string &argLabel,
733 const string &argHelp)
735 addArgument(longarg, shortarg,
StringList, argLabel, argHelp,
us::Any(),
false,
true,
false);
741 return this->Internal->FieldWidth;
747 this->Internal->CurrentGroup = description;
753 this->Internal->CurrentGroup.clear();
760 vector<CommandLineParserArgumentDescription *> deprecatedArgs;
762 text =
"Command Line Utility *" + Title +
"* in Category *" + Category +
"*\n";
763 text += Description +
"\n";
764 text += Contributor +
"\n\n";
765 text +=
"Use --xml to generate an XML description parsable as a CTK Command Line Module Plugin.\n";
768 map<string, vector<CommandLineParserArgumentDescription *>>::iterator it;
769 for (it = Internal->GroupToArgumentDescriptionListMap.begin();
770 it != Internal->GroupToArgumentDescriptionListMap.end();
773 if (!(*it).first.empty())
775 text = text +
"\n" + (*it).first +
"\n";
778 vector<CommandLineParserArgumentDescription *>::iterator it2;
779 for (it2 = (*it).second.begin(); it2 != (*it).second.end(); ++it2)
781 CommandLineParserArgumentDescription *argDesc = *it2;
782 if (argDesc->Deprecated)
784 deprecatedArgs.push_back(argDesc);
788 text += argDesc->helpText();
793 if (!deprecatedArgs.empty())
795 text +=
"\nDeprecated arguments:\n";
796 vector<CommandLineParserArgumentDescription *>::iterator it2;
797 for (it2 = deprecatedArgs.begin(); it2 != deprecatedArgs.end(); ++it2)
799 CommandLineParserArgumentDescription *argDesc = *it2;
800 text += argDesc->helpText();
810 return (this->Internal->ArgNameToArgumentDescriptionMap.count(argument) != 0);
816 for (
unsigned int i = 0; i < Internal->ProcessedArguments.size(); i++)
817 if (argument.compare(Internal->ProcessedArguments.at(i)) == 0)
825 this->Internal->LongPrefix = longPrefix;
826 this->Internal->ShortPrefix = shortPrefix;
832 this->Internal->StrictMode = strictMode;
837 std::stringstream xml;
839 xml <<
"<executable>" << endl;
840 xml <<
"<category>" << Category <<
"</category>" << endl;
841 xml <<
"<title>" << Title <<
"</title>" << endl;
842 xml <<
"<description>" << Description <<
"</description>" << endl;
843 xml <<
"<contributor>" << Contributor <<
"</contributor>" << endl;
844 xml <<
"<parameters>" << endl;
846 std::vector<CommandLineParserArgumentDescription *>::iterator it;
848 std::string lastParameterGroup =
"";
849 for (it = this->Internal->ArgumentDescriptionList.begin(); it != this->Internal->ArgumentDescriptionList.end(); it++)
852 switch ((*it)->ValueType)
863 type =
"string-vector";
889 if (lastParameterGroup.compare((*it)->ArgGroup))
891 if (it != this->Internal->ArgumentDescriptionList.begin())
893 xml <<
"</parameters>" << endl;
894 xml <<
"<parameters>" << endl;
896 xml <<
"<label>" << (*it)->ArgGroup <<
"</label>" << endl;
897 xml <<
"<description>" << (*it)->ArgGroupDescription <<
"</description>" << endl;
898 lastParameterGroup = (*it)->ArgGroup;
902 if ((*it)->ShortArg ==
"h")
905 xml <<
"<" << type <<
">" << endl;
906 xml <<
"<name>" << (*it)->LongArg <<
"</name>" << endl;
907 xml <<
"<description>" << (*it)->ArgHelp <<
"</description>" << endl;
908 xml <<
"<label>" << (*it)->ArgLabel <<
"</label>" << endl;
909 if (!(*it)->DefaultValue.Empty())
910 xml <<
"<default>" << (*it)->DefaultValue.ToString() <<
"</default>" << endl;
912 xml <<
"<longflag>" << (*it)->LongArg <<
"</longflag>" << endl;
913 xml <<
"<flag>" << (*it)->ShortArg <<
"</flag>" << endl;
918 xml <<
"<channel>input</channel>" << endl;
923 xml <<
"<channel>output</channel>" << endl;
925 xml <<
"</" << type <<
">" << endl;
928 xml <<
"</parameters>" << endl;
929 xml <<
"</executable>" << endl;
940 Contributor = contributor;
950 Description = description;
955 ParameterGroupName = name;
956 ParameterGroupDescription = tooltip;
void changeParameterGroup(std::string name, std::string tooltip)
bool argumentParsed(const std::string &argument) const
void setStrictModeEnabled(bool strictMode)
void setContributor(std::string contributor)
ValueType * any_cast(Any *operand)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
std::string errorString() const
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false)
bool argumentAdded(const std::string &argument) const
ValueType
Type of the value held by a Value object.
void setCategory(std::string category)
std::vector< std::string > StringList
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
void addDeprecatedArgument(const std::string &longarg, const std::string &shortarg, const std::string &argLabel, const std::string &argHelp)
const StringContainerType & unparsedArguments() const
std::string::size_type fieldWidth() const
std::string helpText() const
std::vector< std::string > StringContainerType
void setTitle(std::string title)
void setDescription(std::string description)
void beginGroup(const std::string &description)