| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:math' as math; | |
| /// Print the given [table]. | |
| void printTable(List<List<String>> table) { | |
| var buffer = StringBuffer(); | |
| buffer.writeTable(table); | |
| print(buffer.toString()); | |
| } | |
| /// Return an iterable that will produce all of the integer values between | |
| /// [first] and [last] inclusive. | |
| Iterable<int> range(int first, int last) sync* { | |
| for (var i = first; i < last; i++) { | |
| yield i; | |
| } | |
| } | |
| /// Given a [table] represented as a list of rows, right justify all of the | |
| /// cells in the given [column]. | |
| void rightJustifyColumn(List<List<String>> table, int column) { | |
| var width = 0; | |
| for (var i = 0; i < table.length; i++) { | |
| var row = table[i]; | |
| width = math.max(width, row[column].length); | |
| } | |
| for (var i = 0; i < table.length; i++) { | |
| var row = table[i]; | |
| var cellValue = row[column]; | |
| var length = cellValue.length; | |
| if (length < width) { | |
| var padding = ' ' * (width - length); | |
| row[column] = '$padding$cellValue'; | |
| } | |
| } | |
| } | |
| /// Given a [table] represented as a list of rows, right justify all of the | |
| /// cells in the given [columns]. | |
| void rightJustifyColumns(List<List<String>> table, Iterable<int> columns) { | |
| for (var column in columns) { | |
| rightJustifyColumn(table, column); | |
| } | |
| } | |
| extension OutputUtilities on StringSink { | |
| /// Write the given [table]. | |
| /// | |
| /// The table is represented as a list or rows, where each row is a list of | |
| /// the contents of the cells in that row. | |
| /// | |
| /// Throws an [ArgumentError] if the table is empty or if the rows do not | |
| /// contain the same number of cells. | |
| void writeTable(List<List<String>> table) { | |
| var columnWidths = _computeColumnWidths(table); | |
| for (var row in table) { | |
| var lastNonEmpty = row.length - 1; | |
| while (lastNonEmpty > 0) { | |
| if (row[lastNonEmpty].isNotEmpty) { | |
| break; | |
| } | |
| lastNonEmpty--; | |
| } | |
| for (var i = 0; i <= lastNonEmpty; i++) { | |
| var cellContent = row[i]; | |
| var columnWidth = columnWidths[i]; | |
| var padding = columnWidth - cellContent.length; | |
| write(cellContent); | |
| if (i < lastNonEmpty) { | |
| write(' ' * (padding + 2)); | |
| } | |
| } | |
| writeln(); | |
| } | |
| } | |
| /// Return the minimum widths for each of the columns in the given [table]. | |
| /// | |
| /// The table is represented as a list or rows, where each row is a list of | |
| /// the contents of the cells in that row. | |
| /// | |
| /// Throws an [ArgumentError] if the table is empty or if the rows do not | |
| /// contain the same number of cells. | |
| List<int> _computeColumnWidths(List<List<String>> table) { | |
| if (table.isEmpty) { | |
| throw ArgumentError('table cannot be empty'); | |
| } | |
| var columnCount = table[0].length; | |
| if (columnCount == 0) { | |
| throw ArgumentError('rows cannot be empty'); | |
| } | |
| var columnWidths = List<int>.filled(columnCount, 0); | |
| for (var row in table) { | |
| var rowLength = row.length; | |
| if (rowLength > 0) { | |
| if (rowLength != columnCount) { | |
| throw ArgumentError( | |
| 'non-empty rows must contain the same number of columns', | |
| ); | |
| } | |
| for (var i = 0; i < rowLength; i++) { | |
| var cellWidth = row[i].length; | |
| columnWidths[i] = math.max(columnWidths[i], cellWidth); | |
| } | |
| } | |
| } | |
| return columnWidths; | |
| } | |
| } |