# HG changeset patch # User Frantiลกek Kuฤera # Date 1574009473 -3600 # Node ID 32824e833b89b6765d671cc41a4261cf961fc45c # Parent d841e5ac15c08410ded6eafe3c3bd8656a1425f6 compute proper width of strings (characters might be wider than 1 column on display) Before: $ echo hello ๐Ÿญ | relpipe-in-csv wide string | relpipe-out-tabular wide: โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚ string (string) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ hello ๐Ÿญ โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ Record count: 1 After: $ echo hello ๐Ÿญ | relpipe-in-csv wide string | relpipe-out-tabular wide: โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ โ”‚ string (string) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ hello ๐Ÿญ โ”‚ โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ Record count: 1 diff -r d841e5ac15c0 -r 32824e833b89 src/TabularPrefetchingHandler.h --- a/src/TabularPrefetchingHandler.h Wed Oct 30 16:47:43 2019 +0100 +++ b/src/TabularPrefetchingHandler.h Sun Nov 17 17:51:13 2019 +0100 @@ -98,6 +98,16 @@ return result.str(); } + /** + * @param stringValue + * @return the width that would the string occupy on the display (particular characters might be wider than 1 column) + */ + integer_t computeWidth(const string_t& stringValue) { + integer_t width = 0; + for (wchar_t ch : stringValue) width += std::max(0, wcwidth(ch)); + return width; + } + void printHorizontalLine(const string_t &left, const string_t &middle, const string_t &right) { const string_t bar = L"โ”€"; // TODO: support also ASCII nostalgia: @@ -148,7 +158,7 @@ integer_t columnIndex = i % columnCount; if (columnIndex == 0) output << INDENT << ESC_BORDER << "โ”‚" << ESC_RESET; string_t stringValue = values[i]; - integer_t padding = columnWidths[columnIndex] - stringValue.size(); + integer_t padding = columnWidths[columnIndex] - computeWidth(stringValue); boolean_t alignRight = columnTypes[columnIndex] == TypeId::BOOLEAN || columnTypes[columnIndex] == TypeId::INTEGER; if (alignRight) for (integer_t p = 0; p < padding; p++) output << " "; @@ -190,7 +200,7 @@ void attribute(const string_t& value) override { integer_t i = values.size() % columnCount; values.push_back(value); - columnWidths[i] = max(columnWidths[i], value.length()); + columnWidths[i] = max(columnWidths[i], computeWidth(value)); } void endOfPipe() {