def __init__(self, asm_writer, max_width, min_col_width): self.asm_writer = asm_writer self.max_width = max_width self.min_col_width = min_col_width self.table = None self.table_parser = TableParser() self.cell_matrix = None
def __init__(self, asm_writer, max_width, min_col_width, properties): self.asm_writer = asm_writer self.max_width = max_width self.min_col_width = min_col_width border_h = properties.get('table-border-horizontal', '-') self.border_h_ext = border_h[:1].strip() self.border_h_int = (border_h[1:2] or self.border_h_ext).strip() self.border_v = properties.get('table-border-vertical', '')[:1] or '|' self.border_join = properties.get('table-border-join', '')[:1] or '+' self.table = None self.table_parser = TableParser() self.cell_matrix = None
class TableWriter: def __init__(self, asm_writer, max_width, min_col_width, properties): self.asm_writer = asm_writer self.max_width = max_width self.min_col_width = min_col_width border_h = properties.get('table-border-horizontal', '-') self.border_h_ext = border_h[:1].strip() self.border_h_int = (border_h[1:2] or self.border_h_ext).strip() self.border_v = properties.get('table-border-vertical', '')[:1] or '|' self.border_join = properties.get('table-border-join', '')[:1] or '+' self.table = None self.table_parser = TableParser() self.cell_matrix = None def format_table(self, text): self.table = self.table_parser.parse_table(self.asm_writer, text) self.table.prepare_cells(self.min_col_width, self.max_width) self.cell_matrix = self._build_cell_matrix() return self._create_table_text() def _build_cell_matrix(self): cell_matrix = [] for row in self.table.rows: cell_matrix.append([None] * self.table.num_cols) for cell in self.table.cells: for x in range(cell.col_index, cell.col_index + cell.colspan): for y in range(cell.row_index, cell.row_index + cell.rowspan): cell_matrix[y][x] = cell return cell_matrix def _get_cell(self, col_index, row_index): if 0 <= row_index < len( self.cell_matrix) and 0 <= col_index < self.table.num_cols: return self.cell_matrix[row_index][col_index] def _render_row(self, lines, row_index, first_line=True): rendered = False line = '' col_index = 0 cell_left_transparent = True cell = self._get_cell(col_index, row_index) while cell: if cell.transparent and cell_left_transparent: border = ' ' else: border = self.border_v text = '' if cell.contents and (first_line or row_index == cell.row_index + cell.rowspan - 1): text = cell.contents.pop(0) rendered = True line += "{} {} ".format( border, text.ljust(self.table.get_cell_width(col_index, cell.colspan))) col_index += cell.colspan cell_left_transparent = cell.transparent cell = self._get_cell(col_index, row_index) if rendered: if (cell and not cell.transparent) or (cell is None and not cell_left_transparent): line += self.border_v lines.append(line.rstrip()) return rendered def _create_table_text(self): lines = [] max_row_index = len(self.table.rows) if max_row_index == 0: return lines sep = True for row_index in range(max_row_index + 1): if sep or row_index == max_row_index: row_sep = self._create_row_separator(row_index) if row_sep: lines.append(row_sep) if row_index < max_row_index: self._render_row(lines, row_index) while self._render_row(lines, row_index, False): pass sep = any(c.header for c in self.table.rows[row_index]) return lines def _create_row_separator(self, row_index): # Return a separator between rows `row_index - 1` and `row_index` line = '' col_index = 0 cell_left_contents = True while col_index < self.table.num_cols: cell_above = self._get_cell(col_index, row_index - 1) if row_index < len(self.table.rows): cell = self._get_cell(col_index, row_index) else: cell = cell_above if cell is None: break cell_above_transparent = cell_above is None or cell_above.transparent cell_above_left = self._get_cell(col_index - 1, row_index - 1) cell_above_left_transparent = cell_above_left is None or cell_above_left.transparent cell_left = self._get_cell(col_index - 1, row_index) cell_left_transparent = cell_left is None or cell_left.transparent cell_contents = bool( cell_above and (cell_above.contents or cell_above.row_index + cell_above.rowspan > row_index)) if cell.transparent and cell_above_transparent and cell_above_left_transparent and cell_left_transparent: line += ' ' elif cell_contents and cell_left_contents: line += self.border_v else: line += self.border_join if cell_contents: if cell.contents: text = cell.contents.pop(0) else: text = '' line += ' {} '.format( text.ljust( self.table.get_cell_width(col_index, cell_above.colspan))) else: if cell.transparent and cell_above_transparent: spacer = ' ' elif 0 < row_index < len(self.table.rows): spacer = self.border_h_int else: spacer = self.border_h_ext if not spacer: return None line += spacer * ( 2 + self.table.get_cell_width(col_index, cell.colspan)) cell_left_contents = cell_contents col_index += cell.colspan if cell_contents and not cell_above_transparent: return line + self.border_v if line.endswith(' '): return line.rstrip() return line + self.border_join
class TableWriter: def __init__(self, asm_writer, max_width, min_col_width): self.asm_writer = asm_writer self.max_width = max_width self.min_col_width = min_col_width self.table = None self.table_parser = TableParser() self.cell_matrix = None def format_table(self, text): self.table = self.table_parser.parse_table(self.asm_writer, text) self.table.cell_padding = 3 self.table.prepare_cells() self.table.reduce_width(self.max_width, self.min_col_width) self.cell_matrix = self._build_cell_matrix() return self._create_table_text() def _build_cell_matrix(self): cell_matrix = [] for row in self.table.rows: cell_matrix.append([None] * self.table.num_cols) for cell in self.table.cells: for x in range(cell.col_index, cell.col_index + cell.colspan): for y in range(cell.row_index, cell.row_index + cell.rowspan): cell_matrix[y][x] = cell return cell_matrix def _get_cell(self, col_index, row_index): if 0 <= row_index < len(self.cell_matrix) and 0 <= col_index < self.table.num_cols: return self.cell_matrix[row_index][col_index] def _render_row(self, lines, row_index, first_line=True): rendered = False line = '' col_index = 0 cell_left_transparent = True cell = self._get_cell(col_index, row_index) while cell: if cell.transparent and cell_left_transparent: border = ' ' else: border = '|' text = '' if cell.contents and (first_line or row_index == cell.row_index + cell.rowspan - 1): text = cell.contents.pop(0) rendered = True line += "{} {} ".format(border, text.ljust(self.table.get_cell_width(col_index, cell.colspan))) col_index += cell.colspan cell_left_transparent = cell.transparent cell = self._get_cell(col_index, row_index) if rendered: if (cell and not cell.transparent) or (cell is None and not cell_left_transparent): line += '|' lines.append(line.rstrip()) return rendered def _create_table_text(self): lines = [] max_row_index = len(self.table.rows) if max_row_index == 0: return lines separator_row_indexes = set((0, max_row_index)) separator_row_indexes.update([i + 1 for i in self.table.get_header_rows()]) for row_index in range(max_row_index): if row_index in separator_row_indexes: lines.append(self._create_row_separator(row_index)) self._render_row(lines, row_index) while self._render_row(lines, row_index, False): pass lines.append(self._create_row_separator(max_row_index)) return lines def _create_row_separator(self, row_index): # Return a separator between rows `row_index - 1` and `row_index` line = '' col_index = 0 cell_left_contents = True while col_index < self.table.num_cols: cell_above = self._get_cell(col_index, row_index - 1) if row_index < len(self.table.rows): cell = self._get_cell(col_index, row_index) else: cell = cell_above if cell is None: break cell_above_transparent = cell_above is None or cell_above.transparent cell_above_left = self._get_cell(col_index - 1, row_index - 1) cell_above_left_transparent = cell_above_left is None or cell_above_left.transparent cell_left = self._get_cell(col_index - 1, row_index) cell_left_transparent = cell_left is None or cell_left.transparent cell_contents = bool(cell_above and cell_above.contents) if cell.transparent and cell_above_transparent and cell_above_left_transparent and cell_left_transparent: line += ' ' elif cell_contents and cell_left_contents: line += '|' else: line += '+' if cell_contents: text = cell.contents.pop(0) line += ' {} '.format(text.ljust(self.table.get_cell_width(col_index, cell_above.colspan))) else: if cell.transparent and cell_above_transparent: spacer = ' ' else: spacer = '-' line += spacer * (2 + self.table.get_cell_width(col_index, cell.colspan)) cell_left_contents = cell_contents col_index += cell.colspan if cell_contents: return line + '|' if line.endswith(' '): return line.rstrip() return line + '+'