~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to third_party/pexpect/ANSI.py

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""This implements an ANSI terminal emulator as a subclass of screen.
 
2
 
 
3
$Id: ANSI.py 491 2007-12-16 20:04:57Z noah $
 
4
"""
 
5
# references:
 
6
#     http://www.retards.org/terminals/vt102.html
 
7
#     http://vt100.net/docs/vt102-ug/contents.html
 
8
#     http://vt100.net/docs/vt220-rm/
 
9
#     http://www.termsys.demon.co.uk/vtansi.htm
 
10
 
 
11
import screen
 
12
import FSM
 
13
import copy
 
14
import string
 
15
 
 
16
def Emit (fsm):
 
17
 
 
18
    screen = fsm.memory[0]
 
19
    screen.write_ch(fsm.input_symbol)
 
20
 
 
21
def StartNumber (fsm):
 
22
 
 
23
    fsm.memory.append (fsm.input_symbol)
 
24
 
 
25
def BuildNumber (fsm):
 
26
 
 
27
    ns = fsm.memory.pop()
 
28
    ns = ns + fsm.input_symbol
 
29
    fsm.memory.append (ns)
 
30
 
 
31
def DoBackOne (fsm):
 
32
 
 
33
    screen = fsm.memory[0]
 
34
    screen.cursor_back ()
 
35
 
 
36
def DoBack (fsm):
 
37
 
 
38
    count = int(fsm.memory.pop())
 
39
    screen = fsm.memory[0]
 
40
    screen.cursor_back (count)
 
41
 
 
42
def DoDownOne (fsm):
 
43
 
 
44
    screen = fsm.memory[0]
 
45
    screen.cursor_down ()
 
46
 
 
47
def DoDown (fsm):
 
48
 
 
49
    count = int(fsm.memory.pop())
 
50
    screen = fsm.memory[0]
 
51
    screen.cursor_down (count)
 
52
 
 
53
def DoForwardOne (fsm):
 
54
 
 
55
    screen = fsm.memory[0]
 
56
    screen.cursor_forward ()
 
57
 
 
58
def DoForward (fsm):
 
59
 
 
60
    count = int(fsm.memory.pop())
 
61
    screen = fsm.memory[0]
 
62
    screen.cursor_forward (count)
 
63
 
 
64
def DoUpReverse (fsm):
 
65
 
 
66
    screen = fsm.memory[0]
 
67
    screen.cursor_up_reverse()
 
68
 
 
69
def DoUpOne (fsm):
 
70
 
 
71
    screen = fsm.memory[0]
 
72
    screen.cursor_up ()
 
73
 
 
74
def DoUp (fsm):
 
75
 
 
76
    count = int(fsm.memory.pop())
 
77
    screen = fsm.memory[0]
 
78
    screen.cursor_up (count)
 
79
 
 
80
def DoHome (fsm):
 
81
 
 
82
    c = int(fsm.memory.pop())
 
83
    r = int(fsm.memory.pop())
 
84
    screen = fsm.memory[0]
 
85
    screen.cursor_home (r,c)
 
86
 
 
87
def DoHomeOrigin (fsm):
 
88
 
 
89
    c = 1
 
90
    r = 1
 
91
    screen = fsm.memory[0]
 
92
    screen.cursor_home (r,c)
 
93
 
 
94
def DoEraseDown (fsm):
 
95
 
 
96
    screen = fsm.memory[0]
 
97
    screen.erase_down()
 
98
 
 
99
def DoErase (fsm):
 
100
 
 
101
    arg = int(fsm.memory.pop())
 
102
    screen = fsm.memory[0]
 
103
    if arg == 0:
 
104
        screen.erase_down()
 
105
    elif arg == 1:
 
106
        screen.erase_up()
 
107
    elif arg == 2:
 
108
        screen.erase_screen()
 
109
 
 
110
def DoEraseEndOfLine (fsm):
 
111
 
 
112
    screen = fsm.memory[0]
 
113
    screen.erase_end_of_line()
 
114
 
 
115
def DoEraseLine (fsm):
 
116
 
 
117
    screen = fsm.memory[0]
 
118
    if arg == 0:
 
119
        screen.end_of_line()
 
120
    elif arg == 1:
 
121
        screen.start_of_line()
 
122
    elif arg == 2:
 
123
        screen.erase_line()
 
124
 
 
125
def DoEnableScroll (fsm):
 
126
 
 
127
    screen = fsm.memory[0]
 
128
    screen.scroll_screen()
 
129
 
 
130
def DoCursorSave (fsm):
 
131
 
 
132
    screen = fsm.memory[0]
 
133
    screen.cursor_save_attrs()
 
134
 
 
135
def DoCursorRestore (fsm):
 
136
 
 
137
    screen = fsm.memory[0]
 
138
    screen.cursor_restore_attrs()
 
139
 
 
140
def DoScrollRegion (fsm):
 
141
 
 
142
    screen = fsm.memory[0]
 
143
    r2 = int(fsm.memory.pop())
 
144
    r1 = int(fsm.memory.pop())
 
145
    screen.scroll_screen_rows (r1,r2)
 
146
 
 
147
def DoMode (fsm):
 
148
 
 
149
    screen = fsm.memory[0]
 
150
    mode = fsm.memory.pop() # Should be 4
 
151
    # screen.setReplaceMode ()
 
152
 
 
153
def Log (fsm):
 
154
 
 
155
    screen = fsm.memory[0]
 
156
    fsm.memory = [screen]
 
157
    fout = open ('log', 'a')
 
158
    fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
 
159
    fout.close()
 
160
 
 
161
class term (screen.screen):
 
162
    """This is a placeholder. 
 
