1
#!/usr/bin/env python3
2

3
# Contest Management System - http://cms-dev.github.io/
4
# Copyright © 2015 Luca Versari <veluca93@gmail.com>
5
# Copyright © 2018 Luca Chiodini <luca@chiodini.org>
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU Affero General Public License as
9
# published by the Free Software Foundation, either version 3 of the
10
# License, or (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
# GNU Affero General Public License for more details.
16
#
17
# You should have received a copy of the GNU Affero General Public License
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19

20 2
import curses
21 2
import sys
22

23

24 2
class colors:
25 2
    BLACK = curses.COLOR_BLACK
26 2
    RED = curses.COLOR_RED
27 2
    GREEN = curses.COLOR_GREEN
28 2
    YELLOW = curses.COLOR_YELLOW
29 2
    BLUE = curses.COLOR_BLUE
30 2
    MAGENTA = curses.COLOR_MAGENTA
31 2
    CYAN = curses.COLOR_CYAN
32 2
    WHITE = curses.COLOR_WHITE
33

34

35 2
class directions:
36 2
    UP = 1
37 2
    DOWN = 2
38 2
    LEFT = 3
39 2
    RIGHT = 4
40

41

42 2
def has_color_support(stream):
43
    """Try to determine if the given stream supports colored output.
44

45
    Return True only if the stream declares to be a TTY, if it has a
46
    file descriptor on which ncurses can initialize a terminal and if
47
    that terminal's entry in terminfo declares support for colors.
48

49
    stream (fileobj): a file-like object (that adheres to the API
50
        declared in the `io' package).
51

52
    return (bool): True if we're sure that colors are supported, False
53
        if they aren't or if we can't tell.
54

55
    """
56 2
    if stream.isatty():
57 1
        try:
58 1
            curses.setupterm(fd=stream.fileno())
59
            # See `man terminfo` for capabilities' names and meanings.
60 1
            if curses.tigetnum("colors") > 0:
61 1
                return True
62
        # fileno() can raise OSError (since Python 3.3).
63 0
        except Exception:
64 0
            pass
65 1
    return False
66

67

68 2
def add_color_to_string(string, color, stream=sys.stdout, bold=False,
69
                        force=False):
70
    """Format the string to be printed with the given color.
71

72
    Insert formatting characters that, when printed on a terminal, will
73
    make the given string appear with the given foreground color if the
74
    stream passed has color support. Else return the string as it is.
75

76
    string (string): the string to color.
77
    color (int): the color as a colors constant, like colors.BLACK.
78
    stream (fileobj): a file-like object (that adheres to the API
79
        declared in the `io' package). Defaults to sys.stdout.
80
    bold (bool): True if the string should be bold.
81
    force (bool): True if the string should be formatted even if the
82
        given stream has no color support.
83

84
    return (string): the formatted string.
85

86
    """
87 1
    if force or has_color_support(stream):
88 1
        return "%s%s%s%s" % (
89
            curses.tparm(curses.tigetstr("setaf"), color).decode('ascii')
90
                if color != colors.BLACK else "",
91
            curses.tparm(curses.tigetstr("bold")).decode('ascii')
92
                if bold else "",
93
            string,
94
            curses.tparm(curses.tigetstr("sgr0")).decode('ascii')
95
        )
96
    else:
97 0
        return string
98

99

100 2
def move_cursor(direction, amount=1, stream=sys.stdout, erase=False):
101
    """Move the cursor.
102

103
    If the stream is a TTY, print characters that will move the cursor
104
    in the given direction and optionally erase the line. Else do nothing.
105

106
    direction (int): the direction as a directions constant, like
107
        directions.UP.
108
    stream (fileobj): a file-like object (that adheres to the API
109
        declared in the `io' package). Defaults to sys.stdout.
110
    erase (bool): True if the line the cursor ends on should be erased.
111

112
    """
113 0
    if stream.isatty():
114 0
        if direction == directions.UP:
115 0
            print(curses.tparm(curses.tigetstr("cuu"), amount).decode('ascii'),
116
                  file=stream, end='')
117 0
        elif direction == directions.DOWN:
118 0
            print(curses.tparm(curses.tigetstr("cud"), amount).decode('ascii'),
119
                  file=stream, end='')
120 0
        elif direction == directions.LEFT:
121 0
            print(curses.tparm(curses.tigetstr("cub"), amount).decode('ascii'),
122
                  file=stream, end='')
123 0
        elif direction == directions.RIGHT:
124 0
            print(curses.tparm(curses.tigetstr("cuf"), amount).decode('ascii'),
125
                  file=stream, end='')
126 0
        if erase:
127 0
            print(curses.tparm(curses.tigetstr("el")).decode('ascii'),
128
                  file=stream, end='')
129 0
        stream.flush()

Read our documentation on viewing source code .

Loading