working on subparsers
parent
44a57e5ec2
commit
89d95dfec4
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
include(cmake/color.cmake)
|
include(cmake/color.cmake)
|
||||||
set(BLT_VERSION 4.0.4)
|
set(BLT_VERSION 4.0.5)
|
||||||
|
|
||||||
set(BLT_TARGET BLT)
|
set(BLT_TARGET BLT)
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,49 @@ namespace blt::argparse
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class subparse_error final : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit subparse_error(const std::string_view found_string, std::vector<std::string_view> allowed_strings): m_found_string(found_string),
|
||||||
|
m_allowed_strings(std::move(allowed_strings))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<std::string_view>& get_allowed_strings() const
|
||||||
|
{
|
||||||
|
return m_allowed_strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string_view get_found_string() const
|
||||||
|
{
|
||||||
|
return m_found_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string error_string() const
|
||||||
|
{
|
||||||
|
std::string message = "Subparser Error: ";
|
||||||
|
message += m_found_string;
|
||||||
|
message += " is not a valid command. Allowed commands are: {";
|
||||||
|
for (const auto [i, allowed_string] : enumerate(m_allowed_strings))
|
||||||
|
{
|
||||||
|
message += allowed_string;
|
||||||
|
if (i != m_allowed_strings.size() - 1)
|
||||||
|
message += ' ';
|
||||||
|
}
|
||||||
|
message += "}";
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const char* what() const override
|
||||||
|
{
|
||||||
|
return "Please use error_string() method instead of what(). This exception should *always* be caught!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string_view m_found_string;
|
||||||
|
std::vector<std::string_view> m_allowed_strings;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
struct arg_data_helper_t
|
struct arg_data_helper_t
|
||||||
{
|
{
|
||||||
|
@ -207,6 +250,8 @@ namespace blt::argparse
|
||||||
|
|
||||||
class argument_parser_t
|
class argument_parser_t
|
||||||
{
|
{
|
||||||
|
friend argument_subparser_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit argument_parser_t(const std::optional<std::string_view> name = {}, const std::optional<std::string_view> usage = {}):
|
explicit argument_parser_t(const std::optional<std::string_view> name = {}, const std::optional<std::string_view> usage = {}):
|
||||||
m_name(name), m_usage(usage)
|
m_name(name), m_usage(usage)
|
||||||
|
@ -219,6 +264,10 @@ namespace blt::argparse
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse(argument_consumer_t& consumer) // NOLINT
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<std::string> m_name;
|
std::optional<std::string> m_name;
|
||||||
std::optional<std::string> m_usage;
|
std::optional<std::string> m_usage;
|
||||||
|
@ -229,17 +278,51 @@ namespace blt::argparse
|
||||||
class argument_subparser_t
|
class argument_subparser_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit argument_subparser_t(const argument_parser_t& parent): m_parent(&parent)
|
||||||
argument_parser_t add_subparser(const std::string_view dest)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
argument_parser_t add_subparser(std::string& dest)
|
argument_parser_t& add_parser(const std::string_view name)
|
||||||
{
|
{
|
||||||
|
m_parsers.emplace(name);
|
||||||
|
return m_parsers[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the next argument using the provided argument consumer.
|
||||||
|
*
|
||||||
|
* This function uses an argument consumer to extract and process the next argument.
|
||||||
|
* If the argument is a flag or if it cannot be matched against the available parsers,
|
||||||
|
* an exception is thrown.
|
||||||
|
*
|
||||||
|
* @param consumer Reference to an argument_consumer_t object, which handles argument parsing.
|
||||||
|
* The consumer provides the next argument to be parsed.
|
||||||
|
*
|
||||||
|
* @throws detail::subparse_error If the argument is a flag or does not match any known parser.
|
||||||
|
*/
|
||||||
|
void parse(argument_consumer_t& consumer) // NOLINT
|
||||||
|
{
|
||||||
|
const auto key = consumer.consume();
|
||||||
|
if (key.is_flag())
|
||||||
|
throw detail::subparse_error(key.get_argument(), get_allowed_strings());
|
||||||
|
const auto it = m_parsers.find(key.get_name());
|
||||||
|
if (it == m_parsers.end())
|
||||||
|
throw detail::subparse_error(key.get_argument(), get_allowed_strings());
|
||||||
|
it->second.parse(consumer);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] std::vector<std::string_view> get_allowed_strings() const
|
||||||
|
{
|
||||||
|
std::vector<std::string_view> vec;
|
||||||
|
for (const auto& [key, value] : m_parsers)
|
||||||
|
vec.push_back(key);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
const argument_parser_t* m_parent;
|
||||||
|
hashmap_t<std::string_view, argument_parser_t> m_parsers;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue