begin testing, flag work. something is really broken though
parent
e0d36269bf
commit
56611d5aef
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.20)
|
||||
include(cmake/color.cmake)
|
||||
set(BLT_VERSION 4.0.14)
|
||||
set(BLT_VERSION 4.0.15)
|
||||
|
||||
set(BLT_TARGET BLT)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef BLT_PARSE_ARGPARSE_V2_H
|
||||
#define BLT_PARSE_ARGPARSE_V2_H
|
||||
|
||||
#include <complex>
|
||||
#include <blt/std/types.h>
|
||||
#include <blt/std/hashmap.h>
|
||||
#include <blt/fs/path_helper.h>
|
||||
|
@ -89,6 +90,30 @@ namespace blt::argparse
|
|||
}
|
||||
};
|
||||
|
||||
class missing_value_error final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit missing_value_error(const std::string& message): std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class type_error final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit type_error(const std::string& message): std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class unexpected_argument_error final : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit unexpected_argument_error(const std::string& message): std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class subparse_error final : public std::exception
|
||||
{
|
||||
public:
|
||||
|
@ -120,13 +145,6 @@ namespace blt::argparse
|
|||
std::vector<std::vector<std::string_view>> m_allowed_strings;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr auto invalid_option_lambda = [](const T)
|
||||
{
|
||||
std::cerr << "Invalid type - expected list type, found '" << blt::type_string<T>() << "'" << std::endl;
|
||||
std::exit(1);
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct arg_data_helper_t
|
||||
{
|
||||
|
@ -134,6 +152,9 @@ namespace blt::argparse
|
|||
using arg_t = meta::arg_helper<Args...>;
|
||||
using arg_vec_t = meta::arg_helper<std::vector<Args>...>;
|
||||
|
||||
template <typename T>
|
||||
constexpr static bool is_type_stored_v = std::disjunction_v<std::is_same<T, Args>...>;
|
||||
|
||||
template <typename DefaultPrimitiveAction, typename DefaultListAction>
|
||||
static auto make_visitor(const DefaultPrimitiveAction& primitive_action, const DefaultListAction& list_action)
|
||||
{
|
||||
|
@ -196,14 +217,13 @@ namespace blt::argparse
|
|||
class argument_string_t
|
||||
{
|
||||
public:
|
||||
explicit argument_string_t(const char* input, const hashset_t<char>& allowed_flag_prefix): m_argument(input),
|
||||
m_allowed_flag_prefix(&allowed_flag_prefix)
|
||||
explicit argument_string_t(const std::string_view input, const hashset_t<char>& allowed_flag_prefix): m_argument(input),
|
||||
m_allowed_flag_prefix(&allowed_flag_prefix)
|
||||
{
|
||||
if (input == nullptr)
|
||||
throw detail::bad_flag("Argument cannot be null!");
|
||||
process_argument();
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] std::string_view get_flag() const
|
||||
{
|
||||
return m_flag_section;
|
||||
|
@ -325,14 +345,14 @@ namespace blt::argparse
|
|||
|
||||
public:
|
||||
template <typename T>
|
||||
const T& get(const std::string_view key)
|
||||
[[nodiscard]] const T& get(const std::string_view key) const
|
||||
{
|
||||
return std::get<T>(m_data[key]);
|
||||
return std::get<T>(m_data.at(key));
|
||||
}
|
||||
|
||||
std::string_view get(const std::string_view key)
|
||||
[[nodiscard]] std::string_view get(const std::string_view key) const
|
||||
{
|
||||
return std::get<std::string_view>(m_data[key]);
|
||||
return std::get<std::string_view>(m_data.at(key));
|
||||
}
|
||||
|
||||
bool contains(const std::string_view key)
|
||||
|
@ -340,6 +360,11 @@ namespace blt::argparse
|
|||
return m_data.find(key) != m_data.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t size() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
private:
|
||||
void add(const argument_storage_t& values)
|
||||
{
|
||||
|
@ -370,6 +395,7 @@ namespace blt::argparse
|
|||
template <typename T>
|
||||
argument_builder_t& as_type()
|
||||
{
|
||||
static_assert(detail::arg_data_helper_t<T>::template is_type_stored_v<T>, "Type is not valid to be stored/converted as an argument");
|
||||
m_dest_func = [](const std::string_view dest, argument_storage_t& storage, std::string_view value)
|
||||
{
|
||||
storage.m_data.insert({dest, detail::arg_string_converter_t<T>::convert(value)});
|
||||
|
@ -381,9 +407,8 @@ namespace blt::argparse
|
|||
auto& data = storage.m_data[dest];
|
||||
if (!std::holds_alternative<std::vector<T>>(data))
|
||||
{
|
||||
std::cerr << "Invalid type conversion. Trying to add type " << blt::type_string<T>() <<
|
||||
" but this does not match existing type index '" << data.index() << "'!" << std::endl;
|
||||
std::exit(1);
|
||||
throw detail::type_error("Invalid type conversion. Trying to add type " + blt::type_string<T>() +
|
||||
" but this does not match existing type index '" + std::to_string(data.index()) + "'!");
|
||||
}
|
||||
std::vector<T>& converted_values = std::get<std::vector<T>>(data);
|
||||
for (const auto& value : values)
|
||||
|
@ -400,6 +425,75 @@ namespace blt::argparse
|
|||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_action(const action_t action)
|
||||
{
|
||||
m_action = action;
|
||||
switch (m_action)
|
||||
{
|
||||
case action_t::STORE_TRUE:
|
||||
set_nargs(0);
|
||||
as_type<bool>();
|
||||
set_default(false);
|
||||
break;
|
||||
case action_t::STORE_FALSE:
|
||||
set_nargs(0);
|
||||
as_type<bool>();
|
||||
set_default(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_required(const bool required)
|
||||
{
|
||||
m_required = required;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_nargs(const nargs_v nargs)
|
||||
{
|
||||
m_nargs = nargs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_metavar(const std::string& metavar)
|
||||
{
|
||||
m_metavar = metavar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_help(const std::string& help)
|
||||
{
|
||||
m_help = help;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_choices(const std::vector<std::string>& choices)
|
||||
{
|
||||
m_choices = choices;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_default(const detail::arg_data_t& default_value)
|
||||
{
|
||||
m_default_value = default_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_const(const detail::arg_data_t& const_value)
|
||||
{
|
||||
m_const_value = const_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
argument_builder_t& set_dest(const std::string& dest)
|
||||
{
|
||||
m_dest = dest;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
action_t m_action = action_t::STORE;
|
||||
bool m_required = false; // do we require this argument to be provided as an argument?
|
||||
|
@ -436,7 +530,7 @@ namespace blt::argparse
|
|||
"Arguments must be of type string_view, convertible to string_view or be string_view constructable");
|
||||
m_argument_builders.emplace_back();
|
||||
m_flag_arguments.insert({arg, &m_argument_builders.back()});
|
||||
((m_flag_arguments[std::string_view{aliases}] = &m_argument_builders.back()), ...);
|
||||
(m_flag_arguments.insert({std::string_view{aliases}, &m_argument_builders.back()}), ...);
|
||||
return m_argument_builders.back();
|
||||
}
|
||||
|
||||
|
@ -451,6 +545,24 @@ namespace blt::argparse
|
|||
|
||||
argument_storage_t parse(argument_consumer_t& consumer); // NOLINT
|
||||
|
||||
argument_storage_t parse(const std::vector<std::string>& args)
|
||||
{
|
||||
std::vector<argument_string_t> arg_strings;
|
||||
for (const auto& arg : args)
|
||||
arg_strings.emplace_back(arg, allowed_flag_prefixes);
|
||||
argument_consumer_t consumer{arg_strings};
|
||||
return parse(consumer);
|
||||
}
|
||||
|
||||
argument_storage_t parse(const int argc, const char** argv)
|
||||
{
|
||||
std::vector<argument_string_t> arg_strings;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
arg_strings.emplace_back(argv[i], allowed_flag_prefixes);
|
||||
argument_consumer_t consumer{arg_strings};
|
||||
return parse(consumer);
|
||||
}
|
||||
|
||||
void print_help();
|
||||
|
||||
void print_usage();
|
||||
|
@ -511,6 +623,7 @@ namespace blt::argparse
|
|||
std::vector<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_positional_arguments;
|
||||
hashset_t<char> allowed_flag_prefixes = {'-', '+', '/'};
|
||||
};
|
||||
|
||||
class argument_subparser_t
|
||||
|
|
|
@ -19,9 +19,49 @@
|
|||
#include <blt/parse/argparse_v2.h>
|
||||
#include <blt/std/assert.h>
|
||||
#include <blt/meta/type_traits.h>
|
||||
#include <blt/std/logging.h>
|
||||
|
||||
namespace blt::argparse
|
||||
{
|
||||
template <typename T>
|
||||
size_t get_const_char_size(const T& t)
|
||||
{
|
||||
if constexpr (std::is_convertible_v<T, const char*>)
|
||||
{
|
||||
return std::char_traits<char>::length(t);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, char> || std::is_same_v<T, unsigned char> || std::is_same_v<T, signed char>)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::string_view> || std::is_same_v<T, std::string>)
|
||||
{
|
||||
return t.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto ensure_is_string(T&& t)
|
||||
{
|
||||
if constexpr (std::is_arithmetic_v<meta::remove_cvref_t<T>>)
|
||||
return std::to_string(std::forward<T>(t));
|
||||
else
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
template <typename... Strings>
|
||||
std::string make_string(Strings&&... strings)
|
||||
{
|
||||
std::string out;
|
||||
out.reserve((get_const_char_size(strings) + ...));
|
||||
((out += ensure_is_string(std::forward<Strings>(strings))), ...);
|
||||
return out;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Unit Tests for class argument_string_t
|
||||
|
@ -134,9 +174,113 @@ namespace blt::argparse
|
|||
test_argument_string_t_double_plus(prefixes);
|
||||
}
|
||||
|
||||
void test_argparse_empty()
|
||||
{
|
||||
std::vector<std::string> const argv;
|
||||
argument_parser_t parser;
|
||||
const auto args = parser.parse(argv);
|
||||
BLT_ASSERT(args.size() == 0 && "Empty argparse should have no args on output");
|
||||
}
|
||||
|
||||
void test_single_flag_prefixes()
|
||||
{
|
||||
argument_parser_t parser;
|
||||
parser.add_flag("-a").set_action(action_t::STORE_TRUE);
|
||||
parser.add_flag("+b").set_action(action_t::STORE_FALSE);
|
||||
parser.add_flag("/c").as_type<int>().set_action(action_t::STORE);
|
||||
|
||||
const std::vector<std::string> args = {"-a", "+b", "/c", "42"};
|
||||
const auto parsed_args = parser.parse(args);
|
||||
|
||||
BLT_ASSERT(parsed_args.get<bool>("-a") == true && "Flag '-a' should store `true`");
|
||||
BLT_ASSERT(parsed_args.get<bool>("+b") == false && "Flag '+b' should store `false`");
|
||||
BLT_ASSERT(parsed_args.get<int>("/c") == 42 && "Flag '/c' should store the value 42");
|
||||
}
|
||||
|
||||
// Test: Invalid flag prefixes
|
||||
void test_invalid_flag_prefixes()
|
||||
{
|
||||
argument_parser_t parser;
|
||||
parser.add_flag("-a");
|
||||
parser.add_flag("+b");
|
||||
parser.add_flag("/c");
|
||||
|
||||
const std::vector<std::string> args = {"!d", "-a"};
|
||||
try
|
||||
{
|
||||
parser.parse(args);
|
||||
BLT_ASSERT(false && "Parsing should fail with invalid flag prefix '!'");
|
||||
}
|
||||
catch (const bad_flag& _)
|
||||
{
|
||||
BLT_ASSERT(true && "Correctly threw on bad flag prefix");
|
||||
}
|
||||
}
|
||||
|
||||
void test_compound_flags()
|
||||
{
|
||||
argument_parser_t parser;
|
||||
parser.add_flag("-v").as_type<int>().set_action(action_t::COUNT);
|
||||
|
||||
const std::vector<std::string> args = {"-vvv"};
|
||||
const auto parsed_args = parser.parse(args);
|
||||
|
||||
BLT_ASSERT(parsed_args.get<int>("-v") == 3 && "Flag '-v' should count occurrences in compound form");
|
||||
}
|
||||
|
||||
void test_combination_of_valid_and_invalid_flags()
|
||||
{
|
||||
using namespace argparse;
|
||||
|
||||
argument_parser_t parser;
|
||||
parser.add_flag("-x").as_type<int>();
|
||||
parser.add_flag("/y").as_type<std::string_view>();
|
||||
|
||||
const std::vector<std::string> args = {"-x", "10", "!z", "/y", "value"};
|
||||
try
|
||||
{
|
||||
parser.parse(args);
|
||||
BLT_ASSERT(false && "Parsing should fail due to invalid flag '!z'");
|
||||
}
|
||||
catch (const bad_flag& _)
|
||||
{
|
||||
BLT_ASSERT(true && "Correctly threw an exception for invalid flag");
|
||||
}
|
||||
}
|
||||
|
||||
void test_flags_with_different_actions()
|
||||
{
|
||||
using namespace argparse;
|
||||
|
||||
argument_parser_t parser;
|
||||
parser.add_flag("-k").as_type<int>().set_action(action_t::STORE); // STORE action
|
||||
parser.add_flag("-t").as_type<int>().set_action(action_t::STORE_CONST).set_const(999); // STORE_CONST action
|
||||
parser.add_flag("-f").set_action(action_t::STORE_FALSE); // STORE_FALSE action
|
||||
parser.add_flag("-c").set_action(action_t::STORE_TRUE); // STORE_TRUE action
|
||||
|
||||
const std::vector<std::string> args = {"-k", "100", "-t", "-f", "-c"};
|
||||
const auto parsed_args = parser.parse(args);
|
||||
|
||||
BLT_ASSERT(parsed_args.get<int>("-k") == 100 && "Flag '-k' should store 100");
|
||||
BLT_ASSERT(parsed_args.get<int>("-t") == 999 && "Flag '-t' should store a const value of 999");
|
||||
BLT_ASSERT(parsed_args.get<bool>("-f") == false && "Flag '-f' should store `false`");
|
||||
BLT_ASSERT(parsed_args.get<bool>("-c") == true && "Flag '-c' should store `true`");
|
||||
}
|
||||
|
||||
void run_argparse_flag_tests()
|
||||
{
|
||||
test_single_flag_prefixes();
|
||||
test_invalid_flag_prefixes();
|
||||
test_compound_flags();
|
||||
test_combination_of_valid_and_invalid_flags();
|
||||
test_flags_with_different_actions();
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
run_all_tests_argument_string_t();
|
||||
test_argparse_empty();
|
||||
run_argparse_flag_tests();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string subparse_error::error_string() const
|
||||
|
@ -183,10 +327,7 @@ namespace blt::argparse
|
|||
const auto key = consumer.consume();
|
||||
const auto flag = m_flag_arguments.find(key.get_argument());
|
||||
if (flag == m_flag_arguments.end())
|
||||
{
|
||||
std::cerr << "Error: Unknown flag: " << key.get_argument() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
throw detail::bad_flag(make_string("Error: Unknown flag: ", key.get_argument()));
|
||||
found_flags.insert(key.get_argument());
|
||||
parse_flag(parsed_args, consumer, key.get_argument());
|
||||
}
|
||||
|
@ -255,7 +396,7 @@ namespace blt::argparse
|
|||
|
||||
void argument_parser_t::parse_flag(argument_storage_t& parsed_args, argument_consumer_t& consumer, const std::string_view arg)
|
||||
{
|
||||
auto& flag = m_flag_arguments[arg];
|
||||
auto flag = m_flag_arguments[arg];
|
||||
auto dest = flag->m_dest.value_or(std::string{arg});
|
||||
std::visit(lambda_visitor{
|
||||
[&parsed_args, &consumer, &dest, &flag, arg](const nargs_t arg_enum)
|
||||
|
@ -273,7 +414,8 @@ namespace blt::argparse
|
|||
break;
|
||||
case nargs_t::ALL_AT_LEAST_ONE:
|
||||
if (!consumer.can_consume())
|
||||
std::cerr << "Error expected at least one argument to be consumed by '" << arg << '\'' << std::endl;
|
||||
throw detail::missing_argument_error(
|
||||
make_string("Error expected at least one argument to be consumed by '", arg, '\''));
|
||||
[[fallthrough]];
|
||||
case nargs_t::ALL:
|
||||
std::vector<std::string_view> args;
|
||||
|
@ -290,68 +432,56 @@ namespace blt::argparse
|
|||
{
|
||||
if (!consumer.can_consume())
|
||||
{
|
||||
std::cerr << "Error expected " << argc << " arguments to be consumed by '" << arg << "' but found " << i <<
|
||||
std::endl;
|
||||
std::exit(1);
|
||||
throw detail::missing_argument_error(
|
||||
make_string("Expected ", argc, " arguments to be consumed by '", arg, "' but found ", i));
|
||||
}
|
||||
if (consumer.peek().is_flag())
|
||||
{
|
||||
std::cerr << "Error expected " << argc << " arguments to be consumed by '" << arg << "' but found a flag '" <<
|
||||
consumer.peek().get_argument() << "' instead!" << std::endl;
|
||||
std::exit(1);
|
||||
throw detail::unexpected_argument_error(make_string(
|
||||
"Expected ", argc, " arguments to be consumed by '", arg, "' but found a flag '",
|
||||
consumer.peek().get_argument(), "' instead!"
|
||||
));
|
||||
}
|
||||
args.push_back(consumer.consume().get_argument());
|
||||
}
|
||||
if (args.size() != static_cast<size_t>(argc))
|
||||
{
|
||||
std::cerr <<
|
||||
throw std::runtime_error(
|
||||
"This error condition should not be possible. "
|
||||
"Args consumed didn't equal the arguments requested and previous checks didn't fail. "
|
||||
"Please report as an issue on the GitHub"
|
||||
<< std::endl;
|
||||
std::exit(1);
|
||||
"Please report as an issue on the GitHub");
|
||||
}
|
||||
|
||||
BLT_TRACE("Running action %d on dest %s", static_cast<int>(flag->m_action), dest.c_str());
|
||||
|
||||
switch (flag->m_action)
|
||||
{
|
||||
case action_t::STORE:
|
||||
if (argc == 0)
|
||||
{
|
||||
std::cerr << "Error: argument '" << arg <<
|
||||
"' action is store but takes in no arguments. This condition is invalid!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
throw detail::missing_argument_error(
|
||||
make_string("Argument '", arg, "'s action is store but takes in no arguments?"));
|
||||
if (argc == 1)
|
||||
flag->m_dest_func(dest, parsed_args, args.front());
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: argument '" << arg << "' action is store but takes in more than one argument. " <<
|
||||
"This condition is invalid, did you mean to use action_t::APPEND or action_t::EXTEND?" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
throw detail::unexpected_argument_error(make_string("Argument '", arg,
|
||||
"'s action is store but takes in more than one argument. "
|
||||
"Did you mean to use action_t::APPEND or action_t::EXTEND?"));
|
||||
break;
|
||||
case action_t::APPEND:
|
||||
case action_t::EXTEND:
|
||||
if (argc == 0)
|
||||
{
|
||||
std::cerr << "Error: argument '" << arg <<
|
||||
"' action is append or extend but takes in no arguments. This condition is invalid!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
throw detail::missing_argument_error(
|
||||
make_string("Argument '", arg, "'s action is append or extend but takes in no arguments."));
|
||||
flag->m_dest_vec_func(dest, parsed_args, args);
|
||||
break;
|
||||
case action_t::APPEND_CONST:
|
||||
if (argc != 0)
|
||||
{
|
||||
std::cerr << "Error: argument '" << arg << "' action is append const but takes in arguments. "
|
||||
"This condition is invalid!" << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
throw detail::unexpected_argument_error(
|
||||
make_string("Argument '", arg, "'s action is append const but takes in arguments."));
|
||||
if (flag->m_const_value)
|
||||
{
|
||||
std::cerr << "Append const chosen as an action but const value not provided for argument '" << arg << '\'' <<
|
||||
std::endl;
|
||||
std::exit(1);
|
||||
throw detail::missing_value_error(
|
||||
make_string("Append const chosen as an action but const value not provided for argument '", arg, '\''));
|
||||
}
|
||||
if (parsed_args.contains(dest))
|
||||
{
|
||||
|
@ -359,19 +489,17 @@ namespace blt::argparse
|
|||
auto visitor = detail::arg_meta_type_helper_t::make_visitor(
|
||||
[arg](auto& primitive)
|
||||
{
|
||||
std::cerr << "Invalid type for argument '" << arg << "' expected list type, found '"
|
||||
<< blt::type_string<decltype(primitive)>() << "' with value " << primitive << std::endl;
|
||||
std::exit(1);
|
||||
throw detail::type_error(make_string("Invalid type for argument '", arg, "' expected list type, found '",
|
||||
blt::type_string<decltype(primitive)>(), "' with value ", primitive));
|
||||
},
|
||||
[&flag, arg](auto& vec)
|
||||
{
|
||||
using type = typename meta::remove_cvref_t<decltype(vec)>::value_type;
|
||||
if (!std::holds_alternative<type>(*flag->m_const_value))
|
||||
{
|
||||
std::cerr << "Constant value for argument '" << arg <<
|
||||
"' type doesn't match values already present! Expected to be of type '" <<
|
||||
blt::type_string<type>() << "'!" << std::endl;
|
||||
std::exit(1);
|
||||
throw detail::type_error(make_string("Constant value for argument '", arg,
|
||||
"' type doesn't match values already present! Expected to be of type '",
|
||||
blt::type_string<type>(), "'!"));
|
||||
}
|
||||
vec.push_back(std::get<type>(*flag->m_const_value));
|
||||
});
|
||||
|
@ -388,8 +516,7 @@ namespace blt::argparse
|
|||
},
|
||||
[](auto&)
|
||||
{
|
||||
std::cerr << "Append const should not be a list type!" << std::endl;
|
||||
std::exit(1);
|
||||
throw detail::type_error("Append const should not be a list type!");
|
||||
});
|
||||
std::visit(visitor, *flag->m_const_value);
|
||||
}
|
||||
|
@ -397,32 +524,29 @@ namespace blt::argparse
|
|||
case action_t::STORE_CONST:
|
||||
if (argc != 0)
|
||||
{
|
||||
std::cerr << "Store const flag called with an argument. This condition doesn't make sense." << std::endl;
|
||||
print_usage();
|
||||
std::exit(1);
|
||||
throw detail::unexpected_argument_error("Store const flag called with an argument.");
|
||||
}
|
||||
if (!flag->m_const_value)
|
||||
{
|
||||
std::cerr << "Store const flag called with no value. This condition doesn't make sense." << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
throw detail::missing_value_error("Store const flag called with no value. ");
|
||||
parsed_args.m_data.insert({dest, *flag->m_const_value});
|
||||
break;
|
||||
case action_t::STORE_TRUE:
|
||||
if (argc != 0)
|
||||
{
|
||||
std::cerr << "Store true flag called with an argument. This condition doesn't make sense." << std::endl;
|
||||
print_usage();
|
||||
std::exit(1);
|
||||
throw detail::unexpected_argument_error("Store true flag called with an argument.");
|
||||
}
|
||||
parsed_args.m_data.insert({dest, true});
|
||||
break;
|
||||
case action_t::STORE_FALSE:
|
||||
if (argc != 0)
|
||||
{
|
||||
std::cerr << "Store false flag called with an argument. This condition doesn't make sense." << std::endl;
|
||||
print_usage();
|
||||
std::exit(1);
|
||||
throw detail::unexpected_argument_error("Store false flag called with an argument.");
|
||||
}
|
||||
parsed_args.m_data.insert({dest, false});
|
||||
break;
|
||||
case action_t::COUNT:
|
||||
if (parsed_args.m_data.contains(dest))
|
||||
{
|
||||
|
@ -435,16 +559,12 @@ namespace blt::argparse
|
|||
return primitive + static_cast<type>(args.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: count called but stored type is " << blt::type_string<type>() << std::endl;
|
||||
std::exit(1);
|
||||
}
|
||||
throw detail::type_error("Error: count called but stored type is " + blt::type_string<type>());
|
||||
},
|
||||
[](auto&) -> detail::arg_data_t
|
||||
{
|
||||
std::cerr <<
|
||||
"List present on count. This condition doesn't make any sense! (How did we get here, please report this!)";
|
||||
std::exit(1);
|
||||
throw detail::type_error("List present on count. This condition doesn't make any sense! "
|
||||
"(How did we get here, please report this!)");
|
||||
}
|
||||
);
|
||||
parsed_args.m_data[dest] = std::visit(visitor, parsed_args.m_data[dest]);
|
||||
|
|
Loading…
Reference in New Issue