~ubuntu-branches/ubuntu/trusty/pexpect/trusty-proposed

« back to all changes in this revision

Viewing changes to screen.py

  • Committer: Package Import Robot
  • Author(s): Andrew Starr-Bochicchio, Thomas Kluyver, Jakub Wilk, Jackson Doak, Andrew Starr-Bochicchio
  • Date: 2013-12-06 20:20:26 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20131206202026-9k9oixbv7e8ke30q
Tags: 3.0-1
* Team upload.

[ Thomas Kluyver ]
* New upstream release. Closes: #729518
* Add packaging for Python 3.
* Use pybuild for packaging.

[ Jakub Wilk ]
* Use canonical URIs for Vcs-* fields.

[ Jackson Doak ]
* Create debian/python3-pexpect.docs

[ Andrew Starr-Bochicchio ]
* Remove empty debian/patches dir.
* Move documentation and examples into a new python-pexpect-doc
  package. They are shared between the Python 2 and Python 3 packages,
  so there is no need to install them with both.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
"""This implements a virtual screen. This is used to support ANSI terminal
2
 
emulation. The screen representation and state is implemented in this class.
3
 
Most of the methods are inspired by ANSI screen control codes. The ANSI class
4
 
extends this class to add parsing of ANSI escape codes.
5
 
 
6
 
$Id: screen.py 486 2007-07-13 01:04:16Z noah $
7
 
"""
8
 
 
9
 
import copy
10
 
 
11
 
NUL = 0    # Fill character; ignored on input.
12
 
ENQ = 5    # Transmit answerback message.
13
 
BEL = 7    # Ring the bell.
14
 
BS  = 8    # Move cursor left.
15
 
HT  = 9    # Move cursor to next tab stop.
16
 
LF = 10    # Line feed.
17
 
VT = 11    # Same as LF.
18
 
FF = 12    # Same as LF.
19
 
CR = 13    # Move cursor to left margin or newline.
20
 
SO = 14    # Invoke G1 character set.
21
 
SI = 15    # Invoke G0 character set.
22
 
XON = 17   # Resume transmission.
23
 
XOFF = 19  # Halt transmission.
24
 
CAN = 24   # Cancel escape sequence.
25
 
SUB = 26   # Same as CAN.
26
 
ESC = 27   # Introduce a control sequence.
27
 
DEL = 127  # Fill character; ignored on input.
28
 
SPACE = chr(32) # Space or blank character.
29
 
 
30
 
def constrain (n, min, max):
31
 
 
32
 
    """This returns a number, n constrained to the min and max bounds. """
33
 
 
34
 
    if n < min:
35
 
        return min
36
 
    if n > max:
37
 
        return max
38
 
    return n
39
 
 
40
 
class screen:
41
 
 
42
 
    """This object maintains the state of a virtual text screen as a
43
 
    rectangluar array. This maintains a virtual cursor position and handles
44
 
    scrolling as characters are added. This supports most of the methods needed
45
 
    by an ANSI text screen. Row and column indexes are 1-based (not zero-based,
46
 
    like arrays). """
47
 
 
48
 
    def __init__ (self, r=24,c=80):
49
 
 
50
 
        """This initializes a blank scree of the given dimentions."""
51
 
 
52
 
        self.rows = r
53
 
        self.cols = c
54
 
        self.cur_r = 1
55
 
        self.cur_c = 1
56
 
        self.cur_saved_r = 1
57
 
        self.cur_saved_c = 1
58
 
        self.scroll_row_start = 1
59
 
        self.scroll_row_end = self.rows
60
 
        self.w = [ [SPACE] * self.cols for c in range(self.rows)]
61
 
 
62
 
    def __str__ (self):
63
 
 
64
 
        """This returns a printable representation of the screen. The end of
65
 
        each screen line is terminated by a newline. """
66
 
 
67
 
        return '\n'.join ([ ''.join(c) for c in self.w ])
68
 
 
69
 
    def dump (self):
70
 
 
71
 
        """This returns a copy of the screen as a string. This is similar to
72
 
        __str__ except that lines are not terminated with line feeds. """
