Wrap strings which are likely long when printing help

to preserve indentation
This commit is contained in:
Martchus 2017-09-29 20:58:58 +02:00
parent 6e80640db5
commit b7b218c831
2 changed files with 64 additions and 15 deletions

View File

@ -260,6 +260,35 @@ void ArgumentReader::read(ArgumentVector &args)
} // while(argv != end)
}
ostream &operator<<(ostream &os, const Wrapper &wrapper)
{
// determine max. number of columns
static const TerminalSize termSize(determineTerminalSize());
const auto maxColumns = termSize.columns ? termSize.columns : numeric_limits<unsigned short>::max();
// print wrapped string considering indentation
unsigned short currentCol = wrapper.m_indentation.level;
for (const char *currentChar = wrapper.m_str; *currentChar; ++currentChar) {
const bool wrappingRequired = currentCol >= maxColumns;
if (wrappingRequired || *currentChar == '\n') {
// insert newline (TODO: wrap only at end of a word)
os << '\n';
// print indentation (if enough space)
if (wrapper.m_indentation.level < maxColumns) {
os << wrapper.m_indentation;
currentCol = wrapper.m_indentation.level;
} else {
currentCol = 0;
}
}
if (*currentChar != '\n' && (!wrappingRequired || *currentChar != ' ')) {
os << *currentChar;
++currentCol;
}
}
return os;
}
/// \brief Specifies the name of the application (used by ArgumentParser::printHelp()).
const char *applicationName = nullptr;
/// \brief Specifies the author of the application (used by ArgumentParser::printHelp()).
@ -351,7 +380,8 @@ const char *Argument::firstValue() const
*/
void Argument::printInfo(ostream &os, unsigned char indentation) const
{
os << Indentation(indentation);
Indentation ident(indentation);
os << ident;
EscapeCodes::setStyle(os, EscapeCodes::TextAttribute::Bold);
if (notEmpty(name())) {
if (!denotesOperation()) {
@ -372,7 +402,7 @@ void Argument::printInfo(ostream &os, unsigned char indentation) const
os << ' ' << '[' << *i << ']';
++valueNamesPrint;
}
if (requiredValueCount() == static_cast<size_t>(-1)) {
if (requiredValueCount() == Argument::varValueCount) {
os << " ...";
} else {
for (; valueNamesPrint < requiredValueCount(); ++valueNamesPrint) {
@ -380,34 +410,28 @@ void Argument::printInfo(ostream &os, unsigned char indentation) const
}
}
}
indentation += 2;
ident.level += 2;
if (notEmpty(description())) {
os << '\n' << Indentation(indentation) << description();
os << '\n' << ident << Wrapper(description(), ident);
}
if (isRequired()) {
os << '\n' << Indentation(indentation) << "particularities: mandatory";
os << '\n' << ident << "particularities: mandatory";
if (!isMainArgument()) {
os << " if parent argument is present";
}
}
if (environmentVariable()) {
os << '\n' << Indentation(indentation) << "default environment variable: " << environmentVariable();
os << '\n' << ident << "default environment variable: " << Wrapper(environmentVariable(), ident + 30);
}
os << '\n';
for (const auto *arg : subArguments()) {
arg->printInfo(os, indentation);
arg->printInfo(os, ident.level);
}
if (notEmpty(example())) {
if (indentation == 2 && !subArguments().empty()) {
if (ident.level == 2 && !subArguments().empty()) {
os << '\n';
}
os << Indentation(indentation) << "example: ";
for (const char *c = example(); *c; ++c) {
os << *c;
if (*c == '\n') {
os << Indentation(indentation + 9);
}
}
os << ident << "example: " << Wrapper(example(), ident + 9);
os << '\n';
}
}

View File

@ -1,6 +1,9 @@
#ifndef APPLICATION_UTILITIES_ARGUMENTPARSER_PRIVATE_H
#define APPLICATION_UTILITIES_ARGUMENTPARSER_PRIVATE_H
#include "./argumentparser.h"
#include "./commandlineutils.h"
namespace ApplicationUtilities {
class CPP_UTILITIES_EXPORT ArgumentReader {
@ -31,6 +34,28 @@ public:
/// \brief Whether completion mode is enabled. In this case reading args will be continued even if an denotation is unknown (regardless of unknownArgumentBehavior()).
bool completionMode;
};
class Wrapper;
std::ostream &operator<<(std::ostream &os, const Wrapper &wrapper);
class Wrapper {
friend std::ostream &operator<<(std::ostream &os, const Wrapper &wrapper);
public:
Wrapper(const char *str, Indentation currentIndentation = Indentation());
private:
const char *const m_str;
Indentation m_indentation;
};
Wrapper::Wrapper(const char *str, Indentation currentIndentation)
: m_str(str)
, m_indentation(currentIndentation)
{
}
} // namespace ApplicationUtilities
#endif // APPLICATION_UTILITIES_ARGUMENTPARSER_PRIVATE_H