163
    In theory I might want to add other terminal types.
 
164
    """
 
165
    def __init__ (self, r=24, c=80):
 
166
        screen.screen.__init__(self, r,c)
 
167
 
 
168
class ANSI (term):
 
169
 
 
170
    """This class encapsulates a generic terminal. It filters a stream and
 
171
    maintains the state of a screen object. """
 
172
 
 
173
    def __init__ (self, r=24,c=80):
 
174
 
 
175
        term.__init__(self,r,c)
 
176
 
 
177
        #self.screen = screen (24,80)
 
178
        self.state = FSM.FSM ('INIT',[self])
 
179
        self.state.set_default_transition (Log, 'INIT')
 
180
        self.state.add_transition_any ('INIT', Emit, 'INIT')
 
181
        self.state.add_transition ('\x1b', 'INIT', None, 'ESC')
 
182
        self.state.add_transition_any ('ESC', Log, 'INIT')
 
183
        self.state.add_transition ('(', 'ESC', None, 'G0SCS')
 
184
        self.state.add_transition (')', 'ESC', None, 'G1SCS')
 
185
        self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT')
 
186
        self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT')
 
187
        self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT')
 
188
        self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT')
 
189
        self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT')
 
190
        self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT')
 
191
        self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT')
 
192
        self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad.
 
193
        self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND')
 
194
        self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT')
 
195
        self.state.add_transition ('[', 'ESC', None, 'ELB')
 
196
        # ELB means Escape Left Bracket. That is ^[[
 
197
        self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT')
 
198
        self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT')
 
199
        self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT')
 
200
        self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT')
 
201
        self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT')
 
202
        self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT')
 
203
        self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT')
 
204
        self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT')
 
205
        self.state.add_transition ('m', 'ELB', None, 'INIT')
 
206
        self.state.add_transition ('?', 'ELB', None, 'MODECRAP')
 
207
        self.state.add_transition_list (string.digits, 'ELB', StartNumber, 'NUMBER_1')
 
208
        self.state.add_transition_list (string.digits, 'NUMBER_1', BuildNumber, 'NUMBER_1')
 
209
        self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT')
 
210
        self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT')
 
211
        self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT')
 
212
        self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT')
 
213
        self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT')
 
214
        self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT')
 
215
        self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT')
 
216
        ### It gets worse... the 'm' code can have infinite number of
 
217
        ### number;number;number before it. I've never seen more than two,
 
218
        ### but the specs say it's allowed. crap!
 
219
        self.state.add_transition ('m', 'NUMBER_1', None, 'INIT')
 
220
        ### LED control. Same problem as 'm' code.
 
221
        self.state.add_transition ('q', 'NUMBER_1', None, 'INIT') 
 
222
        
 
223
        # \E[?47h appears to be "switch to alternate screen"
 
224
        # \E[?47l restores alternate screen... I think.
 
225
        self.state.add_transition_list (string.digits, 'MODECRAP', StartNumber, 'MODECRAP_NUM')
 
226
        self.state.add_transition_list (string.digits, 'MODECRAP_NUM', BuildNumber, 'MODECRAP_NUM')
 
227
        self.state.add_transition ('l', 'MODECRAP_NUM', None, 'INIT')
 
228
        self.state.add_transition ('h', 'MODECRAP_NUM', None, 'INIT')
 
229
 
 
230
#RM   Reset Mode                Esc [ Ps l                   none
 
231
        self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON')
 
232
        self.state.add_transition_any ('SEMICOLON', Log, 'INIT')
 
233
        self.state.add_transition_list (string.digits, 'SEMICOLON', StartNumber, 'NUMBER_2')
 
234
        self.state.add_transition_list (string.digits, 'NUMBER_2', BuildNumber, 'NUMBER_2')
 
235
        self.state.add_transition_any ('NUMBER_2', Log, 'INIT')
 
236
        self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT')
 
237
        self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT')
 
238
        self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT')
 
239
        ### It gets worse... the 'm' code can have infinite number of
 
240
        ### number;number;number before it. I've never seen more than two,
 
241
        ### but the specs say it's allowed. crap!
 
242
        self.state.add_transition ('m', 'NUMBER_2', None, 'INIT')
 
243
        ### LED control. Same problem as 'm' code.
 
244
        self.state.add_transition ('q', 'NUMBER_2', None, 'INIT') 
 
245
 
 
246
    def process (self, c):
 
247
 
 
248
        self.state.process(c)
 
249
 
 
250
    def process_list (self, l):
 
251
 
 
252
        self.write(l)
 
253
 
 
254
    def write (self, s):
 
255
 
 
256
        for c in s:
 
257
            self.process(c)
 
258
 
 
259
    def flush (self):
 
260
 
 
261
        pass
 
262
 
 
263
    def write_ch (self, ch):
 
264
 
 
265
        """This puts a character at the current cursor position. cursor
 