73
 
 
74
 
        return ''.join ([ ''.join(c) for c in self.w ])
75
 
 
76
 
    def pretty (self):
77
 
 
78
 
        """This returns a copy of the screen as a string with an ASCII text box
79
 
        around the screen border. This is similar to __str__ except that it
80
 
        adds a box. """
81
 
 
82
 
        top_bot = '+' + '-'*self.cols + '+\n'
83
 
        return top_bot + '\n'.join(['|'+line+'|' for line in str(self).split('\n')]) + '\n' + top_bot
84
 
 
85
 
    def fill (self, ch=SPACE):
86
 
 
87
 
        self.fill_region (1,1,self.rows,self.cols, ch)
88
 
 
89
 
    def fill_region (self, rs,cs, re,ce, ch=SPACE):
90
 
 
91
 
        rs = constrain (rs, 1, self.rows)
92
 
        re = constrain (re, 1, self.rows)
93
 
        cs = constrain (cs, 1, self.cols)
94
 
        ce = constrain (ce, 1, self.cols)
95
 
        if rs > re:
96
 
            rs, re = re, rs
97
 
        if cs > ce:
98
 
            cs, ce = ce, cs
99
 
        for r in range (rs, re+1):
100
 
            for c in range (cs, ce + 1):
101
 
                self.put_abs (r,c,ch)
102
 
 
103
 
    def cr (self):
104
 
 
105
 
        """This moves the cursor to the beginning (col 1) of the current row.
106
 
        """
107
 
 
108
 
        self.cursor_home (self.cur_r, 1)
109
 
 
110
 
    def lf (self):
111
 
 
112
 
        """This moves the cursor down with scrolling.
113
 
        """
114
 
 
115
 
        old_r = self.cur_r
116
 
        self.cursor_down()
117
 
        if old_r == self.cur_r:
118
 
            self.scroll_up ()
119
 
            self.erase_line()
120
 
 
121
 
    def crlf (self):
122
 
 
123
 
        """This advances the cursor with CRLF properties.
124
 
        The cursor will line wrap and the screen may scroll.
125
 
        """
126
 
 
127
 
        self.cr ()
128
 
        self.lf ()
129
 
 
130
 
    def newline (self):
131
 
 
132
 
        """This is an alias for crlf().
133
 
        """
134
 
 
135
 
        self.crlf()
136
 
 
137
 
    def put_abs (self, r, c, ch):
138
 
 
139
 
        """Screen array starts at 1 index."""
140
 
 
141
 
        r = constrain (r, 1, self.rows)
142
 
        c = constrain (c, 1, self.cols)
143
 
        ch = str(ch)[0]
144
 
        self.w[r-1][c-1] = ch
145
 
 
146
 
    def put (self, ch):
147
 
 
148
 
        """This puts a characters at the current cursor position.
149
 
        """
150
 
 
151
 
        self.put_abs (self.cur_r, self.cur_c, ch)
152
 
 
153
 
    def insert_abs (self, r, c, ch):
154
 
 
155
 
        """This inserts a character at (r,c). Everything under
156
 
        and to the right is shifted right one character.
157
 
        The last character of the line is lost.
158
 
        """
159
 
 
160
 
        r = constrain (r, 1, self.rows)
161
 
        c = constrain (c, 1, self.cols)
162
 
        for ci in range (self.cols, c, -1): 
163
 
            self.put_abs (r,ci, self.get_abs(r,ci-1))
164
 
        self.put_abs (r,c,ch)
165
 
 
166
 
    def insert (self, ch):
167
 
 
168
 
        self.insert_abs (self.cur_r, self.cur_c, ch)
169
 
 
170
 
    def get_abs (self, r, c):
171
 
    
172
 
        r = constrain (r, 1, self.rows)
173
 
        c = constrain (c, 1, self.cols)
174
 
        return self.w[r-1][c-1]
175
 
 
176
 
    def get (self):
177
 
 
178
 
        self.get_abs (self.cur_r, self.cur_c)
179
 
 
180
 
    def get_region (self, rs,cs, re,ce):
