summaryrefslogtreecommitdiff
path: root/src/python/m5/util/terminal_formatter.py
blob: 84c21dbe4487d34c9395a8a8604a061ce5f3a1c6 (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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Copyright (c) 2019 The Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Bobby R. Bruce



import textwrap

class TerminalFormatter:

    def __init__(self, max_width=80):
        # text_width holds the actual width we'll be wrapping to.
        # This takes into account the current terminal size.
        self.__text_width = min(max_width, self.__terminal_size()[0])

    def __terminal_size(self):
        import fcntl, termios, struct
        h, w, hp, wp = struct.unpack('HHHH',
            fcntl.ioctl(0, termios.TIOCGWINSZ,
            struct.pack('HHHH', 0, 0, 0, 0)))
        return w, h

    def __get_paragraphs(self, text, flatten=False):

        """
        This function takes a text and returns a list of constituent
        paragraphs, defining a paragraph as a block of text separated from
        other text by a blank line (or one containing only whitespace). If the
        "flatten" argument is set to true, all line breaks within paragraphs
        will be removed.

        E.g.:

        text = '''Hello, this is
        paragraph number 1.

        This is paragraph number 2.

        And this is
        paragraph number 3.
        '''

        __get_paragraphs(text, False)
        ["Hello, this is\nparagraph number 1", "This is paragraph number 2.",
            "And this is\npagraph number 3."]

        __get_paragraphs(text, True)
        ["Hello, this is paragraph number 1", "This is paragraph number 2.",
            "And this is pagraph number 3."]
        """

        paragraphs = []
        cur_paragraph = []

        for line in text.splitlines():
            stripped = line.strip()
            if not stripped: #I.e. a blank line.
                paragraphs.append(
                        {False: "\n", True: " "}[flatten].join(cur_paragraph))
                cur_paragraph = []
            else:
                cur_paragraph.append(stripped)

        paragraphs.append(
                {False: "\n", True: " "}[flatten].join(cur_paragraph))

        return paragraphs

    def format_output(self, text, label="", indent=0):
        """
        This function aids in the formatting of outputs. When obtaining
        the list of sim object we desire the output in the following
        format:

        desc: Address to mask loading binaries with, if 0,
              system auto-calculates the mask to be the most
              restrictive, otherwise it obeys a custom mask.

        We must take into account the width of the text, and wrap
        accordingly. We also must display the label.

        Keyword arguments:

        text --- The description text.
        label --- The label of the output (e.g. "desc: ").
        indent --- The white space width before each line.
        """

        if not text.strip():
            return ""

        # The text  may be over multiple lines (as when using triple
        # double quotes). First, we split the text into its constituent
        # paragraphs and remove new line characters from each.
        paragraphs = self.__get_paragraphs(text, True)

        # Wrap and Indent the paragraphs
        wrapper = textwrap.TextWrapper(width =
                max((self.__text_width - indent),1))
        # The first paragraph is special case due to the inclusion of the label
        formatted_paragraphs = [' ' * max((indent - len(label)),0) \
                + label + wrapper.wrap(paragraphs[0])[0]]
        for paragraph in paragraphs:
            for line in wrapper.wrap(paragraph[1:])[1:]:
                formatted_paragraphs.append(' ' * indent + line)
            formatted_paragraphs.append('\n')

        # Remove the last line break
        return '\n'.join(formatted_paragraphs[:-1])