this doesn't work rn
parent
17e6b507ea
commit
6935ae4785
|
@ -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.30)
|
set(BLT_VERSION 4.0.31)
|
||||||
|
|
||||||
set(BLT_TARGET BLT)
|
set(BLT_TARGET BLT)
|
||||||
|
|
||||||
|
|
|
@ -231,8 +231,11 @@ namespace blt::argparse
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto ensure_is_string(T&& t)
|
auto ensure_is_string(T&& t)
|
||||||
{
|
{
|
||||||
if constexpr (std::is_arithmetic_v<meta::remove_cvref_t<T>> && !(std::is_same_v<T, char>
|
using NO_REF = meta::remove_cvref_t<T>;
|
||||||
|| std::is_same_v<T, unsigned char> || std::is_same_v<T, signed char>))
|
if constexpr (std::is_same_v<NO_REF, bool>)
|
||||||
|
return t ? "true" : "false";
|
||||||
|
else if constexpr (std::is_arithmetic_v<NO_REF> && !(std::is_same_v<NO_REF, char>
|
||||||
|
|| std::is_same_v<NO_REF, unsigned char> || std::is_same_v<NO_REF, signed char>))
|
||||||
return std::to_string(std::forward<T>(t));
|
return std::to_string(std::forward<T>(t));
|
||||||
else
|
else
|
||||||
return std::forward<T>(t);
|
return std::forward<T>(t);
|
||||||
|
@ -582,7 +585,9 @@ namespace blt::argparse
|
||||||
class argument_parser_t
|
class argument_parser_t
|
||||||
{
|
{
|
||||||
friend argument_subparser_t;
|
friend argument_subparser_t;
|
||||||
|
explicit argument_parser_t(const argument_subparser_t* parent): m_parent(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
explicit argument_parser_t(const std::optional<std::string_view> description = {}, const std::optional<std::string_view> epilogue = {},
|
explicit argument_parser_t(const std::optional<std::string_view> description = {}, const std::optional<std::string_view> epilogue = {},
|
||||||
const std::optional<std::string_view> version = {},
|
const std::optional<std::string_view> version = {},
|
||||||
|
@ -739,6 +744,7 @@ namespace blt::argparse
|
||||||
std::optional<std::string> m_description;
|
std::optional<std::string> m_description;
|
||||||
std::optional<std::string> m_epilogue;
|
std::optional<std::string> m_epilogue;
|
||||||
std::optional<std::string> m_version;
|
std::optional<std::string> m_version;
|
||||||
|
const argument_subparser_t* m_parent = nullptr;
|
||||||
std::vector<std::pair<std::string_view, argument_subparser_t>> m_subparsers;
|
std::vector<std::pair<std::string_view, argument_subparser_t>> m_subparsers;
|
||||||
std::vector<std::unique_ptr<argument_builder_t>> m_argument_builders;
|
std::vector<std::unique_ptr<argument_builder_t>> m_argument_builders;
|
||||||
hashmap_t<std::string_view, argument_builder_t*> m_flag_arguments;
|
hashmap_t<std::string_view, argument_builder_t*> m_flag_arguments;
|
||||||
|
@ -748,6 +754,7 @@ namespace blt::argparse
|
||||||
|
|
||||||
class argument_subparser_t
|
class argument_subparser_t
|
||||||
{
|
{
|
||||||
|
friend argument_parser_t;
|
||||||
public:
|
public:
|
||||||
explicit argument_subparser_t(const argument_parser_t& parent): m_parent(&parent)
|
explicit argument_subparser_t(const argument_parser_t& parent): m_parent(&parent)
|
||||||
{
|
{
|
||||||
|
@ -760,9 +767,16 @@ namespace blt::argparse
|
||||||
std::conjunction_v<std::disjunction<std::is_convertible<Aliases, std::string_view>, std::is_constructible<
|
std::conjunction_v<std::disjunction<std::is_convertible<Aliases, std::string_view>, std::is_constructible<
|
||||||
std::string_view, Aliases>>...>,
|
std::string_view, Aliases>>...>,
|
||||||
"Arguments must be of type string_view, convertible to string_view or be string_view constructable");
|
"Arguments must be of type string_view, convertible to string_view or be string_view constructable");
|
||||||
m_parsers.emplace(name, argument_parser_t{});
|
m_parsers.emplace_back(new argument_parser_t{this});
|
||||||
((m_aliases[std::string_view{aliases}] = &m_parsers[name]), ...);
|
m_aliases[name] = m_parsers.back().get();
|
||||||
return &m_parsers[name];
|
((m_aliases[std::string_view{aliases}] = m_parsers.back().get()), ...);
|
||||||
|
return m_parsers.back().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
argument_subparser_t* set_help(const std::optional<std::string>& help)
|
||||||
|
{
|
||||||
|
m_help = help;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -781,10 +795,15 @@ namespace blt::argparse
|
||||||
std::pair<argument_string_t, argument_storage_t> parse(argument_consumer_t& consumer); // NOLINT
|
std::pair<argument_string_t, argument_storage_t> parse(argument_consumer_t& consumer); // NOLINT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] std::vector<std::vector<std::string_view>> get_allowed_strings() const;
|
[[nodiscard]] hashmap_t<argument_parser_t*, std::vector<std::string_view>> get_allowed_strings() const;
|
||||||
|
|
||||||
|
// annoying compatability because im lazy
|
||||||
|
static std::vector<std::vector<std::string_view>> to_vec(const hashmap_t<argument_parser_t*, std::vector<std::string_view>>& map);
|
||||||
|
|
||||||
const argument_parser_t* m_parent;
|
const argument_parser_t* m_parent;
|
||||||
hashmap_t<std::string_view, argument_parser_t> m_parsers;
|
std::optional<std::string> m_last_parsed_parser; // bad hack
|
||||||
|
std::optional<std::string> m_help;
|
||||||
|
std::vector<std::unique_ptr<argument_parser_t>> m_parsers;
|
||||||
hashmap_t<std::string_view, argument_parser_t*> m_aliases;
|
hashmap_t<std::string_view, argument_parser_t*> m_aliases;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,9 @@ namespace blt::argparse
|
||||||
}
|
}
|
||||||
else if constexpr (std::is_same_v<T, char> || std::is_same_v<T, unsigned char> || std::is_same_v<T, signed char>)
|
else if constexpr (std::is_same_v<T, char> || std::is_same_v<T, unsigned char> || std::is_same_v<T, signed char>)
|
||||||
{
|
{
|
||||||
return std::string() + t;
|
std::string str;
|
||||||
|
str += t;
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -400,7 +402,23 @@ namespace blt::argparse
|
||||||
{
|
{
|
||||||
help += "Subcommands:";
|
help += "Subcommands:";
|
||||||
help.newline();
|
help.newline();
|
||||||
|
for (const auto& [key, value] : m_subparsers)
|
||||||
|
{
|
||||||
|
help += '\t';
|
||||||
|
auto map = value.get_allowed_strings();
|
||||||
|
// TODO: make an unzip?
|
||||||
|
for (const auto& [parser, strings] : map)
|
||||||
|
{
|
||||||
|
for (const auto& [i, str] : enumerate(strings))
|
||||||
|
{
|
||||||
|
help += str;
|
||||||
|
if (i != strings.size() - 1)
|
||||||
|
help += ", ";
|
||||||
|
}
|
||||||
|
help += parser.he
|
||||||
|
help.newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_flag_arguments.empty())
|
if (!m_flag_arguments.empty())
|
||||||
|
@ -461,7 +479,7 @@ namespace blt::argparse
|
||||||
{
|
{
|
||||||
auto& [builder, flag_list] = pair;
|
auto& [builder, flag_list] = pair;
|
||||||
str += builder->m_help.value_or("");
|
str += builder->m_help.value_or("");
|
||||||
if (builder->m_default_value)
|
if (builder->m_default_value && !(builder->m_action == action_t::STORE_TRUE || builder->m_action == action_t::STORE_FALSE))
|
||||||
{
|
{
|
||||||
if (!std::isblank(str.str().back()))
|
if (!std::isblank(str.str().back()))
|
||||||
str += " ";
|
str += " ";
|
||||||
|
@ -514,6 +532,17 @@ namespace blt::argparse
|
||||||
aligner += m_name.value_or("");
|
aligner += m_name.value_or("");
|
||||||
aligner += ' ';
|
aligner += ' ';
|
||||||
|
|
||||||
|
auto parent = m_parent;
|
||||||
|
while (parent != nullptr)
|
||||||
|
{
|
||||||
|
if (!parent->m_last_parsed_parser)
|
||||||
|
throw detail::missing_value_error(
|
||||||
|
"Error: Help called on subparser but unable to find parser chain. This condition should be impossible.");
|
||||||
|
aligner += parent->m_last_parsed_parser.value();
|
||||||
|
aligner += ' ';
|
||||||
|
parent = parent->m_parent->m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
hashmap_t<std::string, std::vector<std::string>> singleFlags;
|
hashmap_t<std::string, std::vector<std::string>> singleFlags;
|
||||||
std::vector<std::pair<argument_string_t, argument_builder_t*>> compoundFlags;
|
std::vector<std::pair<argument_string_t, argument_builder_t*>> compoundFlags;
|
||||||
|
|
||||||
|
@ -960,36 +989,28 @@ namespace blt::argparse
|
||||||
throw detail::missing_argument_error("Subparser requires an argument.");
|
throw detail::missing_argument_error("Subparser requires an argument.");
|
||||||
const auto key = consumer.consume();
|
const auto key = consumer.consume();
|
||||||
if (key.is_flag())
|
if (key.is_flag())
|
||||||
throw detail::subparse_error(key.get_argument(), get_allowed_strings());
|
throw detail::subparse_error(key.get_argument(), to_vec(get_allowed_strings()));
|
||||||
const auto it = m_parsers.find(key.get_name());
|
const auto it = m_aliases.find(key.get_name());
|
||||||
argument_parser_t* parser;
|
if (it == m_aliases.end())
|
||||||
if (it == m_parsers.end())
|
throw detail::subparse_error(key.get_argument(), to_vec(get_allowed_strings()));
|
||||||
{
|
it->second->m_name = m_parent->m_name;
|
||||||
const auto it2 = m_aliases.find(key.get_name());
|
m_last_parsed_parser = key.get_name();
|
||||||
if (it2 == m_aliases.end())
|
return {key, it->second->parse(consumer)};
|
||||||
throw detail::subparse_error(key.get_argument(), get_allowed_strings());
|
|
||||||
parser = it2->second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
parser = &it->second;
|
|
||||||
parser->m_name = m_parent->m_name;
|
|
||||||
return {key, parser->parse(consumer)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<std::string_view>> argument_subparser_t::get_allowed_strings() const
|
hashmap_t<argument_parser_t*, std::vector<std::string_view>> argument_subparser_t::get_allowed_strings() const
|
||||||
|
{
|
||||||
|
hashmap_t<argument_parser_t*, std::vector<std::string_view>> map;
|
||||||
|
for (const auto& [key, value] : m_aliases)
|
||||||
|
map[value].emplace_back(key);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<std::string_view>> argument_subparser_t::to_vec(const hashmap_t<argument_parser_t*, std::vector<std::string_view>>& map)
|
||||||
{
|
{
|
||||||
std::vector<std::vector<std::string_view>> vec;
|
std::vector<std::vector<std::string_view>> vec;
|
||||||
for (const auto& [key, value] : m_parsers)
|
for (const auto& [key, value] : map)
|
||||||
{
|
vec.push_back(value);
|
||||||
std::vector<std::string_view> aliases;
|
|
||||||
aliases.push_back(key);
|
|
||||||
for (const auto& [alias, parser] : m_aliases)
|
|
||||||
{
|
|
||||||
if (parser == &value)
|
|
||||||
aliases.push_back(alias);
|
|
||||||
}
|
|
||||||
vec.emplace_back(std::move(aliases));
|
|
||||||
}
|
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue