# This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details from typing import Dict from enum import Enum import re class Alignment(Enum): LEFT = 0 RIGHT = 1 CENTER = 2 class TablePrinter(object): def __init__(self, columns): assert(len(columns) > 0) self._columns = columns self._widths = [len(col['label']) for col in self._columns] self._rows = [] pass def _convert_field_dict_to_ordered_list(self, fields:Dict[str, object]): assert(len(fields) == len(self._columns)) ordered_list = [None] * len(self._columns) column_names = [column['label'] for column in self._columns] for column, value in fields.items(): index = column_names.index(column) ordered_list[index] = value return ordered_list def _print_row(self, row, align_style=None): for i, (value, column, align_width) in enumerate(zip(row, self._columns, self._widths)): if i > 0: print(' | ', end='') actual_align_style = align_style if align_style != None else column['align'] align_char = { Alignment.LEFT: '<', Alignment.CENTER: '^', Alignment.RIGHT: '>' }[actual_align_style] print('{0:{align_style}{align_width}}'.format(value, align_style=align_char, align_width=align_width), end=' ') print() pass def _print_horizontal_separator(self): for i, align_width in enumerate(self._widths): if i > 0: print('-+-', end='') print('-' * (align_width+1), end='') print() pass def clean_colorama(self, str): return re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]').sub('', str) def add_row(self, fields:Dict[str, object]): fields = self._convert_field_dict_to_ordered_list(fields) for i, value in enumerate(fields): self._widths[i] = max(self._widths[i], len(self.clean_colorama(str(value)))) self._rows.append(fields) def _compute_summary_row(self): sums = [0] * len(self._widths) for row in self._rows: for i, value in enumerate(row): if not isinstance(value, int): continue sums[i] = sums[i] + value sums[0] = "Total" return sums def print(self, summary=False): self._print_row([column['label'] for column in self._columns], align_style=Alignment.LEFT) self._print_horizontal_separator() if summary: summary_row = self._compute_summary_row() for i, value in enumerate(summary_row): self._widths[i] = max(self._widths[i], len(str(value))) for row in self._rows: self._print_row(row) if summary: self._print_horizontal_separator() self._print_row(summary_row) pass