Issues (8)

neovim_gui/screen.py (1 issue)

1
"""Common code for graphical and text UIs."""
2
from neovim.compat import IS_PYTHON3
3
4
5
__all__ = ('Screen',)
6
7
8
if not IS_PYTHON3:
9
    range = xrange  # NOQA
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'xrange'
Loading history...
10
11
12
class Cell(object):
13
    def __init__(self):
14
        self.text = ' '
15
        self.attrs = None
16
17
    def __repr__(self):
18
        return self.text
19
20
    def get(self):
21
        return self.text, self.attrs
22
23
    def set(self, text, attrs):
24
        self.text = text
25
        self.attrs = attrs
26
27
    def copy(self, other):
28
        other.text = self.text
29
        other.attrs = self.attrs
30
31
32
class Screen(object):
33
34
    """Store nvim screen state."""
35
36
    def __init__(self, columns, rows):
37
        """Initialize the Screen instance."""
38
        self.columns = columns
39
        self.rows = rows
40
        self.row = 0
41
        self.col = 0
42
        self.top = 0
43
        self.bot = rows - 1
44
        self.left = 0
45
        self.right = columns - 1
46
        self._cells = [[Cell() for c in range(columns)] for r in range(rows)]
47
48
    def clear(self):
49
        """Clear the screen."""
50
        self._clear_region(self.top, self.bot, self.left, self.right)
51
52
    def eol_clear(self):
53
        """Clear from the cursor position to the end of the scroll region."""
54
        self._clear_region(self.row, self.row, self.col, self.right)
55
56
    def cursor_goto(self, row, col):
57
        """Change the virtual cursor position."""
58
        self.row = row
59
        self.col = col
60
61
    def set_scroll_region(self, top, bot, left, right):
62
        """Change scroll region."""
63
        self.top = top
64
        self.bot = bot
65
        self.left = left
66
        self.right = right
67
68
    def scroll(self, count):
69
        """Shift scroll region."""
70
        top, bot = self.top, self.bot
71
        left, right = self.left, self.right
72
        if count > 0:
73
            start = top
74
            stop = bot - count + 1
75
            step = 1
76
        else:
77
            start = bot
78
            stop = top - count - 1
79
            step = -1
80
        # shift the cells
81
        for row in range(start, stop, step):
82
            target_row = self._cells[row]
83
            source_row = self._cells[row + count]
84
            for col in range(left, right + 1):
85
                tgt = target_row[col]
86
                source_row[col].copy(tgt)
87
        # clear invalid cells
88
        for row in range(stop, stop + count, step):
89
            self._clear_region(row, row, left, right)
90
91
    def put(self, text, attrs):
92
        """Put character on virtual cursor position."""
93
        cell = self._cells[self.row][self.col]
94
        cell.set(text, attrs)
95
        self.cursor_goto(self.row, self.col + 1)
96
97
    def get_cell(self, row, col):
98
        """Get text, attrs at row, col."""
99
        return self._cells[row][col].get()
100
101
    def get_cursor(self):
102
        """Get text, attrs at the virtual cursor position."""
103
        return self.get_cell(self.row, self.col)
104
105
    def iter(self, startrow, endrow, startcol, endcol):
106
        """Extract text/attrs at row, startcol-endcol."""
107
        for row in range(startrow, endrow + 1):
108
            r = self._cells[row]
109
            cell = r[startcol]
110
            curcol = startcol
111
            attrs = cell.attrs
112
            buf = [cell.text]
113
            for col in range(startcol + 1, endcol + 1):
114
                cell = r[col]
115
                if cell.attrs != attrs or not cell.text:
116
                    yield row, curcol, ''.join(buf), attrs
117
                    attrs = cell.attrs
118
                    buf = [cell.text]
119
                    curcol = col
120
                    if not cell.text:
121
                        # glyph uses two cells, yield a separate entry
122
                        yield row, curcol, '', None
123
                        curcol += 1
124
                else:
125
                    buf.append(cell.text)
126
            if buf:
127
                yield row, curcol, ''.join(buf), attrs
128
129
    def _clear_region(self, top, bot, left, right):
130
        for rownum in range(top, bot + 1):
131
            row = self._cells[rownum]
132
            for colnum in range(left, right + 1):
133
                cell = row[colnum]
134
                cell.set(' ', None)
135