#!/usr/bin/env python3 # -*- encoding: utf-8 -*- from typing import Any, List, Optional, Union def table_fmt(labels: List[str], table: List[List[Any]], title: Optional[str] = None, alignment: Optional[Union[str, List[str]]] = None, divide_last_line: bool = False ) -> str: lbl: List[str] = list(map(str, labels)) tbl: List[List[str]] = list(map(lambda l: list(map(str, l)), table)) lbl_sz = len(lbl) for line in tbl: line_sz = len(line) if line_sz != lbl_sz: raise ValueError( "A table line does not match its cell count to the number of labels." ) algnmt: List[str] = list() if alignment is None: algnmt = ['<']*lbl_sz else: if len(alignment) != lbl_sz: raise ValueError( "Table alignment does not match its rule count to the number of labels." ) algnmt = list(alignment) acceptable_rules = ('<', '^', '>') for rl in algnmt: if rl not in acceptable_rules: raise ValueError( "Table alignment rule %r is not one of %r" % (rl, acceptable_rules) ) tbl_sz = len(tbl) tbl_szs: List[List[int]] = ( [list(map(len, lbl))] + list(map(lambda l: list(map(len, l)), tbl)) ) row_widths: List[int] = list(map(max, zip(*tbl_szs))) print(row_widths) labels_tpl = ( '| ' + ' | '.join([f'{{{e}:^{l}}}' for e, l in enumerate(row_widths)]) + ' |' ) data_tpl = ( '| ' + ' | '.join([f'{{{e}:{algnmt[e]}{l}}}' for e, l in enumerate(row_widths)]) + ' |' ) lastlinesep = ( '|.' + '.|.'.join(['.'*w for w in row_widths]) + '.|' ) title_tpl = '| {0:^%d} |\n' % (sum(row_widths)+3*(lbl_sz-1)) linesep_total_sz = (4+sum(row_widths)+3*(lbl_sz-1)) hugelinesep = '='*linesep_total_sz linesep = '-'*linesep_total_sz s = '' # title section s += hugelinesep + '\n' if title: s += title_tpl.format(title) s += hugelinesep + '\n' # row label section s += labels_tpl.format(*lbl) + '\n' s += linesep + '\n' # data section for seq, line in enumerate(tbl): if seq+1 == tbl_sz and divide_last_line: s+= lastlinesep + '\n' s += data_tpl.format(*line) + '\n' # row label section s += linesep + '\n' s += labels_tpl.format(*lbl) + '\n' # title section s += hugelinesep + '\n' if title: s += title_tpl.format(title) s += hugelinesep + '\n' return s