2024-07-30 22:13:59 +08:00
|
|
|
namespace YYCC::ArgParser {
|
2024-07-30 10:35:41 +08:00
|
|
|
/**
|
|
|
|
|
|
|
|
\page arg_parser Universal Argument Parser
|
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
YYCC::ArgParser provides an universal way to parsing command line arguments.
|
2024-07-30 10:35:41 +08:00
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
Universal argument parser has similar design with universal config manager,
|
|
|
|
it is highly recommand that read \ref config_manager chapter first,
|
|
|
|
because you will have a clear understanding of this namespace after reading universal config manager chapter.
|
2024-07-30 10:35:41 +08:00
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
There is an example about how to use universal argument parser.
|
|
|
|
In following content, we will describe it in detail.
|
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
\code{.cpp}
|
|
|
|
class TestArgParser {
|
|
|
|
public:
|
|
|
|
TestArgParser() :
|
|
|
|
m_IntArgument(YYCC_U8("int"), YYCC_U8_CHAR('i'), YYCC_U8("integral argument"), YYCC_U8("114514")),
|
|
|
|
m_FloatArgument(nullptr, YYCC_U8_CHAR('f'), nullptr, nullptr, true),
|
|
|
|
m_StringArgument(YYCC_U8("string"), YYCC::ArgParser::AbstractArgument::NO_SHORT_NAME, nullptr, nullptr, true),
|
|
|
|
m_BoolArgument(nullptr, YYCC_U8_CHAR('b'), nullptr),
|
|
|
|
m_ClampedFloatArgument(YYCC_U8("clamped-float"), YYCC::ArgParser::AbstractArgument::NO_SHORT_NAME, nullptr, nullptr, true, YYCC::Constraints::GetMinMaxRangeConstraint<float>(-1.0f, 1.0f)),
|
|
|
|
m_OptionContext(YYCC_U8("TestArgParser"), YYCC_U8("This is the testbench of argument parser."), {
|
|
|
|
&m_IntArgument, &m_FloatArgument, &m_StringArgument,
|
|
|
|
&m_BoolArgument, &m_ClampedFloatArgument
|
|
|
|
}) {}
|
|
|
|
~TestArgParser() {}
|
|
|
|
|
|
|
|
YYCC::ArgParser::NumberArgument<int32_t> m_IntArgument;
|
|
|
|
YYCC::ArgParser::NumberArgument<float> m_FloatArgument;
|
|
|
|
YYCC::ArgParser::StringArgument m_StringArgument;
|
|
|
|
|
|
|
|
YYCC::ArgParser::SwitchArgument m_BoolArgument;
|
|
|
|
YYCC::ArgParser::NumberArgument<float> m_ClampedFloatArgument;
|
|
|
|
|
|
|
|
YYCC::ArgParser::OptionContext m_OptionContext;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Initialize argument parser.
|
|
|
|
TestArgParser test;
|
|
|
|
// Get argument list for parsing from standard C main function.
|
|
|
|
auto al = YYCC::ArgParser::ArgumentList::CreateFromStd(argc, argv);
|
|
|
|
// Start parsing
|
|
|
|
test.Parse(al);
|
|
|
|
// Get captured string argument
|
|
|
|
if (test.m_StringArgument.IsCaptured())
|
|
|
|
auto val = test.m_StringArgument.Get();
|
|
|
|
\endcode
|
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
These code can resolve following command line:
|
2024-07-30 22:13:59 +08:00
|
|
|
|
|
|
|
\code{.sh}
|
|
|
|
exec -i 114514 -f 2.0 --string fuck -b --clamped-float 0.5
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
For convenience, we define following terms used in this article.
|
|
|
|
|
|
|
|
\li Every items in command line: Argument.
|
|
|
|
\li \c -i, \c --clamped-float: \b Switch / \b Option. the argument starts with dash or double dash.
|
|
|
|
\li \c 114514: \b Value. the value of switch.
|
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
\section arg_parser__argument Argument
|
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
Argument is the leaf of argument parser.
|
|
|
|
It has the same position as setting in universal config manager.
|
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
\subsection arg_parser__argument__presets Argument Presets
|
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
Like setting in universal config manager,
|
|
|
|
we also provide various common used argument presets.
|
|
|
|
Current'y we support following argument presets:
|
|
|
|
|
|
|
|
\li NumberArgument: The argument storing arithmetic type (except \c bool) inside. Such as <TT>-i 114514</TT> in example.
|
|
|
|
\li StringArgument: The argument storing string inside. Such as <TT>--string fuck</TT> in example.
|
|
|
|
\li SwitchArgument: The argument storing nothing. It is just a simple switch. Such as <TT>-b</TT> in example.
|
|
|
|
|
|
|
|
When constructing these argument,
|
|
|
|
you need provide one from long name or short name, or both of them.
|
|
|
|
Short name is the argument starting with dash and long name starts with double dash.
|
|
|
|
You don't need add dash or double dash prefix when providing these names.
|
|
|
|
Please note only ASCII characters, which can be displayed on screen, can be used in these names.
|
2024-07-30 17:31:38 +08:00
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
Optionally, you can provide description when constructing,
|
|
|
|
which will tell user how this switch does and more infomation about this switch.
|
|
|
|
And, you can add an example to tell user which value is valid.
|
2024-07-30 17:31:38 +08:00
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
Next, you can specify an argument to be optional.
|
|
|
|
Optional argument can be absent in command line.
|
|
|
|
Oppositely, non-optional argument must be presented in command line,
|
|
|
|
otherwise parser will return false to indicate an error.
|
|
|
|
For checking whether an optional argument is specified,
|
|
|
|
please call AbstractArgument::IsCaptured().
|
2024-07-30 17:31:38 +08:00
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
Last, you can optionally assign a constraint to it,
|
|
|
|
to help argument limit its value.
|
|
|
|
|
|
|
|
However SwitchArgument must be optional argument.
|
2024-07-30 17:31:38 +08:00
|
|
|
Because it is true if user specify it explicit it,
|
|
|
|
and will be false if user do not give this flag.
|
2024-07-31 12:08:30 +08:00
|
|
|
SwitchArgument doesn't have constraint features,
|
|
|
|
because it doesn't store any value inside.
|
|
|
|
Thus no need to limit this.
|
2024-07-30 17:31:38 +08:00
|
|
|
|
|
|
|
\subsection arg_parser__argument__custom Custom Argument
|
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
In most cases, the combination use of argument presets and constraints is enough.
|
|
|
|
However, if you still are urge to create your personal argument,
|
|
|
|
please inherit AbstractArgument and implement essential class functions.
|
|
|
|
For the class functions you need to implement,
|
|
|
|
please refer to our argument presets.
|
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
\section arg_parser__argument_list Argument List
|
|
|
|
|
2024-07-31 12:08:30 +08:00
|
|
|
Argument list is a struct used by parser for parsing.
|
|
|
|
It is a higher wrapper of a simple list containing argument items.
|
|
|
|
We provide 2 ways to get argument list.
|
|
|
|
|
|
|
|
\li ArgumentList::CreateFromStd: Create argument list from standard C main function parameters.
|
|
|
|
\li ArgumentList::CreateFromWin32: Create argument list from Win32 functions in Windows.
|
|
|
|
You should use this function in Windows instead of ArgumentList::CreateFromStd.
|
|
|
|
Because the command line passed in standard C main function has encoding issue in Windows.
|
|
|
|
Use this function you will fetch correct argument list especially command including non-ASCII characters.
|
|
|
|
|
|
|
|
Please note the first argument in given command line will be stripped.
|
|
|
|
Because in most cases it point to the executable self,
|
|
|
|
and should not be seen as the part of argument list.
|
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
\section arg_parser__option_context Option Context
|
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
Please note any unknow argument will let the parser return false.
|
|
|
|
This is different with other argument parsers.
|
|
|
|
In other common argument parsers,
|
2024-07-31 12:08:30 +08:00
|
|
|
they will collect all unknow argument as positional argument,
|
2024-07-30 22:13:59 +08:00
|
|
|
or just simply ignore them.
|
|
|
|
|
|
|
|
OptionContext also will not add \c -h or \c --help switch automatically.
|
|
|
|
This is also differnent with other parsers.
|
|
|
|
You should manually add it.
|
2024-07-31 12:08:30 +08:00
|
|
|
However, OptionContext provide a universal help print function, OptionContext::Help.
|
2024-07-30 22:13:59 +08:00
|
|
|
You can directly call it to output help text if you needed (fail to parse or user order help).
|
|
|
|
|
2024-07-30 17:31:38 +08:00
|
|
|
\section arg_parser__limitation Limitation
|
|
|
|
|
|
|
|
This universal argument parser is a tiny parser.
|
|
|
|
It only just fulfill my personal requirements.
|
|
|
|
So it only accepts limited command line syntax.
|
|
|
|
In following content I will tell you some syntaxes which this parser \b not accept.
|
|
|
|
|
|
|
|
\subsection arg_parser__limitation__flag_combination Flag Combination
|
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
\code{.sh}
|
2024-07-30 17:31:38 +08:00
|
|
|
exec -l -s -h
|
|
|
|
exec -lsh
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Parser accept first line but not accept the second line.
|
|
|
|
You must write these flags independently.
|
|
|
|
|
|
|
|
\subsection arg_parser__limitation__equal_symbol Equal Symbol
|
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
\code{.sh}
|
2024-07-30 17:31:38 +08:00
|
|
|
exec --value 114514
|
|
|
|
exec --value=114514
|
|
|
|
exec --value:114514
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Parser only accept first line command.
|
|
|
|
You can not use equal symbol or any other symbol to assign value for specified argument.
|
|
|
|
You must write value after the argument immediately please.
|
|
|
|
|
|
|
|
\subsection arg_parser__limitation__variable_argument Variable Argument
|
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
\code{.sh}
|
2024-07-30 17:31:38 +08:00
|
|
|
exec -DSOME_VARABLE=SOME_VALUE
|
|
|
|
exec -D SOME_VARIABLE=SOME_VALUE
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Parser only accept second line.
|
|
|
|
However you nned to write a custom argument or constraint to holding this value.
|
2024-07-30 10:35:41 +08:00
|
|
|
|
2024-07-30 22:13:59 +08:00
|
|
|
\subsection arg_parser__limitation__switch_dependency Switch Dependency
|
|
|
|
|
|
|
|
\code{.sh}
|
|
|
|
exec --action-a --action-b
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
For command line written above,
|
|
|
|
if you hope \c --action-a and \c --action-b is exclusive,
|
|
|
|
or \c --action-b only be valid if \c --action-a specified,
|
|
|
|
you should manually implement this.
|
|
|
|
Parser don't have such features to process this switch dependency.
|
|
|
|
|
|
|
|
The thing you need to do is set these switches are \b not optional.
|
|
|
|
And after parser do a success parsing,
|
|
|
|
manually calling AbstractArgument::IsCaptured to fetch whether corresponding switches are captured,
|
|
|
|
then do your personal dependency check.
|
|
|
|
|
|
|
|
*/
|
|
|
|
}
|