summaryrefslogtreecommitdiff
path: root/creole/shared/markup_table.py
blob: acb9b2163a1f83a227e3c7f6afc78e9f800aca91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

class MarkupTable(object):
    """
    Container for holding table data and render the data in creole markup.
    Format every cell width to the same col width.
    """

    def __init__(self, head_prefix="= ", auto_width=True, debug_msg=None):
        self.head_prefix = head_prefix
        self.auto_width = auto_width

        if debug_msg is None:
            self.debug_msg = self._non_debug
        else:
            self.debug_msg = debug_msg

        self.rows = []
        self.row_index = None
        self.has_header = False

    def _non_debug(self, *args):
        pass

    def add_tr(self):
        self.debug_msg("Table.add_tr", "")
        self.rows.append([])
        self.row_index = len(self.rows) - 1

    def add_th(self, text):
        self.has_header = True
        self.add_td(self.head_prefix + text)

    def add_td(self, text):
        if self.row_index is None:
            self.add_tr()

        self.debug_msg("Table.add_td", text)
        self.rows[self.row_index].append(text)

    def _get_preformat_info(self):
        cells = []
        for row in self.rows:
            line_cells = []
            for cell in row:
                cell = cell.strip()
                if cell != "":
                    if self.head_prefix and cell.startswith(self.head_prefix):
                        cell += " "  # Headline
                    else:
                        cell = f" {cell} "  # normal cell
                line_cells.append(cell)
            cells.append(line_cells)

        # Build a list of max len for every column
        widths = [max(map(len, col)) for col in zip(*cells)]

        return cells, widths

    def get_table_markup(self):
        """ return the table data in creole/textile markup. """
        if not self.auto_width:
            lines = []
            for row in self.rows:
                lines.append("|" + "|".join([cell for cell in row]) + "|")
        else:
            # preformat every table cell
            cells, widths = self._get_preformat_info()

            # Join every line with ljust
            lines = []
            for row in cells:
                cells = [cell.ljust(width) for cell, width in zip(row, widths)]
                lines.append("|" + "|".join(cells) + "|")

        result = "\n".join(lines)

        self.debug_msg("Table.get_table_markup", result)
        return result

    def get_rest_table(self):
        """ return the table data in ReSt markup. """
        # preformat every table cell
        cells, widths = self._get_preformat_info()

        separator_line = "+%s+" % "+".join(["-" * width for width in widths])
        headline_separator = "+%s+" % "+".join(["=" * width for width in widths])

        lines = []
        for no, row in enumerate(cells):
            if no == 1 and self.has_header:
                lines.append(headline_separator)
            else:
                lines.append(separator_line)

            # Join every line with ljust
            cells = [cell.ljust(width) for cell, width in zip(row, widths)]
            lines.append("|" + "|".join(cells) + "|")

        lines.append(separator_line)

        return "\n".join(lines)


if __name__ == '__main__':
    import doctest
    print(doctest.testmod())