Added hanging indent to help output to make it more readable

This commit is contained in:
Daniel Wolf 2016-04-12 21:23:15 +02:00
parent fd6b3b1e2f
commit 4b8e38970a
4 changed files with 15 additions and 16 deletions

View File

@ -68,10 +68,6 @@ void NiceCmdLineOutput::printShortUsage(CmdLineInterface& cli, std::ostream& out
outStream << shortUsage << endl; outStream << shortUsage << endl;
} }
string wrapLongID(const string& s) {
return std::regex_replace(s, std::regex(", "), ",\n");
}
void NiceCmdLineOutput::printLongUsage(CmdLineInterface& cli, std::ostream& outStream) const { void NiceCmdLineOutput::printLongUsage(CmdLineInterface& cli, std::ostream& outStream) const {
TablePrinter tablePrinter(&outStream, { 20, 56 }); TablePrinter tablePrinter(&outStream, { 20, 56 });
@ -83,7 +79,7 @@ void NiceCmdLineOutput::printLongUsage(CmdLineInterface& cli, std::ostream& outS
if (arg != xorArgGroup[0]) if (arg != xorArgGroup[0])
outStream << "-- or --" << endl; outStream << "-- or --" << endl;
tablePrinter.printRow({ wrapLongID(arg->longID()), arg->getDescription() }); tablePrinter.printRow({ arg->longID(), arg->getDescription() });
} }
outStream << endl; outStream << endl;
} }
@ -93,6 +89,6 @@ void NiceCmdLineOutput::printLongUsage(CmdLineInterface& cli, std::ostream& outS
for (auto arg : argList) { for (auto arg : argList) {
if (xorHandler.contains(arg)) continue; if (xorHandler.contains(arg)) continue;
tablePrinter.printRow({ wrapLongID(arg->longID()), arg->getDescription() }); tablePrinter.printRow({ arg->longID(), arg->getDescription() });
} }
} }

View File

@ -33,7 +33,7 @@ void TablePrinter::printRow(initializer_list<string> columns) const {
{ {
int columnIndex = 0; int columnIndex = 0;
for (const string& column : columns) { for (const string& column : columns) {
vector<string> lines = wrapString(column, columnWidths[columnIndex]); vector<string> lines = wrapString(column, columnWidths[columnIndex], 2);
if (lines.size() > lineCount) lineCount = lines.size(); if (lines.size() > lineCount) lineCount = lines.size();
strings[columnIndex] = move(lines); strings[columnIndex] = move(lines);

View File

@ -25,8 +25,10 @@ vector<string> splitIntoLines(const string& s) {
return lines; return lines;
} }
vector<string> wrapSingleLineString(const string& s, int lineLength) { vector<string> wrapSingleLineString(const string& s, int lineLength, int hangingIndent) {
if (lineLength <= 0) throw std::invalid_argument("lineLength must be > 0."); if (lineLength <= 0) throw std::invalid_argument("lineLength must be > 0.");
if (hangingIndent < 0) throw std::invalid_argument("hangingIndent must be >= 0.");
if (hangingIndent >= lineLength) throw std::invalid_argument("hangingIndent must be < lineLength.");
if (s.find('\t') != std::string::npos) throw std::invalid_argument("s must not contain tabs."); if (s.find('\t') != std::string::npos) throw std::invalid_argument("s must not contain tabs.");
if (s.find('\n') != std::string::npos) throw std::invalid_argument("s must not contain line breaks."); if (s.find('\n') != std::string::npos) throw std::invalid_argument("s must not contain line breaks.");
@ -37,13 +39,14 @@ vector<string> wrapSingleLineString(const string& s, int lineLength) {
auto end = p + s.size(); auto end = p + s.size();
// Iterate over input string // Iterate over input string
while (p <= end) { while (p <= end) {
// If we're at a word boundary: update safeLineEnd // If we're at a word boundary: update lineEnd
if (p == end || *p == ' ') { if (p == end || *p == ' ' || *p == '|') {
lineEnd = p; lineEnd = p;
} }
// If we've hit lineLength or the end of the string: add a new result line // If we've hit lineLength or the end of the string: add a new result line
if (p == end || p - lineBegin == lineLength) { int currentIndent = lines.empty() ? 0 : hangingIndent;
if (p == end || p - lineBegin == lineLength - currentIndent) {
if (lineEnd == lineBegin) { if (lineEnd == lineBegin) {
// The line contains a single word, which is too long. Split mid-word. // The line contains a single word, which is too long. Split mid-word.
lineEnd = p; lineEnd = p;
@ -52,7 +55,7 @@ vector<string> wrapSingleLineString(const string& s, int lineLength) {
// Add trimmed line to list // Add trimmed line to list
string line(lineBegin, lineEnd); string line(lineBegin, lineEnd);
boost::algorithm::trim_right(line); boost::algorithm::trim_right(line);
lines.push_back(line); lines.push_back(string(currentIndent, ' ') + line);
// Resume after the last line, skipping spaces // Resume after the last line, skipping spaces
p = lineEnd; p = lineEnd;
@ -66,10 +69,10 @@ vector<string> wrapSingleLineString(const string& s, int lineLength) {
return lines; return lines;
} }
vector<string> wrapString(const string& s, int lineLength) { vector<string> wrapString(const string& s, int lineLength, int hangingIndent) {
vector<string> lines; vector<string> lines;
for (string paragraph : splitIntoLines(s)) { for (string paragraph : splitIntoLines(s)) {
auto paragraphLines = wrapSingleLineString(paragraph, lineLength); auto paragraphLines = wrapSingleLineString(paragraph, lineLength, hangingIndent);
copy(paragraphLines.cbegin(), paragraphLines.cend(), back_inserter(lines)); copy(paragraphLines.cbegin(), paragraphLines.cend(), back_inserter(lines));
} }

View File

@ -5,6 +5,6 @@
std::vector<std::string> splitIntoLines(const std::string& s); std::vector<std::string> splitIntoLines(const std::string& s);
std::vector<std::string> wrapSingleLineString(const std::string& s, int lineLength); std::vector<std::string> wrapSingleLineString(const std::string& s, int lineLength, int hangingIndent = 0);
std::vector<std::string> wrapString(const std::string& s, int lineLength); std::vector<std::string> wrapString(const std::string& s, int lineLength, int hangingIndent = 0);