181
 
 
182
 
        """This returns a list of lines representing the region.
183
 
        """
184
 
 
185
 
        rs = constrain (rs, 1, self.rows)
186
 
        re = constrain (re, 1, self.rows)
187
 
        cs = constrain (cs, 1, self.cols)
188
 
        ce = constrain (ce, 1, self.cols)
189
 
        if rs > re:
190
 
            rs, re = re, rs
191
 
        if cs > ce:
192
 
            cs, ce = ce, cs
193
 
        sc = []
194
 
        for r in range (rs, re+1):
195
 
            line = ''
196
 
            for c in range (cs, ce + 1):
197
 
                ch = self.get_abs (r,c)
198
 
                line = line + ch
199
 
            sc.append (line)
200
 
        return sc
201
 
 
202
 
    def cursor_constrain (self):
203
 
 
204
 
        """This keeps the cursor within the screen area.
205
 
        """
206
 
 
207
 
        self.cur_r = constrain (self.cur_r, 1, self.rows)
208
 
        self.cur_c = constrain (self.cur_c, 1, self.cols)
209
 
 
210
 
    def cursor_home (self, r=1, c=1): # <ESC>[{ROW};{COLUMN}H
211
 
 
212
 
        self.cur_r = r
213
 
        self.cur_c = c
214
 
        self.cursor_constrain ()
215
 
 
216
 
    def cursor_back (self,count=1): # <ESC>[{COUNT}D (not confused with down)
217
 
 
218
 
        self.cur_c = self.cur_c - count
219
 
        self.cursor_constrain ()
220
 
 
221
 
    def cursor_down (self,count=1): # <ESC>[{COUNT}B (not confused with back)
222
 
 
223
 
        self.cur_r = self.cur_r + count
224
 
        self.cursor_constrain ()
225
 
 
226
 
    def cursor_forward (self,count=1): # <ESC>[{COUNT}C
227
 
 
228
 
        self.cur_c = self.cur_c + count
229
 
        self.cursor_constrain ()
230
 
 
231
 
    def cursor_up (self,count=1): # <ESC>[{COUNT}A
232
 
 
233
 
        self.cur_r = self.cur_r - count
234
 
        self.cursor_constrain ()
235
 
 
236
 
    def cursor_up_reverse (self): # <ESC> M   (called RI -- Reverse Index)
237
 
 
238
 
        old_r = self.cur_r
239
 
        self.cursor_up()
240
 
        if old_r == self.cur_r:
241
 
            self.scroll_up()
242
 
 
243
 
    def cursor_force_position (self, r, c): # <ESC>[{ROW};{COLUMN}f
244
 
 
245
 
        """Identical to Cursor Home."""
246
 
 
247
 
        self.cursor_home (r, c)
248
 
 
249
 
    def cursor_save (self): # <ESC>[s
250
 
 
251
 
        """Save current cursor position."""
252
 
 
253
 
        self.cursor_save_attrs()
254
 
 
255
 
    def cursor_unsave (self): # <ESC>[u
256
 
 
257
 
        """Restores cursor position after a Save Cursor."""
258
 
 
259
 
        self.cursor_restore_attrs()
260
 
 
261
 
    def cursor_save_attrs (self): # <ESC>7
262
 
 
263
 
        """Save current cursor position."""
264
 
 
265
 
        self.cur_saved_r = self.cur_r
266
 
        self.cur_saved_c = self.cur_c
267
 
 
268
 
    def cursor_restore_attrs (self): # <ESC>8
269
 
 
270
 
        """Restores cursor position after a Save Cursor."""
271
 
 
272
 
        self.cursor_home (self.cur_saved_r, self.cur_saved_c)
273
 
 
274
 
    def scroll_constrain (self):
275
 
 
276
 
        """This keeps the scroll region within the screen region."""
277
 
 
278
 
        if self.scroll_row_start <= 0:
279
 
            self.scroll_row_start = 1
280
 
        if self.scroll_row_end > self.rows:
281
 
            self.scroll_row_end = self.rows
282
 
 
283
 
    def scroll_screen (self): # <ESC>[r
