this doesn't work rn

v2
Brett 2025-02-27 01:53:22 -05:00
parent 17e6b507ea
commit 6935ae4785
3 changed files with 78 additions and 38 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20)
include(cmake/color.cmake)
set(BLT_VERSION 4.0.30)
set(BLT_VERSION 4.0.31)
set(BLT_TARGET BLT)

View File

@ -231,8 +231,11 @@ namespace blt::argparse
template <typename T>
auto ensure_is_string(T&& t)
{
if constexpr (std::is_arithmetic_v<meta::remove_cvref_t<T>> && !(std::is_same_v<T, char>
|| std::is_same_v<T, unsigned char> || std::is_same_v<T, signed char>))
using NO_REF = meta::remove_cvref_t<T>;
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));
else
return std::forward<T>(t);
@ -582,7 +585,9 @@ namespace blt::argparse
class argument_parser_t
{
friend argument_subparser_t;
explicit argument_parser_t(const argument_subparser_t* parent): m_parent(parent)
{
}
public:
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 = {},
@ -739,6 +744,7 @@ namespace blt::argparse
std::optional<std::string> m_description;
std::optional<std::string> m_epilogue;
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::unique_ptr<argument_builder_t>> m_argument_builders;
hashmap_t<std::string_view, argument_builder_t*> m_flag_arguments;
@ -748,6 +754,7 @@ namespace blt::argparse
class argument_subparser_t
{
friend argument_parser_t;
public:
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::string_view, Aliases>>...>,
"Arguments must be of type string_view, convertible to string_view or be string_view constructable");
m_parsers.emplace(name, argument_parser_t{});
((m_aliases[std::string_view{aliases}] = &m_parsers[name]), ...);
return &m_parsers[name];
m_parsers.emplace_back(new argument_parser_t{this});
m_aliases[name] = m_parsers.back().get();
((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
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;
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;
};
}

View File

@ -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>)
{
return std::string() + t;
std::string str;
str += t;
return str;
}
else
{
@ -400,7 +402,23 @@ namespace blt::argparse
{
help += "Subcommands:";
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())
@ -461,7 +479,7 @@ namespace blt::argparse
{
auto& [builder, flag_list] = pair;
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()))
str += " ";
@ -514,6 +532,17 @@ namespace blt::argparse
aligner += m_name.value_or("");
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;
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.");
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());
argument_parser_t* parser;
if (it == m_parsers.end())
{
const auto it2 = m_aliases.find(key.get_name());
if (it2 == m_aliases.end())
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)};
throw detail::subparse_error(key.get_argument(), to_vec(get_allowed_strings()));
const auto it = m_aliases.find(key.get_name());
if (it == m_aliases.end())
throw detail::subparse_error(key.get_argument(), to_vec(get_allowed_strings()));
it->second->m_name = m_parent->m_name;
m_last_parsed_parser = key.get_name();
return {key, it->second->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;
for (const auto& [key, value] : m_parsers)
{
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));
}
for (const auto& [key, value] : map)
vec.push_back(value);
return vec;
}