renderTable function

String renderTable(
  1. List<List<String>> rows
)

Render a 2-D string grid as a Unicode box-drawing table — the kind dialect status and dialect check summaries use.

No deps. Right-aligns numeric-looking cells (everything that parses as a number); left-aligns text. Header row is always the first row of rows.

┌────────┬──────────┬───────┬─────┐
│ Locale │ Coverage │ Stale │ New │
├────────┼──────────┼───────┼─────┤
│ es     │     98.5 │     3 │  12 │
│ ja     │     97.2 │     5 │  12 │
└────────┴──────────┴───────┴─────┘

Implementation

String renderTable(List<List<String>> rows) {
  if (rows.isEmpty) return '';
  final cols = rows.first.length;
  final widths = List<int>.filled(cols, 0);
  for (final row in rows) {
    if (row.length != cols) {
      throw ArgumentError(
        'renderTable: every row must have $cols columns; got ${row.length}',
      );
    }
    for (var i = 0; i < cols; i++) {
      if (row[i].length > widths[i]) widths[i] = row[i].length;
    }
  }
  // Header row is `rows[0]`; rest are data rows. Decide alignment per
  // column from the data rows only (so a string header above numeric
  // data doesn't force left-align).
  final rightAlign = List<bool>.filled(cols, true);
  for (var i = 0; i < cols; i++) {
    for (var r = 1; r < rows.length; r++) {
      if (!_isNumeric(rows[r][i])) {
        rightAlign[i] = false;
        break;
      }
    }
  }
  // Header row stays left-aligned for readability even when data is numeric.

  final buf = StringBuffer();
  buf.writeln(_border(widths, _BorderStyle.top));
  for (var r = 0; r < rows.length; r++) {
    _writeRow(buf, rows[r], widths, rightAlign, header: r == 0);
    if (r == 0) buf.writeln(_border(widths, _BorderStyle.mid));
  }
  buf.write(_border(widths, _BorderStyle.bottom));
  return buf.toString();
}