266
        position if moved forward with wrap-around, but no scrolling is done if
 
267
        the cursor hits the lower-right corner of the screen. """
 
268
 
 
269
        #\r and \n both produce a call to crlf().
 
270
        ch = ch[0]
 
271
 
 
272
        if ch == '\r':
 
273
        #    self.crlf()
 
274
            return
 
275
        if ch == '\n':
 
276
            self.crlf()
 
277
            return
 
278
        if ch == chr(screen.BS):
 
279
            self.cursor_back()
 
280
            self.put_abs(self.cur_r, self.cur_c, ' ')
 
281
            return
 
282
 
 
283
        if ch not in string.printable:
 
284
            fout = open ('log', 'a')
 
285
            fout.write ('Nonprint: ' + str(ord(ch)) + '\n')
 
286
            fout.close()
 
287
            return
 
288
        self.put_abs(self.cur_r, self.cur_c, ch)
 
289
        old_r = self.cur_r
 
290
        old_c = self.cur_c
 
291
        self.cursor_forward()
 
292
        if old_c == self.cur_c:
 
293
            self.cursor_down()
 
294
            if old_r != self.cur_r:
 
295
                self.cursor_home (self.cur_r, 1)
 
296
            else:
 
297
                self.scroll_up ()
 
298
                self.cursor_home (self.cur_r, 1)
 
299
                self.erase_line()
 
300
 
 
301
#    def test (self):
 
302
#
 
303
#        import sys
 
304
#        write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
 
305
#        '(He\'s got a ferret sticking up his nose.)\n' + \
 
306
#        'How it got there I can\'t tell\n' + \
 
307
#        'But now it\'s there it hurts like hell\n' + \
 
308
#        'And what is more it radically affects my sense of smell.\n' + \
 
309
#        '(His sense of smell.)\n' + \
 
310
#        'I can see a bare-bottomed mandril.\n' + \
 
311
#        '(Slyly eyeing his other nostril.)\n' + \
 
312
#        'If it jumps inside there too I really don\'t know what to do\n' + \
 
313
#        'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
 
314
#        '(A nasal zoo.)\n' + \
 
315
#        'I\'ve got a ferret sticking up my nose.\n' + \
 
316
#        '(And what is worst of all it constantly explodes.)\n' + \
 
317
#        '"Ferrets don\'t explode," you say\n' + \
 
318
#        'But it happened nine times yesterday\n' + \
 
319
#        'And I should know for each time I was standing in the way.\n' + \
 
320
#        'I\'ve got a ferret sticking up my nose.\n' + \
 
321
#        '(He\'s got a ferret sticking up his nose.)\n' + \
 
322
#        'How it got there I can\'t tell\n' + \
 
323
#        'But now it\'s there it hurts like hell\n' + \
 
324
#        'And what is more it radically affects my sense of smell.\n' + \
 
325
#        '(His sense of smell.)'
 
326
#        self.fill('.')
 
327
#        self.cursor_home()
 
328
#        for c in write_text:
 
329
#            self.write_ch (c)
 
330
#        print str(self)
 
331
#
 
332
#if __name__ == '__main__':
 
333
#    t = ANSI(6,65)
 
334
#    t.test()