1 """This implements an ANSI terminal emulator as a subclass of screen.
3 $Id: ANSI.py 491 2007-12-16 20:04:57Z noah $
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
18 screen = fsm.memory[0]
19 screen.write_ch(fsm.input_symbol)
21 def StartNumber (fsm):
23 fsm.memory.append (fsm.input_symbol)
25 def BuildNumber (fsm):
28 ns = ns + fsm.input_symbol
29 fsm.memory.append (ns)
33 screen = fsm.memory[0]
38 count = int(fsm.memory.pop())
39 screen = fsm.memory[0]
40 screen.cursor_back (count)
44 screen = fsm.memory[0]
49 count = int(fsm.memory.pop())
50 screen = fsm.memory[0]
51 screen.cursor_down (count)
53 def DoForwardOne (fsm):
55 screen = fsm.memory[0]
56 screen.cursor_forward ()
60 count = int(fsm.memory.pop())
61 screen = fsm.memory[0]
62 screen.cursor_forward (count)
64 def DoUpReverse (fsm):
66 screen = fsm.memory[0]
67 screen.cursor_up_reverse()
71 screen = fsm.memory[0]
76 count = int(fsm.memory.pop())
77 screen = fsm.memory[0]
78 screen.cursor_up (count)
82 c = int(fsm.memory.pop())
83 r = int(fsm.memory.pop())
84 screen = fsm.memory[0]
85 screen.cursor_home (r,c)
87 def DoHomeOrigin (fsm):
91 screen = fsm.memory[0]
92 screen.cursor_home (r,c)
94 def DoEraseDown (fsm):
96 screen = fsm.memory[0]
101 arg = int(fsm.memory.pop())
102 screen = fsm.memory[0]
108 screen.erase_screen()
110 def DoEraseEndOfLine (fsm):
112 screen = fsm.memory[0]
113 screen.erase_end_of_line()
115 def DoEraseLine (fsm):
117 screen = fsm.memory[0]
121 screen.start_of_line()
125 def DoEnableScroll (fsm):
127 screen = fsm.memory[0]
128 screen.scroll_screen()
130 def DoCursorSave (fsm):
132 screen = fsm.memory[0]
133 screen.cursor_save_attrs()
135 def DoCursorRestore (fsm):
137 screen = fsm.memory[0]
138 screen.cursor_restore_attrs()
140 def DoScrollRegion (fsm):
142 screen = fsm.memory[0]
143 r2 = int(fsm.memory.pop())
144 r1 = int(fsm.memory.pop())
145 screen.scroll_screen_rows (r1,r2)
149 screen = fsm.memory[0]
150 mode = fsm.memory.pop() # Should be 4
151 # screen.setReplaceMode ()
155 screen = fsm.memory[0]
156 fsm.memory = [screen]
157 fout = open ('log', 'a')
158 fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
161 class term (screen.screen):
162 """This is a placeholder.
163 In theory I might want to add other terminal types.
165 def __init__ (self, r=24, c=80):
166 screen.screen.__init__(self, r,c)
170 """This class encapsulates a generic terminal. It filters a stream and
171 maintains the state of a screen object. """
173 def __init__ (self, r=24,c=80):
175 term.__init__(self,r,c)
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')
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')
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')
246 def process (self, c):
248 self.state.process(c)
250 def process_list (self, l):
263 def write_ch (self, ch):
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. """
269 #\r and \n both produce a call to crlf().
278 if ch == chr(screen.BS):
280 self.put_abs(self.cur_r, self.cur_c, ' ')
283 if ch not in string.printable:
284 fout = open ('log', 'a')
285 fout.write ('Nonprint: ' + str(ord(ch)) + '\n')
288 self.put_abs(self.cur_r, self.cur_c, ch)
291 self.cursor_forward()
292 if old_c == self.cur_c:
294 if old_r != self.cur_r:
295 self.cursor_home (self.cur_r, 1)
298 self.cursor_home (self.cur_r, 1)
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.)'
328 # for c in write_text:
332 #if __name__ == '__main__':