diff --git a/CMakeLists.txt b/CMakeLists.txt index 2807d26..614e651 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20) include(cmake/color.cmake) -set(BLT_VERSION 4.0.28) +set(BLT_VERSION 4.0.29) set(BLT_TARGET BLT) diff --git a/include/blt/parse/argparse_v2.h b/include/blt/parse/argparse_v2.h index 1f42898..d7dc348 100644 --- a/include/blt/parse/argparse_v2.h +++ b/include/blt/parse/argparse_v2.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -227,6 +228,16 @@ namespace blt::argparse } }; + template + auto ensure_is_string(T&& t) + { + if constexpr (std::is_arithmetic_v> && !(std::is_same_v + || std::is_same_v || std::is_same_v)) + return std::to_string(std::forward(t)); + else + return std::forward(t); + } + void test(); } @@ -493,6 +504,14 @@ namespace blt::argparse return *this; } + template + argument_builder_t& set_choices(Args&&... args) + { + m_choices = hashset_t{}; + ((m_choices->emplace(detail::ensure_is_string(std::forward(args)))), ...); + return *this; + } + argument_builder_t& set_default(const detail::arg_data_t& default_value) { m_default_value = default_value; @@ -566,7 +585,7 @@ namespace blt::argparse public: explicit argument_parser_t(const std::optional description = {}, const std::optional epilogue = {}, - const std::optional version = {}, + const std::optional version = {}, const std::optional usage = {}, const std::optional name = {}): m_name(name), m_usage(usage), m_description(description), m_epilogue(epilogue), m_version(version) { diff --git a/src/blt/parse/argparse_v2.cpp b/src/blt/parse/argparse_v2.cpp index 1254909..d8f298c 100644 --- a/src/blt/parse/argparse_v2.cpp +++ b/src/blt/parse/argparse_v2.cpp @@ -67,16 +67,6 @@ namespace blt::argparse } } - template - auto ensure_is_string(T&& t) - { - if constexpr (std::is_arithmetic_v> && !(std::is_same_v - || std::is_same_v || std::is_same_v)) - return std::to_string(std::forward(t)); - else - return std::forward(t); - } - template std::string to_string(const T& t) { @@ -99,7 +89,7 @@ namespace blt::argparse { std::string out; out.reserve((get_const_char_size(strings) + ...)); - ((out += ensure_is_string(std::forward(strings))), ...); + ((out += detail::ensure_is_string(std::forward(strings))), ...); return out; } @@ -151,7 +141,7 @@ namespace blt::argparse template aligned_internal_string_t& operator+=(T&& value) { - const auto str = to_string(ensure_is_string(std::forward(value))); + const auto str = to_string(detail::ensure_is_string(std::forward(value))); for (size_t i = 0; i < str.size(); i++) { size_t j = i; @@ -166,6 +156,11 @@ namespace blt::argparse return *this; } + [[nodiscard]] std::string& str() const + { + return string; + } + private: std::string& string; size_t max_line_size; @@ -264,7 +259,7 @@ namespace blt::argparse template aligned_printer_t& add(T&& value) { - const auto str = to_string(ensure_is_string(std::forward(value))); + const auto str = to_string(detail::ensure_is_string(std::forward(value))); if (buffer.back().size() + str.size() > max_line_size) newline(); buffer.back() += replace_tabs(str); @@ -458,13 +453,10 @@ namespace blt::argparse { auto& [builder, flag_list] = pair; str += builder->m_help.value_or(""); - } - mark.align(4); - for (auto [str, pair] : mark.iter().zip(same_flags)) - { - auto& [builder, flag_list] = pair; if (builder->m_default_value) { + if (!std::isblank(str.str().back())) + str += " "; str += "(Default: "; std::visit(detail::arg_meta_type_helper_t::make_visitor( [&](auto& value) @@ -487,6 +479,19 @@ namespace blt::argparse }), *builder->m_default_value); str += ")"; } + if (builder->m_choices) + { + if (!std::isblank(str.str().back())) + str += " "; + str += "(Choices: "; + for (const auto& [i, v] : enumerate(*builder->m_choices)) + { + str += v; + if (i != builder->m_choices->size() - 1) + str += ", "; + } + str += ')'; + } } }