284
 
 
285
 
        """Enable scrolling for entire display."""
286
 
 
287
 
        self.scroll_row_start = 1
288
 
        self.scroll_row_end = self.rows
289
 
 
290
 
    def scroll_screen_rows (self, rs, re): # <ESC>[{start};{end}r
291
 
 
292
 
        """Enable scrolling from row {start} to row {end}."""
293
 
 
294
 
        self.scroll_row_start = rs
295
 
        self.scroll_row_end = re
296
 
        self.scroll_constrain()
297
 
 
298
 
    def scroll_down (self): # <ESC>D
299
 
 
300
 
        """Scroll display down one line."""
301
 
 
302
 
        # Screen is indexed from 1, but arrays are indexed from 0.
303
 
        s = self.scroll_row_start - 1
304
 
        e = self.scroll_row_end - 1
305
 
        self.w[s+1:e+1] = copy.deepcopy(self.w[s:e])
306
 
 
307
 
    def scroll_up (self): # <ESC>M
308
 
 
309
 
        """Scroll display up one line."""
310
 
 
311
 
        # Screen is indexed from 1, but arrays are indexed from 0.
312
 
        s = self.scroll_row_start - 1
313
 
        e = self.scroll_row_end - 1
314
 
        self.w[s:e] = copy.deepcopy(self.w[s+1:e+1])
315
 
 
316
 
    def erase_end_of_line (self): # <ESC>[0K -or- <ESC>[K
317
 
 
318
 
        """Erases from the current cursor position to the end of the current
319
 
        line."""
320
 
 
321
 
        self.fill_region (self.cur_r, self.cur_c, self.cur_r, self.cols)
322
 
 
323
 
    def erase_start_of_line (self): # <ESC>[1K
324
 
 
325
 
        """Erases from the current cursor position to the start of the current
326
 
        line."""
327
 
 
328
 
        self.fill_region (self.cur_r, 1, self.cur_r, self.cur_c)
329
 
 
330
 
    def erase_line (self): # <ESC>[2K
331
 
 
332
 
        """Erases the entire current line."""
333
 
 
334
 
        self.fill_region (self.cur_r, 1, self.cur_r, self.cols)
335
 
 
336
 
    def erase_down (self): # <ESC>[0J -or- <ESC>[J
337
 
 
338
 
        """Erases the screen from the current line down to the bottom of the
339
 
        screen."""
340
 
 
341
 
        self.erase_end_of_line ()
342
 
        self.fill_region (self.cur_r + 1, 1, self.rows, self.cols)
343
 
 
344
 
    def erase_up (self): # <ESC>[1J
345
 
 
346
 
        """Erases the screen from the current line up to the top of the
347
 
        screen."""
348
 
 
349
 
        self.erase_start_of_line ()
350
 
        self.fill_region (self.cur_r-1, 1, 1, self.cols)
351
 
 
352
 
    def erase_screen (self): # <ESC>[2J
353
 
 
354
 
        """Erases the screen with the background color."""
355
 
 
356
 
        self.fill ()
357
 
 
358
 
    def set_tab (self): # <ESC>H
359
 
 
360
 
        """Sets a tab at the current position."""
361
 
 
362
 
        pass
363
 
 
364
 
    def clear_tab (self): # <ESC>[g
365
 
 
366
 
        """Clears tab at the current position."""
367
 
 
368
 
        pass
369
 
 
370
 
    def clear_all_tabs (self): # <ESC>[3g
371
 
 
372
 
        """Clears all tabs."""
373
 
 
374
 
        pass
375
 
 
376
 
#        Insert line             Esc [ Pn L
377
 
#        Delete line             Esc [ Pn M
378
 
#        Delete character        Esc [ Pn P
379
 
#        Scrolling region        Esc [ Pn(top);Pn(bot) r
380
 
 
 
1
import warnings
 
2
 
 
3
warnings.warn("This module has been moved to pexpect.screen, please update imports.",
 
4
                ImportWarning)
 
5
del warnings
 
6
 
 
7
from pexpect.screen import *  # analysis:ignore
 
 
b'\\ No newline at end of file'