1#ifndef APPLICATION_UTILITIES_ARGUMENTPARSER_H
2#define APPLICATION_UTILITIES_ARGUMENTPARSER_H
8#include <initializer_list>
12#ifdef CPP_UTILITIES_DEBUG_BUILD
24 const char *
name =
nullptr;
27 const char *
url =
nullptr;
46#define SET_DEPENDENCY_INFO ::CppUtilities::applicationInfo.dependencyVersions = DEPENCENCY_VERSIONS
53#define SET_APPLICATION_INFO \
54 ::CppUtilities::applicationInfo.name = APP_NAME; \
55 ::CppUtilities::applicationInfo.author = APP_AUTHOR; \
56 ::CppUtilities::applicationInfo.version = APP_VERSION; \
57 ::CppUtilities::applicationInfo.url = APP_URL; \
58 ::CppUtilities::applicationInfo.domain = APP_DOMAIN; \
59 ::CppUtilities::applicationInfo.description = APP_DESCRIPTION; \
60 ::CppUtilities::applicationInfo.license = PROJECT_LICENSE; \
61 ::CppUtilities::applicationInfo.credits = APP_CREDITS; \
99 return static_cast<ParseArgumentBehavior>(
static_cast<unsigned char>(lhs) |
static_cast<unsigned char>(rhs));
104 return static_cast<bool>(
static_cast<unsigned char>(lhs) &
static_cast<unsigned char>(rhs));
130 return static_cast<ValueCompletionBehavior>(
static_cast<unsigned char>(lhs) |
static_cast<unsigned char>(rhs));
135 return static_cast<bool>(
static_cast<unsigned char>(lhs) &
static_cast<unsigned char>(rhs));
147template <
typename TargetType, Traits::EnableIf<std::is_same<TargetType, std::
string>> * =
nullptr> TargetType
convert(
const char *value)
149 return std::string(value);
152template <
typename TargetType, Traits::EnableIf<std::is_arithmetic<TargetType>> * =
nullptr> TargetType
convert(
const char *value)
160 const std::string errorMessage;
161 const char *
const valueToConvert;
162 const char *
const targetTypeName;
164 [[noreturn]]
void throwFailure(
const std::vector<Argument *> &argumentPath)
const;
167template <std::size_t N,
typename FirstTargetType,
typename... RemainingTargetTypes>
struct ArgumentValueConverter {
168 static std::tuple<FirstTargetType, RemainingTargetTypes...> convertValues(std::vector<const char *>::const_iterator firstValue)
170 return std::tuple_cat(ArgumentValueConverter<1, FirstTargetType>::convertValues(firstValue),
171 ArgumentValueConverter<N - 1, RemainingTargetTypes...>::convertValues(firstValue + 1));
175template <
typename FirstTargetType,
typename... RemainingTargetTypes>
struct ArgumentValueConverter<1, FirstTargetType, RemainingTargetTypes...> {
176 static std::tuple<FirstTargetType> convertValues(std::vector<const char *>::const_iterator firstValue)
180 return std::make_tuple<FirstTargetType>(ValueConversion::convert<FirstTargetType>(*firstValue));
181 }
catch (
const ConversionException &exception) {
182 throw ArgumentValueConversionError{ exception.what(), *firstValue,
typeid(FirstTargetType).name() };
214 template <
typename... RemainingTargetTypes> std::tuple<RemainingTargetTypes...>
convertValues()
const;
217 [[noreturn]]
void throwNumberOfValuesNotSufficient(
unsigned long valuesToConvert)
const;
227 constexpr auto valuesToConvert =
sizeof...(RemainingTargetTypes);
228 if (
values.size() < valuesToConvert) {
229 throwNumberOfValuesNotSufficient(valuesToConvert);
232 return ValueConversion::Helper::ArgumentValueConverter<valuesToConvert, RemainingTargetTypes...>::convertValues(
values.cbegin());
233 }
catch (
const ValueConversion::Helper::ArgumentValueConversionError &error) {
234 error.throwFailure(
path);
259 path.push_back(parent);
264 friend ArgumentParser;
265 friend ArgumentReader;
266 friend ArgumentParserTests;
283 Argument(
const char *name,
char abbreviation =
'\0',
const char *description =
nullptr,
const char *example =
nullptr);
294 const char *name()
const;
295 void setName(
const char *name);
296 char abbreviation()
const;
297 void setAbbreviation(
char abbreviation);
298 const char *environmentVariable()
const;
299 void setEnvironmentVariable(
const char *environmentVariable);
300 const char *description()
const;
301 void setDescription(
const char *description);
302 const char *example()
const;
303 void setExample(
const char *example);
304 std::size_t requiredValueCount()
const;
305 void setRequiredValueCount(std::size_t requiredValueCount);
306 const std::vector<const char *> &valueNames()
const;
307 void setValueNames(std::initializer_list<const char *> valueNames);
308 void appendValueName(
const char *valueName);
309 void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
310 const std::vector<Argument *> &path(std::size_t occurrence = 0)
const;
311 bool isRequired()
const;
312 void setRequired(
bool required);
316 bool isCombinable()
const;
317 void setCombinable(
bool combinable);
318 bool isImplicit()
const;
319 void setImplicit(
bool implicit);
320 bool denotesOperation()
const;
321 void setDenotesOperation(
bool denotesOperation);
322 const CallbackFunction &callback()
const;
323 void setCallback(CallbackFunction callback);
328 bool hasSubArguments()
const;
330 void printInfo(std::ostream &os,
unsigned char indentation = 0)
const;
335 const char *preDefinedCompletionValues()
const;
336 void setPreDefinedCompletionValues(
const char *preDefinedCompletionValues);
339 const std::vector<const char *> &values(std::size_t occurrence = 0)
const;
340 template <
typename... TargetType> std::tuple<TargetType...> valuesAs(std::size_t occurrence = 0)
const;
341 template <
typename... TargetType> std::vector<std::tuple<TargetType...>> allValuesAs()
const;
343 const char *firstValue()
const;
344 const char *firstValueOr(
const char *fallback)
const;
345 bool allRequiredValuesPresent(std::size_t occurrence = 0)
const;
346 bool isPresent()
const;
347 std::size_t occurrences()
const;
348 std::size_t index(std::size_t occurrence)
const;
349 std::size_t minOccurrences()
const;
350 std::size_t maxOccurrences()
const;
351 bool isDeprecated()
const;
352 const Argument *deprecatedBy()
const;
353 void markAsDeprecated(
const Argument *deprecatedBy =
nullptr);
354 bool isMainArgument()
const;
355 bool isParentPresent()
const;
356 Argument *conflictsWithArgument()
const;
357 Argument *wouldConflictWithArgument()
const;
358 Argument *specifiedOperation()
const;
359 const std::vector<ArgumentOccurrence> &occurrenceInfo()
const;
360 std::vector<ArgumentOccurrence> &occurrenceInfo();
362 void resetRecursively();
368 static constexpr std::size_t
varValueCount = std::numeric_limits<std::size_t>::max();
372 bool matchesDenotation(
const char *denotation, std::size_t denotationLength)
const;
376 const char *m_environmentVar;
377 const char *m_description;
378 const char *m_example;
379 std::size_t m_minOccurrences;
380 std::size_t m_maxOccurrences;
381 std::size_t m_requiredValueCount;
382 std::vector<const char *> m_valueNames;
384 std::vector<ArgumentOccurrence> m_occurrences;
391 const char *m_preDefinedCompletionValues;
397 return static_cast<Argument::Flags>(
static_cast<unsigned char>(lhs) |
static_cast<unsigned char>(rhs));
402 return static_cast<bool>(
static_cast<unsigned char>(lhs) &
static_cast<unsigned char>(rhs));
411template <
typename... TargetType> std::tuple<TargetType...>
Argument::valuesAs(std::size_t occurrence)
const
413 return m_occurrences[occurrence].convertValues<TargetType...>();
423 std::vector<std::tuple<TargetType...>> res;
424 res.reserve(m_occurrences.size());
425 for (
const auto &occurrence : m_occurrences) {
426 res.emplace_back(occurrence.convertValues<TargetType...>());
444 std::initializer_list<const char *>
valueNames = std::initializer_list<const char *>());
448 friend ArgumentParserTests;
458 friend ArgumentParserTests;
459 friend ArgumentReader;
471 void parseArgs(
int argc,
const char *
const *argv,
474 void readArgs(
int argc,
const char *
const *argv);
500 int argc,
const char *
const *argv,
unsigned int currentWordIndex,
const ArgumentReader &reader)
const;
501 std::string findSuggestions(
int argc,
const char *
const *argv,
unsigned int cursorPos,
const ArgumentReader &reader)
const;
502 void printBashCompletion(
int argc,
const char *
const *argv,
unsigned int cursorPos,
const ArgumentReader &reader)
const;
505 void invokeExit(
int code);
508 unsigned int m_actualArgc;
509 const char *m_executable;
514 std::function<void(
int)> m_exitFunction;
536#if defined(CPP_UTILITIES_DEBUG_BUILD) && !defined(_MSC_VER)
538 assert(*
name !=
'-');
539 for (
const char *c =
name; *c; ++c) {
540 assert(*c !=
' ' && *c !=
'=' && *c !=
'\'' && *c !=
'\"' && *c !=
'\n' && *c !=
'\r');
554 return m_abbreviation;
577 return m_environmentVar;
596 return m_description;
637 return m_occurrences[occurrence].values;
655 return m_requiredValueCount;
714 m_valueNames.emplace_back(valueName);
723 || (m_occurrences[occurrence].values.size() >=
static_cast<std::size_t
>(m_requiredValueCount));
749 return !m_occurrences.empty();
757 return m_occurrences.size();
765 return m_occurrences[occurrence].index;
775 return m_minOccurrences;
785 return m_maxOccurrences;
798 return m_deprecatedBy;
826inline const std::vector<Argument *> &
Argument::path(std::size_t occurrence)
const
828 return m_occurrences[occurrence].path;
842 return m_minOccurrences;
855 if (!m_minOccurrences) {
856 m_minOccurrences = 1;
859 m_minOccurrences = 0;
884 m_flags = add ? (m_flags |
flags)
885 :
static_cast<Argument::Flags>(
static_cast<std::underlying_type<Argument::Flags>::type
>(m_flags)
886 & ~static_cast<std::underlying_type<Argument::Flags>::type>(
flags));
945 return m_callbackFunction;
978 return !m_subArgs.empty();
1015 return m_valueCompletionBehavior;
1026 m_valueCompletionBehavior = completionValues;
1034 return m_preDefinedCompletionValues;
1052 m_occurrences.clear();
1079 return m_occurrences;
1090 return m_occurrences;
1107 return m_actualArgc;
1115 return m_executable;
1125 return m_unknownArgBehavior;
1135 m_unknownArgBehavior = behavior;
1144 return m_defaultArg;
1153 m_defaultArg = argument;
1181 m_exitFunction = exitFunction;
1205 return m_noColorArg;
1213 return m_noColorArg;
#define CPP_UTILITIES_IF_DEBUG_BUILD(x)
Wraps debug-only lines conveniently.
The ArgumentParserTests class tests the ArgumentParser and Argument classes.
void setDefaultArgument(Argument *argument)
Sets the default argument.
const HelpArgument & helpArg() const
Returns the --help argument.
void checkConstraints()
Checks whether constraints are violated.
ArgumentParser()
Constructs a new ArgumentParser.
const char * executable() const
Returns the name of the current executable.
void readArgs(int argc, const char *const *argv)
Parses the specified command line arguments.
const ArgumentVector & mainArguments() const
Returns the main arguments.
unsigned int actualArgumentCount() const
Returns the actual number of arguments that could be found when parsing.
bool isUncombinableMainArgPresent() const
Checks whether at least one uncombinable main argument is present.
void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior)
Sets how unknown arguments are treated.
Argument * defaultArgument() const
Returns the default argument.
void setMainArguments(const ArgumentInitializerList &mainArguments)
Sets the main arguments for the parser.
void setExitFunction(std::function< void(int)> exitFunction)
Specifies a function quit the application.
void printHelp(std::ostream &os) const
Prints help text for all assigned arguments.
void addMainArgument(Argument *argument)
Adds the specified argument to the main argument.
void parseArgs(int argc, const char *const *argv, ParseArgumentBehavior behavior=ParseArgumentBehavior::CheckConstraints|ParseArgumentBehavior::InvokeCallbacks|ParseArgumentBehavior::ExitOnFailure)
Parses the specified command line arguments.
void invokeCallbacks()
Invokes all assigned callbacks.
void resetArgs()
Resets all Argument instances assigned as mainArguments() and sub arguments.
void ensureDefaultOperation()
Ensures a main operation argument is present.
UnknownArgumentBehavior unknownArgumentBehavior() const
Returns how unknown arguments are treated.
const NoColorArgument & noColorArg() const
Returns the --no-color argument.
Argument * specifiedOperation() const
Returns the first operation argument specified by the user or nullptr if no operation has been specif...
void assumeDefaultArgument()
Assumes the default argument is present (if not already present).
The Argument class is a wrapper for command line argument information.
const char * description() const
Returns the description of the argument.
Argument(const char *name, char abbreviation='\0', const char *description=nullptr, const char *example=nullptr)
Constructs an Argument with the given name, abbreviation and description.
static constexpr std::size_t varValueCount
Denotes a variable number of values.
const std::vector< Argument * > & path(std::size_t occurrence=0) const
Returns the path of the specified occurrence.
bool isMainArgument() const
Returns an indication whether the argument is used as main argument.
const ArgumentVector & subArguments() const
Returns the secondary arguments for this argument.
const char * example() const
Returns the usage example of the argument.
Flags
The Flags enum specifies options for treating the argument in a special way.
bool isDeprecated() const
const std::vector< const char * > & valueNames() const
Returns the names of the required values.
void setValueCompletionBehavior(ValueCompletionBehavior valueCompletionBehaviour)
Sets the items to be considered when generating completion for the values.
const CallbackFunction & callback() const
Returns the assigned callback function.
const std::vector< ArgumentOccurrence > & occurrenceInfo() const
Returns information about all occurrences of the argument which have been detected when parsing.
ValueCompletionBehavior valueCompletionBehaviour() const
Returns the items to be considered when generating completion for the values.
void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences)
Sets the allowed number of occurrences.
void setImplicit(bool implicit)
Sets whether the argument is an implicit argument.
void setValueNames(std::initializer_list< const char * > valueNames)
Sets the names of the required values.
char abbreviation() const
Returns the abbreviation of the argument.
std::size_t occurrences() const
Returns how often the argument could be detected when parsing.
void setDenotesOperation(bool denotesOperation)
Sets whether the argument denotes the operation.
void markAsDeprecated(const Argument *deprecatedBy=nullptr)
Marks the argument as deprecated.
const char * name() const
Returns the name of the argument.
void setAbbreviation(char abbreviation)
Sets the abbreviation of the argument.
bool isCombinable() const
Returns an indication whether the argument is combinable.
bool denotesOperation() const
Returns whether the argument denotes an operation.
void setDescription(const char *description)
Sets the description of the argument.
void appendValueName(const char *valueName)
Appends a value name.
std::size_t maxOccurrences() const
Returns the maximum number of occurrences.
Argument::Flags flags() const
Returns Argument::Flags for the argument.
const std::vector< const char * > & values(std::size_t occurrence=0) const
Returns the parameter values for the specified occurrence of argument.
const char * preDefinedCompletionValues() const
Returns the assigned values used when generating completion for the values.
std::size_t requiredValueCount() const
Returns the number of values which are required to be given for this argument.
const char * environmentVariable() const
Returns the environment variable queried when firstValue() is called.
std::vector< std::tuple< TargetType... > > allValuesAs() const
Converts the present values for all occurrence to the specified target types.
bool isImplicit() const
Returns an indication whether the argument is an implicit argument.
void reset()
Resets occurrences (indices, values and paths).
const Argument * deprecatedBy() const
Returns the argument which obsoletes this argument.
std::function< void(const ArgumentOccurrence &)> CallbackFunction
std::size_t index(std::size_t occurrence) const
Returns the indices of the argument's occurrences which could be detected when parsing.
bool isPresent() const
Returns an indication whether the argument could be detected when parsing.
void setExample(const char *example)
Sets the a usage example for the argument.
const ArgumentVector & parents() const
Returns the parents of this argument.
void setFlags(Argument::Flags flags)
Replaces all Argument::Flags for the argument with the flags.
std::size_t minOccurrences() const
Returns the minimum number of occurrences.
bool allRequiredValuesPresent(std::size_t occurrence=0) const
Returns an indication whether all required values are present.
void setCombinable(bool combinable)
Sets whether this argument can be combined.
void setCallback(CallbackFunction callback)
Sets a callback function which will be called by the parser if the argument could be found and no par...
bool isRequired() const
Returns an indication whether the argument is mandatory.
void setRequired(bool required)
Sets whether this argument is mandatory or not.
void setPreDefinedCompletionValues(const char *preDefinedCompletionValues)
Assigns the values to be used when generating completion for the values.
void setEnvironmentVariable(const char *environmentVariable)
Sets the environment variable queried when firstValue() is called.
bool hasSubArguments() const
Returns an indication whether the argument has secondary arguments.
std::tuple< TargetType... > valuesAs(std::size_t occurrence=0) const
Converts the present values for the specified occurrence to the specified target types.
void setRequiredValueCount(std::size_t requiredValueCount)
Sets the number of values which are required to be given for this argument.
void setName(const char *name)
Sets the name of the argument.
ConfigValueArgument(const char *name, char abbreviation='\0', const char *description=nullptr, std::initializer_list< const char * > valueNames=std::initializer_list< const char * >())
Constructs a new ConfigValueArgument with the specified parameter.
The HelpArgument class prints help information for an argument parser when present (–help,...
HelpArgument(ArgumentParser &parser)
Constructs a new help argument for the specified parser.
The NoColorArgument class allows to specify whether use of escape codes or similar technique to provi...
void apply() const
Sets EscapeCodes::enabled according to the presence of the first instantiation of NoColorArgument.
NoColorArgument()
Constructs a new NoColorArgument argument.
OperationArgument(const char *name, char abbreviation='\0', const char *description=nullptr, const char *example=nullptr)
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
constexpr bool operator&(FlagEnumClass lhs, FlagEnumClass rhs)
Contains functions to convert raw argument values to certain types.
TargetType convert(const char *value)
Contains all utilities provides by the c++utilities library.
std::initializer_list< Argument * > ArgumentInitializerList
std::vector< Argument * > ArgumentVector
UnknownArgumentBehavior
The UnknownArgumentBehavior enum specifies the behavior of the argument parser when an unknown argume...
IntegralType stringToNumber(const StringType &string, BaseType base=10)
Converts the given string to an unsigned/signed number assuming string uses the specified base.
ParseArgumentBehavior
The ParseArgumentBehavior enum specifies the behavior when parsing arguments.
ValueCompletionBehavior
The ValueCompletionBehavior enum specifies the items to be considered when generating completion for ...
@ FileSystemIfNoPreDefinedValues
std::function< bool(Argument *)> ArgumentPredicate
CPP_UTILITIES_EXPORT ApplicationInfo applicationInfo
Stores global application info used by ArgumentParser::printHelp() and AboutDialog.
Stores information about an application.
std::vector< const char * > dependencyVersions
The ArgumentCompletionInfo struct holds information internally used for shell completion and suggesti...
The ArgumentOccurrence struct holds argument values for an occurrence of an argument.
std::size_t index
The index of the occurrence.
std::vector< const char * > values
The parameter values which have been specified after the occurrence of the argument.
std::tuple< RemainingTargetTypes... > convertValues() const
Converts the present values to the specified target types.
ArgumentOccurrence(std::size_t index)
Constructs an argument occurrence for the specified index.
std::vector< Argument * > path
The "path" of the occurrence (the parent elements which have been specified before).