1#ifndef KOUTIL_ARGPARSER_PARSER_H
2#define KOUTIL_ARGPARSER_PARSER_H
33template <
typename T,
typename Ctx>
34concept parser =
requires(Ctx& ctx,
const Arg& arg, std::string_view value,
const SubcommandBase& cmd) {
35 { T::parse_argument(ctx, value) } -> std::same_as<ParseResult>;
36 { T::parse_option_flag(ctx, arg) } -> std::same_as<ParseResult>;
37 { T::parse_option_value(ctx, arg, value) } -> std::same_as<ParseResult>;
38 { T::parse_command(ctx, cmd) } -> std::same_as<ParseResult>;
49template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
class Parser {
51 constexpr Parser(Ctx& ctx, Args&& args, Cmds&& commands)
56 constexpr Parser(Ctx& ctx,
const Args& args,
const Cmds& commands)
118template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
119constexpr auto make_parser(Ctx& ctx, Args&& args, Cmds&& commands) {
121 ctx, std::forward<
decltype(args)>(args), std::forward<
decltype(commands)>(commands)
139template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
142 ctx, std::forward<
decltype(args)>(args), std::forward<
decltype(commands)>(commands)
147template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
149 m_values = std::span(argv + 1, argc - 1);
151 for (; m_offset < m_values.size(); ++m_offset) {
152 std::string_view arg(m_values[m_offset]);
155 if (arg.starts_with(
"--")) {
156 result = parse_long_opt(arg.substr(2));
157 }
else if (arg.starts_with(
'-')) {
158 result = parse_short_opt(arg.substr(1));
160 result = parse_command_or_argument(arg);
171template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
178 while (!opt.empty()) {
179 const auto* arg_res = m_current_args->find_short(opt.front());
180 if (arg_res ==
nullptr) {
184 const auto& arg = *arg_res;
185 auto result = UParser::parse_option_flag(m_ctx, arg);
196template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
201 for (; m_offset < m_values.size(); ++m_offset) {
202 auto result = UParser::parse_argument(m_ctx, m_values[m_offset]);
210 auto eql_it = opt.find(
'=', 1);
211 std::string_view option = opt.substr(0, eql_it);
212 std::string_view value;
214 const auto* arg_res = m_current_args->find_long(option);
215 if (arg_res ==
nullptr) {
219 const auto& arg = *arg_res;
224 result = UParser::parse_option_flag(m_ctx, arg);
227 if (eql_it != std::string_view::npos) {
228 value = opt.substr(eql_it + 1);
229 }
else if (m_offset + 1 >= m_values.size()) {
232 value = m_values[++m_offset];
235 result = UParser::parse_option_value(m_ctx, arg, value);
247template <
typename Ctx, parser<Ctx> UParser, are_arguments Args, are_commands Cmds>
251 }
else if (m_current_cms->size() == 0) {
252 return UParser::parse_argument(m_ctx, opt);
255 const auto* cmd = m_current_cms->find(opt);
256 if (cmd ==
nullptr) {
260 m_current_args = &cmd->get_args();
261 m_current_cms = &cmd->get_cmds();
263 return UParser::parse_command(m_ctx, *cmd);
Base class for commands.
Definition subcommand.h:67
Template class representing a parser.
Definition parser.h:49
std::span< const char * > m_values
Definition parser.h:78
ParseResult parse(std::size_t argc, const char **argv)
Parses the command-line arguments.
Definition parser.h:148
ParseResult parse_short_opt(std::string_view opt)
Parses a short option.
Definition parser.h:172
constexpr Parser(Ctx &ctx, Args &&args, Cmds &&commands)
Definition parser.h:51
ArgumentsBase const * m_current_args
Definition parser.h:74
Args m_args
Definition parser.h:71
ParseResult parse_long_opt(std::string_view opt)
Parses a long option.
Definition parser.h:197
CommandsBase const * m_current_cms
Definition parser.h:75
ParseResult parse_command_or_argument(std::string_view opt)
Parses a command or argument.
Definition parser.h:248
Ctx & m_ctx
Definition parser.h:77
Cmds m_subcommands
Definition parser.h:72
constexpr Parser(Ctx &ctx, const Args &args, const Cmds &commands)
Definition parser.h:56
std::size_t m_offset
Definition parser.h:79
Concept to check if a type is a parser.
Definition parser.h:34
constexpr auto make_parser(Ctx &ctx, Args &&args, Cmds &&commands)
Creates a Parser object.
Definition parser.h:119
ParseResult
Enum class representing possible parse results.
Definition parser.h:18
ParseResult process_args(std::size_t argc, const char **argv, Ctx &ctx, Args &&args, Cmds &&commands)
Processes the command-line arguments.
Definition parser.h:140
@ OPTION_FLAG
Definition arg.h:31
@ OPTION_VALUE
Definition arg.h:32