1#ifndef APPLICATION_UTILITIES_ARGUMENTPARSER_H
2#define APPLICATION_UTILITIES_ARGUMENTPARSER_H
4#include "../conversion/stringconversion.h"
5#include "../misc/traits.h"
8#include <initializer_list>
11#ifdef CPP_UTILITIES_DEBUG_BUILD
23 const char *
name =
nullptr;
26 const char *
url =
nullptr;
45#define SET_DEPENDENCY_INFO ::CppUtilities::applicationInfo.dependencyVersions = DEPENCENCY_VERSIONS
52#define SET_APPLICATION_INFO \
53 ::CppUtilities::applicationInfo.name = APP_NAME; \
54 ::CppUtilities::applicationInfo.author = APP_AUTHOR; \
55 ::CppUtilities::applicationInfo.version = APP_VERSION; \
56 ::CppUtilities::applicationInfo.url = APP_URL; \
57 ::CppUtilities::applicationInfo.domain = APP_DOMAIN; \
58 ::CppUtilities::applicationInfo.description = APP_DESCRIPTION; \
59 ::CppUtilities::applicationInfo.license = PROJECT_LICENSE; \
60 ::CppUtilities::applicationInfo.credits = APP_CREDITS; \
98 return static_cast<ParseArgumentBehavior>(
static_cast<unsigned char>(lhs) |
static_cast<unsigned char>(rhs));
103 return static_cast<bool>(
static_cast<unsigned char>(lhs) &
static_cast<unsigned char>(rhs));
129 return static_cast<ValueCompletionBehavior>(
static_cast<unsigned char>(lhs) |
static_cast<unsigned char>(rhs));
134 return static_cast<bool>(
static_cast<unsigned char>(lhs) &
static_cast<unsigned char>(rhs));
145namespace ValueConversion {
146template <
typename TargetType, Traits::EnableIf<std::is_same<TargetType, std::
string>> * =
nullptr> TargetType
convert(
const char *value)
148 return std::string(value);
151template <
typename TargetType, Traits::EnableIf<std::is_arithmetic<TargetType>> * =
nullptr> TargetType
convert(
const char *value)
153 return stringToNumber<TargetType>(value);
159 const std::string errorMessage;
160 const char *
const valueToConvert;
161 const char *
const targetTypeName;
163 [[noreturn]]
void throwFailure(
const std::vector<Argument *> &argumentPath)
const;
166template <std::size_t N,
typename FirstTargetType,
typename... RemainingTargetTypes>
struct ArgumentValueConverter {
167 static std::tuple<FirstTargetType, RemainingTargetTypes...> convertValues(std::vector<const char *>::const_iterator firstValue)
169 return std::tuple_cat(ArgumentValueConverter<1, FirstTargetType>::convertValues(firstValue),
170 ArgumentValueConverter<N - 1, RemainingTargetTypes...>::convertValues(firstValue + 1));
174template <
typename FirstTargetType,
typename... RemainingTargetTypes>
struct ArgumentValueConverter<1, FirstTargetType, RemainingTargetTypes...> {
175 static std::tuple<FirstTargetType> convertValues(std::vector<const char *>::const_iterator firstValue)
179 return std::make_tuple<FirstTargetType>(ValueConversion::convert<FirstTargetType>(*firstValue));
180 }
catch (
const ConversionException &exception) {
181 throw ArgumentValueConversionError{ exception.what(), *firstValue,
typeid(FirstTargetType).name() };
213 template <
typename... RemainingTargetTypes> std::tuple<RemainingTargetTypes...> convertValues()
const;
216 [[noreturn]]
void throwNumberOfValuesNotSufficient(
unsigned long valuesToConvert)
const;
226 constexpr auto valuesToConvert =
sizeof...(RemainingTargetTypes);
227 if (
values.size() < valuesToConvert) {
228 throwNumberOfValuesNotSufficient(valuesToConvert);
231 return ValueConversion::Helper::ArgumentValueConverter<valuesToConvert, RemainingTargetTypes...>::convertValues(
values.cbegin());
232 }
catch (
const ValueConversion::Helper::ArgumentValueConversionError &error) {
233 error.throwFailure(
path);
258 path.push_back(parent);
282 Argument(
const char *name,
char abbreviation =
'\0',
const char *description =
nullptr,
const char *example =
nullptr);
293 const char *name()
const;
294 void setName(
const char *name);
295 char abbreviation()
const;
296 void setAbbreviation(
char abbreviation);
297 const char *environmentVariable()
const;
298 void setEnvironmentVariable(
const char *environmentVariable);
299 const char *description()
const;
300 void setDescription(
const char *description);
301 const char *example()
const;
302 void setExample(
const char *example);
303 std::size_t requiredValueCount()
const;
304 void setRequiredValueCount(std::size_t requiredValueCount);
305 const std::vector<const char *> &valueNames()
const;
306 void setValueNames(std::initializer_list<const char *> valueNames);
307 void appendValueName(
const char *valueName);
308 void setConstraints(std::size_t minOccurrences, std::size_t maxOccurrences);
309 const std::vector<Argument *> &path(std::size_t occurrence = 0)
const;
310 bool isRequired()
const;
311 void setRequired(
bool required);
315 bool isCombinable()
const;
316 void setCombinable(
bool combinable);
317 bool isImplicit()
const;
318 void setImplicit(
bool implicit);
319 bool denotesOperation()
const;
320 void setDenotesOperation(
bool denotesOperation);
321 const CallbackFunction &callback()
const;
322 void setCallback(CallbackFunction callback);
326 bool hasSubArguments()
const;
328 void printInfo(std::ostream &os,
unsigned char indentation = 0)
const;
333 const char *preDefinedCompletionValues()
const;
334 void setPreDefinedCompletionValues(
const char *preDefinedCompletionValues);
337 const std::vector<const char *> &values(std::size_t occurrence = 0)
const;
338 template <
typename... TargetType> std::tuple<TargetType...> valuesAs(std::size_t occurrence = 0)
const;
339 template <
typename... TargetType> std::vector<std::tuple<TargetType...>> allValuesAs()
const;
341 const char *firstValue()
const;
342 const char *firstValueOr(
const char *fallback)
const;
343 bool allRequiredValuesPresent(std::size_t occurrence = 0)
const;
344 bool isPresent()
const;
345 std::size_t occurrences()
const;
346 std::size_t index(std::size_t occurrence)
const;
347 std::size_t minOccurrences()
const;
348 std::size_t maxOccurrences()
const;
349 bool isDeprecated()
const;
350 const Argument *deprecatedBy()
const;
351 void markAsDeprecated(
const Argument *deprecatedBy =
nullptr);
352 bool isMainArgument()
const;
353 bool isParentPresent()
const;
354 Argument *conflictsWithArgument()
const;
355 Argument *wouldConflictWithArgument()
const;
356 Argument *specifiedOperation()
const;
357 const std::vector<ArgumentOccurrence> &occurrenceInfo()
const;
358 std::vector<ArgumentOccurrence> &occurrenceInfo();
360 void resetRecursively();
370 bool matchesDenotation(
const char *denotation, std::size_t denotationLength)
const;
374 const char *m_environmentVar;
375 const char *m_description;
376 const char *m_example;
377 std::size_t m_minOccurrences;
378 std::size_t m_maxOccurrences;
379 std::size_t m_requiredValueCount;
380 std::vector<const char *> m_valueNames;
382 std::vector<ArgumentOccurrence> m_occurrences;
389 const char *m_preDefinedCompletionValues;
395 return static_cast<Argument::Flags>(
static_cast<unsigned char>(lhs) |
static_cast<unsigned char>(rhs));
400 return static_cast<bool>(
static_cast<unsigned char>(lhs) &
static_cast<unsigned char>(rhs));
409template <
typename... TargetType> std::tuple<TargetType...>
Argument::valuesAs(std::size_t occurrence)
const
411 return m_occurrences[occurrence].convertValues<TargetType...>();
421 std::vector<std::tuple<TargetType...>> res;
422 res.reserve(m_occurrences.size());
423 for (
const auto &occurrence : m_occurrences) {
424 res.emplace_back(occurrence.convertValues<TargetType...>());
436 OperationArgument(
const char *name,
char abbreviation =
'\0',
const char *description =
nullptr,
const char *example =
nullptr);
441 ConfigValueArgument(
const char *name,
char abbreviation =
'\0',
const char *description =
nullptr,
442 std::initializer_list<const char *> valueNames = std::initializer_list<const char *>());
465 void addMainArgument(
Argument *argument);
468 void printHelp(std::ostream &os)
const;
469 void parseArgs(
int argc,
const char *
const *argv,
472 void readArgs(
int argc,
const char *
const *argv);
474 void checkConstraints();
475 void invokeCallbacks();
478 unsigned int actualArgumentCount()
const;
479 const char *executable()
const;
483 void setDefaultArgument(
Argument *argument);
484 Argument *specifiedOperation()
const;
485 bool isUncombinableMainArgPresent()
const;
486 void setExitFunction(std::function<
void(
int)> exitFunction);
496 int argc,
const char *
const *argv,
unsigned int currentWordIndex,
const ArgumentReader &reader)
const;
497 std::string findSuggestions(
int argc,
const char *
const *argv,
unsigned int cursorPos,
const ArgumentReader &reader)
const;
498 void printBashCompletion(
int argc,
const char *
const *argv,
unsigned int cursorPos,
const ArgumentReader &reader)
const;
501 void invokeExit(
int code);
504 unsigned int m_actualArgc;
505 const char *m_executable;
510 std::function<void(
int)> m_exitFunction;
532#ifdef CPP_UTILITIES_DEBUG_BUILD
534 assert(*
name !=
'-');
535 for (
const char *c =
name; *c; ++c) {
536 assert(*c !=
' ' && *c !=
'=' && *c !=
'\'' && *c !=
'\"' && *c !=
'\n' && *c !=
'\r');
550 return m_abbreviation;
573 return m_environmentVar;
592 return m_description;
633 return m_occurrences[occurrence].values;
651 return m_requiredValueCount;
710 m_valueNames.emplace_back(valueName);
719 || (m_occurrences[occurrence].values.size() >=
static_cast<std::size_t
>(m_requiredValueCount));
745 return !m_occurrences.empty();
753 return m_occurrences.size();
761 return m_occurrences[occurrence].index;
771 return m_minOccurrences;
781 return m_maxOccurrences;
794 return m_deprecatedBy;
822inline const std::vector<Argument *> &
Argument::path(std::size_t occurrence)
const
824 return m_occurrences[occurrence].path;
838 return m_minOccurrences;
851 if (!m_minOccurrences) {
852 m_minOccurrences = 1;
855 m_minOccurrences = 0;
880 m_flags = add ? (m_flags |
flags)
881 :
static_cast<Argument::Flags>(
static_cast<std::underlying_type<Argument::Flags>::type
>(m_flags)
882 & ~static_cast<std::underlying_type<Argument::Flags>::type>(
flags));
941 return m_callbackFunction;
974 return !m_subArgs.empty();
1011 return m_valueCompletionBehavior;
1022 m_valueCompletionBehavior = completionValues;
1030 return m_preDefinedCompletionValues;
1048 m_occurrences.clear();
1052 :
Argument(name, abbreviation, description, example)
1061 const char *name,
char abbreviation,
const char *description, std::initializer_list<const char *> valueNames)
1062 :
Argument(name, abbreviation, description)
1075 return m_occurrences;
1086 return m_occurrences;
1103 return m_actualArgc;
1111 return m_executable;
1121 return m_unknownArgBehavior;
1131 m_unknownArgBehavior = behavior;
1140 return m_defaultArg;
1149 m_defaultArg = argument;
1177 m_exitFunction = exitFunction;
1201 return m_noColorArg;
1209 return m_noColorArg;
#define CPP_UTILITIES_IF_DEBUG_BUILD(x)
Wraps debug-only lines conveniently.
The ArgumentParserTests class tests the ArgumentParser and Argument classes.
The ArgumentParser class provides a means for handling command line arguments.
void setDefaultArgument(Argument *argument)
Sets the default argument.
const HelpArgument & helpArg() const
Returns the --help argument.
void checkConstraints()
Checks whether constraints are violated.
const char * executable() const
Returns the name of the current executable.
const ArgumentVector & mainArguments() const
Returns the main arguments.
unsigned int actualArgumentCount() const
Returns the actual number of arguments that could be found when parsing.
void setUnknownArgumentBehavior(UnknownArgumentBehavior behavior)
Sets how unknown arguments are treated.
Argument * defaultArgument() const
Returns the default argument.
void setExitFunction(std::function< void(int)> exitFunction)
Specifies a function quit the application.
void invokeCallbacks()
Invokes all assigned callbacks.
UnknownArgumentBehavior unknownArgumentBehavior() const
Returns how unknown arguments are treated.
const NoColorArgument & noColorArg() const
Returns the --no-color argument.
The ArgumentReader class internally encapsulates the process of reading command line arguments.
The Argument class is a wrapper for command line argument information.
const char * description() const
Returns the description of the argument.
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.
The ConfigValueArgument class is an Argument where setCombinable() is true by default.
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,...
The NoColorArgument class allows to specify whether use of escape codes or similar technique to provi...
The OperationArgument class is an Argument where denotesOperation() is true by default.
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)
constexpr FlagEnumClass operator|(FlagEnumClass lhs, FlagEnumClass rhs)
TargetType convert(const char *value)
Contains all utilities provides by the c++utilities library.
std::vector< Argument * > ArgumentVector
UnknownArgumentBehavior
The UnknownArgumentBehavior enum specifies the behavior of the argument parser when an unknown argume...
ParseArgumentBehavior
The ParseArgumentBehavior enum specifies the behavior when parsing arguments.
std::function< bool(Argument *)> ArgumentPredicate
std::initializer_list< Argument * > ArgumentInitializerList
constexpr T max(T first, T second)
Returns the greatest of the given items.
ValueCompletionBehavior
The ValueCompletionBehavior enum specifies the items to be considered when generating completion for ...
@ FileSystemIfNoPreDefinedValues
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).