From 282f9ebf91b4bf7cccd291955526fdc46d5951f6 Mon Sep 17 00:00:00 2001 From: Mike Zozu Date: Tue, 15 Dec 2020 16:10:56 +0300 Subject: [PATCH] show default values in help --- include/argparse/argparse.hpp | 63 +++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/include/argparse/argparse.hpp b/include/argparse/argparse.hpp index b8c9daf..9843435 100644 --- a/include/argparse/argparse.hpp +++ b/include/argparse/argparse.hpp @@ -73,6 +73,58 @@ struct is_container< template static constexpr bool is_container_v = is_container::value; +template +struct is_streamable : std::false_type {}; + +template +struct is_streamable< + T, + std::conditional_t() << std::declval()), + void>> : std::true_type {}; + +template +static constexpr bool is_streamable_v = is_streamable::value; + +template +static constexpr bool is_representable_v = + is_streamable_v || is_container_v; + + +constexpr size_t repr_max_container_size = 5; + +template +std::string repr(T const &val) { + if constexpr(std::is_convertible_v) { + return '"' + std::string{std::string_view{val}} + '"'; + } else if constexpr (is_streamable_v) { + std::stringstream out; + out << val; + return out.str(); + } else if constexpr(is_container_v) { + std::stringstream out; + out << "{"; + const auto size = val.size(); + if (size > 1) { + out << repr(*val.begin()); + std::for_each( + std::next(val.begin()), + std::next(val.begin(), std::min(size, repr_max_container_size)-1), + [&out](const auto &v) { out << " " << repr(v); }); + if (size <= repr_max_container_size) + out << " "; + else + out << "..."; + } + if (size > 0) + out << repr(*std::prev(val.end())); + out << "}"; + return out.str(); + } else { + return ""; + } +} + namespace { template constexpr bool standard_signed_integer = false; @@ -294,8 +346,10 @@ public: return *this; } - Argument &default_value(std::any aDefaultValue) { - mDefaultValue = std::move(aDefaultValue); + template + Argument &default_value(T&& aDefaultValue) { + mDefaultValueRepr = details::repr(aDefaultValue); + mDefaultValue = std::forward(aDefaultValue); return *this; } @@ -485,6 +539,8 @@ public: stream << nameStream.str() << "\t" << argument.mHelp; if (argument.mIsRequired && !argument.mDefaultValue.has_value()) stream << "[Required]"; + if (argument.mDefaultValue.has_value()) + stream << " [default: " << argument.mDefaultValueRepr << "]"; stream << "\n"; return stream; } @@ -735,6 +791,7 @@ private: std::string_view mUsedName; std::string mHelp; std::any mDefaultValue; + std::string mDefaultValueRepr; std::any mImplicitValue; using valued_action = std::function; using void_action = std::function; @@ -963,7 +1020,7 @@ private: std::cout << *this; std::exit(0); } - // the second optional argument is --version + // the second optional argument is --version else if (tArgument == std::next(mOptionalArguments.begin(), 1)) { std::cout << mVersion << "\n"; std::exit(0);