Move print_help logic into Argument

This commit is contained in:
Stephan van Veen 2019-05-25 20:01:04 +02:00
parent 34d259d892
commit 67e535e171

View File

@ -41,6 +41,8 @@ SOFTWARE.
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <numeric> #include <numeric>
#include <iomanip>
#include <iterator>
namespace argparse { namespace argparse {
@ -168,6 +170,18 @@ public:
} }
} }
size_t get_arguments_length() const {
return std::accumulate(std::begin(mNames), std::end(mNames), size_t(0), [](const auto& sum, const auto& s) {
return sum + s.size() + 1; // +1 for space between names
});
}
friend std::ostream& operator<<(std::ostream& stream, const Argument& argument) {
std::stringstream nameStream;
std::copy(std::begin(argument.mNames), std::end(argument.mNames), std::ostream_iterator<std::string>(nameStream, " "));
return stream << nameStream.str() << "\t" << argument.mHelp << "\n";
}
template <typename T> template <typename T>
bool operator!=(const T& aRhs) const { bool operator!=(const T& aRhs) const {
@ -366,6 +380,7 @@ class ArgumentParser {
// TODO: support user-defined help and usage messages for the ArgumentParser // TODO: support user-defined help and usage messages for the ArgumentParser
std::string print_help() { std::string print_help() {
std::stringstream stream; std::stringstream stream;
stream << std::left;
stream << "Usage: " << mProgramName << " [options]"; stream << "Usage: " << mProgramName << " [options]";
size_t tLongestArgumentLength = get_length_of_longest_argument(); size_t tLongestArgumentLength = get_length_of_longest_argument();
@ -378,24 +393,8 @@ class ArgumentParser {
if (!mPositionalArguments.empty()) if (!mPositionalArguments.empty())
stream << "Positional arguments:\n"; stream << "Positional arguments:\n";
for (const auto& mPositionalArgument : mPositionalArguments) { for (const auto& mPositionalArgument : mPositionalArguments) {
size_t tCurrentLength = 0; stream.width(tLongestArgumentLength);
auto tNames = mPositionalArgument->mNames; stream << *mPositionalArgument;
for (size_t j = 0; j < tNames.size() - 1; j++) {
auto tCurrentName = tNames[j];
stream << tCurrentName;
stream << ", ";
tCurrentLength += tCurrentName.length() + 2;
}
stream << tNames[tNames.size() - 1];
tCurrentLength += tNames[tNames.size() - 1].length();
if (tCurrentLength < tLongestArgumentLength)
stream << std::string((tLongestArgumentLength - tCurrentLength) + 2, ' ');
else if (tCurrentLength == tLongestArgumentLength)
stream << std::string(2, ' ');
else
stream << std::string((tCurrentLength - tLongestArgumentLength) + 2, ' ');
stream << mPositionalArgument->mHelp << "\n";
} }
if (!mOptionalArguments.empty() && !mPositionalArguments.empty()) if (!mOptionalArguments.empty() && !mPositionalArguments.empty())
@ -403,24 +402,8 @@ class ArgumentParser {
else if (!mOptionalArguments.empty()) else if (!mOptionalArguments.empty())
stream << "Optional arguments:\n"; stream << "Optional arguments:\n";
for (const auto & mOptionalArgument : mOptionalArguments) { for (const auto & mOptionalArgument : mOptionalArguments) {
size_t tCurrentLength = 0; stream.width(tLongestArgumentLength);
auto tNames = mOptionalArgument->mNames; stream << *mOptionalArgument;
for (size_t j = 0; j < tNames.size() - 1; j++) {
auto tCurrentName = tNames[j];
stream << tCurrentName;
stream << ", ";
tCurrentLength += tCurrentName.length() + 2;
}
stream << tNames[tNames.size() - 1];
tCurrentLength += tNames[tNames.size() - 1].length();
if (tCurrentLength < tLongestArgumentLength)
stream << std::string((tLongestArgumentLength - tCurrentLength) + 2, ' ');
else if (tCurrentLength == tLongestArgumentLength)
stream << std::string(2, ' ');
else
stream << std::string((tCurrentLength - tLongestArgumentLength) + 2, ' ');
stream << mOptionalArgument->mHelp << "\n";
} }
std::cout << stream.str(); std::cout << stream.str();
@ -493,11 +476,7 @@ class ArgumentParser {
std::vector<size_t> argumentLengths(mArgumentMap.size()); std::vector<size_t> argumentLengths(mArgumentMap.size());
std::transform(std::begin(mArgumentMap), std::end(mArgumentMap), std::begin(argumentLengths), [](const auto& argPair) { std::transform(std::begin(mArgumentMap), std::end(mArgumentMap), std::begin(argumentLengths), [](const auto& argPair) {
const auto& [key, arg] = argPair; const auto& [key, arg] = argPair;
const auto& names = arg->mNames; return arg->get_arguments_length();
auto maxLength = std::accumulate(std::begin(names), std::end(names), std::string::size_type{0}, [](const auto& sum, const auto& s) {
return sum + s.size() + 2; // +2 for ", "
});
return maxLength - 2; // -2 since the last one doesn't need ", "
}); });
return *std::max_element(std::begin(argumentLengths), std::end(argumentLengths)); return *std::max_element(std::begin(argumentLengths), std::end(argumentLengths));
} }