xref: /openbmc/u-boot/tools/patman/terminal.py (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
11a459660SWolfgang Denk# SPDX-License-Identifier: GPL-2.0+
2*83d290c5STom Rini# Copyright (c) 2011 The Chromium OS Authors.
30d24de9dSSimon Glass#
40d24de9dSSimon Glass
50d24de9dSSimon Glass"""Terminal utilities
60d24de9dSSimon Glass
70d24de9dSSimon GlassThis module handles terminal interaction including ANSI color codes.
80d24de9dSSimon Glass"""
90d24de9dSSimon Glass
10a920a17bSPaul Burtonfrom __future__ import print_function
11a920a17bSPaul Burton
12bbd01435SSimon Glassimport os
13bbd01435SSimon Glassimport sys
14bbd01435SSimon Glass
15bbd01435SSimon Glass# Selection of when we want our output to be colored
16bbd01435SSimon GlassCOLOR_IF_TERMINAL, COLOR_ALWAYS, COLOR_NEVER = range(3)
17bbd01435SSimon Glass
183c6c0f81SSimon Glass# Initially, we are set up to print to the terminal
193c6c0f81SSimon Glassprint_test_mode = False
203c6c0f81SSimon Glassprint_test_list = []
213c6c0f81SSimon Glass
223c6c0f81SSimon Glassclass PrintLine:
233c6c0f81SSimon Glass    """A line of text output
243c6c0f81SSimon Glass
253c6c0f81SSimon Glass    Members:
263c6c0f81SSimon Glass        text: Text line that was printed
273c6c0f81SSimon Glass        newline: True to output a newline after the text
283c6c0f81SSimon Glass        colour: Text colour to use
293c6c0f81SSimon Glass    """
303c6c0f81SSimon Glass    def __init__(self, text, newline, colour):
313c6c0f81SSimon Glass        self.text = text
323c6c0f81SSimon Glass        self.newline = newline
333c6c0f81SSimon Glass        self.colour = colour
343c6c0f81SSimon Glass
353c6c0f81SSimon Glass    def __str__(self):
363c6c0f81SSimon Glass        return 'newline=%s, colour=%s, text=%s' % (self.newline, self.colour,
373c6c0f81SSimon Glass                self.text)
383c6c0f81SSimon Glass
393c6c0f81SSimon Glassdef Print(text='', newline=True, colour=None):
403c6c0f81SSimon Glass    """Handle a line of output to the terminal.
413c6c0f81SSimon Glass
423c6c0f81SSimon Glass    In test mode this is recorded in a list. Otherwise it is output to the
433c6c0f81SSimon Glass    terminal.
443c6c0f81SSimon Glass
453c6c0f81SSimon Glass    Args:
463c6c0f81SSimon Glass        text: Text to print
473c6c0f81SSimon Glass        newline: True to add a new line at the end of the text
483c6c0f81SSimon Glass        colour: Colour to use for the text
493c6c0f81SSimon Glass    """
503c6c0f81SSimon Glass    if print_test_mode:
513c6c0f81SSimon Glass        print_test_list.append(PrintLine(text, newline, colour))
523c6c0f81SSimon Glass    else:
533c6c0f81SSimon Glass        if colour:
543c6c0f81SSimon Glass            col = Color()
553c6c0f81SSimon Glass            text = col.Color(colour, text)
56a920a17bSPaul Burton        print(text, end='')
573c6c0f81SSimon Glass        if newline:
58a920a17bSPaul Burton            print()
598b4919edSSimon Glass        else:
608b4919edSSimon Glass            sys.stdout.flush()
613c6c0f81SSimon Glass
623c6c0f81SSimon Glassdef SetPrintTestMode():
633c6c0f81SSimon Glass    """Go into test mode, where all printing is recorded"""
643c6c0f81SSimon Glass    global print_test_mode
653c6c0f81SSimon Glass
663c6c0f81SSimon Glass    print_test_mode = True
673c6c0f81SSimon Glass
683c6c0f81SSimon Glassdef GetPrintTestLines():
693c6c0f81SSimon Glass    """Get a list of all lines output through Print()
703c6c0f81SSimon Glass
713c6c0f81SSimon Glass    Returns:
723c6c0f81SSimon Glass        A list of PrintLine objects
733c6c0f81SSimon Glass    """
743c6c0f81SSimon Glass    global print_test_list
753c6c0f81SSimon Glass
763c6c0f81SSimon Glass    ret = print_test_list
773c6c0f81SSimon Glass    print_test_list = []
783c6c0f81SSimon Glass    return ret
793c6c0f81SSimon Glass
803c6c0f81SSimon Glassdef EchoPrintTestLines():
813c6c0f81SSimon Glass    """Print out the text lines collected"""
823c6c0f81SSimon Glass    for line in print_test_list:
833c6c0f81SSimon Glass        if line.colour:
843c6c0f81SSimon Glass            col = Color()
85a920a17bSPaul Burton            print(col.Color(line.colour, line.text), end='')
863c6c0f81SSimon Glass        else:
87a920a17bSPaul Burton            print(line.text, end='')
883c6c0f81SSimon Glass        if line.newline:
89a920a17bSPaul Burton            print()
903c6c0f81SSimon Glass
913c6c0f81SSimon Glass
920d24de9dSSimon Glassclass Color(object):
930d24de9dSSimon Glass    """Conditionally wraps text in ANSI color escape sequences."""
940d24de9dSSimon Glass    BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
950d24de9dSSimon Glass    BOLD = -1
9643bca004SSimon Glass    BRIGHT_START = '\033[1;%dm'
9743bca004SSimon Glass    NORMAL_START = '\033[22;%dm'
980d24de9dSSimon Glass    BOLD_START = '\033[1m'
990d24de9dSSimon Glass    RESET = '\033[0m'
1000d24de9dSSimon Glass
101bbd01435SSimon Glass    def __init__(self, colored=COLOR_IF_TERMINAL):
1020d24de9dSSimon Glass        """Create a new Color object, optionally disabling color output.
1030d24de9dSSimon Glass
1040d24de9dSSimon Glass        Args:
1050d24de9dSSimon Glass          enabled: True if color output should be enabled. If False then this
1060d24de9dSSimon Glass            class will not add color codes at all.
1070d24de9dSSimon Glass        """
108e752edcbSSimon Glass        try:
109bbd01435SSimon Glass            self._enabled = (colored == COLOR_ALWAYS or
110e752edcbSSimon Glass                    (colored == COLOR_IF_TERMINAL and
111e752edcbSSimon Glass                     os.isatty(sys.stdout.fileno())))
112e752edcbSSimon Glass        except:
113e752edcbSSimon Glass            self._enabled = False
1140d24de9dSSimon Glass
11543bca004SSimon Glass    def Start(self, color, bright=True):
1160d24de9dSSimon Glass        """Returns a start color code.
1170d24de9dSSimon Glass
1180d24de9dSSimon Glass        Args:
1190d24de9dSSimon Glass          color: Color to use, .e.g BLACK, RED, etc.
1200d24de9dSSimon Glass
1210d24de9dSSimon Glass        Returns:
1226ba5737fSSimon Glass          If color is enabled, returns an ANSI sequence to start the given
1236ba5737fSSimon Glass          color, otherwise returns empty string
1240d24de9dSSimon Glass        """
1250d24de9dSSimon Glass        if self._enabled:
12643bca004SSimon Glass            base = self.BRIGHT_START if bright else self.NORMAL_START
12743bca004SSimon Glass            return base % (color + 30)
1280d24de9dSSimon Glass        return ''
1290d24de9dSSimon Glass
1300d24de9dSSimon Glass    def Stop(self):
1310d24de9dSSimon Glass        """Retruns a stop color code.
1320d24de9dSSimon Glass
1330d24de9dSSimon Glass        Returns:
1346ba5737fSSimon Glass          If color is enabled, returns an ANSI color reset sequence,
1356ba5737fSSimon Glass          otherwise returns empty string
1360d24de9dSSimon Glass        """
1370d24de9dSSimon Glass        if self._enabled:
1380d24de9dSSimon Glass            return self.RESET
1390d24de9dSSimon Glass        return ''
1400d24de9dSSimon Glass
14143bca004SSimon Glass    def Color(self, color, text, bright=True):
1420d24de9dSSimon Glass        """Returns text with conditionally added color escape sequences.
1430d24de9dSSimon Glass
1440d24de9dSSimon Glass        Keyword arguments:
1456ba5737fSSimon Glass          color: Text color -- one of the color constants defined in this
1466ba5737fSSimon Glass                  class.
1470d24de9dSSimon Glass          text: The text to color.
1480d24de9dSSimon Glass
1490d24de9dSSimon Glass        Returns:
1500d24de9dSSimon Glass          If self._enabled is False, returns the original text. If it's True,
1516ba5737fSSimon Glass          returns text with color escape sequences based on the value of
1526ba5737fSSimon Glass          color.
1530d24de9dSSimon Glass        """
1540d24de9dSSimon Glass        if not self._enabled:
1550d24de9dSSimon Glass            return text
1560d24de9dSSimon Glass        if color == self.BOLD:
1570d24de9dSSimon Glass            start = self.BOLD_START
1580d24de9dSSimon Glass        else:
15943bca004SSimon Glass            base = self.BRIGHT_START if bright else self.NORMAL_START
16043bca004SSimon Glass            start = base % (color + 30)
1610d24de9dSSimon Glass        return start + text + self.RESET
162