summaryrefslogtreecommitdiffstats
path: root/cli_helpers/tabular_output/terminaltables_adapter.py
blob: b9c7497238b8e0ab2b011b24e1f527c56696a141 (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
# -*- coding: utf-8 -*-
"""Format adapter for the terminaltables module."""

from __future__ import unicode_literals

import terminaltables
import itertools

from cli_helpers.utils import filter_dict_by_key
from cli_helpers.compat import (Terminal256Formatter, StringIO)
from .preprocessors import (convert_to_string, truncate_string, override_missing_value,
                            style_output, HAS_PYGMENTS,
                            override_tab_value, escape_newlines)

supported_formats = ('ascii', 'double', 'github')
preprocessors = (
    override_missing_value, convert_to_string, override_tab_value,
    truncate_string, style_output, escape_newlines
)

table_format_handler = {
    'ascii': terminaltables.AsciiTable,
    'double': terminaltables.DoubleTable,
    'github': terminaltables.GithubFlavoredMarkdownTable,
}


def style_output_table(format_name=""):
    def style_output(data, headers, style=None,
                     table_separator_token='Token.Output.TableSeparator', **_):
        """Style the *table* (e.g. bold, italic, and colors)

        .. NOTE::
            This requires the `Pygments <http://pygments.org/>`_ library to
            be installed. You can install it with CLI Helpers as an extra::
                $ pip install cli_helpers[styles]

        Example usage::

            from cli_helpers.tabular_output import terminaltables_adapter
            from pygments.style import Style
            from pygments.token import Token

            class YourStyle(Style):
                default_style = ""
                styles = {
                    Token.Output.TableSeparator: '#ansigray'
                }

            headers = ('First Name', 'Last Name')
            data = [['Fred', 'Roberts'], ['George', 'Smith']]
            style_output_table = terminaltables_adapter.style_output_table('psql')
            style_output_table(data, headers, style=CliStyle)

            output = terminaltables_adapter.adapter(data, headers, style=YourStyle)

        :param iterable data: An :term:`iterable` (e.g. list) of rows.
        :param iterable headers: The column headers.
        :param str/pygments.style.Style style: A Pygments style. You can `create
            your own styles <https://pygments.org/docs/styles#creating-own-styles>`_.
        :param str table_separator_token: The token type to be used for the table separator.
        :return: data and headers.
        :rtype: tuple

        """
        if style and HAS_PYGMENTS and format_name in supported_formats:
            formatter = Terminal256Formatter(style=style)

            def style_field(token, field):
                """Get the styled text for a *field* using *token* type."""
                s = StringIO()
                formatter.format(((token, field),), s)
                return s.getvalue()

            clss = table_format_handler[format_name]
            for char in [char for char in terminaltables.base_table.BaseTable.__dict__ if char.startswith("CHAR_")]:
                setattr(clss, char, style_field(
                    table_separator_token, getattr(clss, char)))

        return iter(data), headers
    return style_output


def adapter(data, headers, table_format=None, **kwargs):
    """Wrap terminaltables inside a function for TabularOutputFormatter."""
    keys = ('title', )

    table = table_format_handler[table_format]

    t = table([headers] + list(data), **filter_dict_by_key(kwargs, keys))

    dimensions = terminaltables.width_and_alignment.max_dimensions(
        t.table_data,
        t.padding_left,
        t.padding_right)[:3]
    for r in t.gen_table(*dimensions):
        yield u''.join(r)