namespace YYCC::ArgParser { /** \page arg_parser Universal Argument Parser YYCC::ArgParser provides an universal way to parsing command line arguments. 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. There is an example about how to use universal argument parser. In following content, we will describe it in detail. \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(-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 m_IntArgument; YYCC::ArgParser::NumberArgument m_FloatArgument; YYCC::ArgParser::StringArgument m_StringArgument; YYCC::ArgParser::SwitchArgument m_BoolArgument; YYCC::ArgParser::NumberArgument 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 These code can resolve following command line: \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. \section arg_parser__argument Argument Argument is the leaf of argument parser. It has the same position as setting in universal config manager. \subsection arg_parser__argument__presets Argument Presets 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 -i 114514 in example. \li StringArgument: The argument storing string inside. Such as --string fuck in example. \li SwitchArgument: The argument storing nothing. It is just a simple switch. Such as -b 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. 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. 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(). Last, you can optionally assign a constraint to it, to help argument limit its value. However SwitchArgument must be optional argument. Because it is true if user specify it explicit it, and will be false if user do not give this flag. SwitchArgument doesn't have constraint features, because it doesn't store any value inside. Thus no need to limit this. \subsection arg_parser__argument__custom Custom Argument 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. \section arg_parser__argument_list Argument List 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. \section arg_parser__option_context Option Context Please note any unknow argument will let the parser return false. This is different with other argument parsers. In other common argument parsers, they will collect all unknow argument as positional argument, 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. However, OptionContext provide a universal help print function, OptionContext::Help. You can directly call it to output help text if you needed (fail to parse or user order help). \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 \code{.sh} 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 \code{.sh} 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 \code{.sh} 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. \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. */ }