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
--- 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() {