| # 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]) |