| Index: third_party/pexpect/ANSI.py
|
| diff --git a/third_party/pexpect/ANSI.py b/third_party/pexpect/ANSI.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..537017e90b29000416e05398cecc9645eedde14d
|
| --- /dev/null
|
| +++ b/third_party/pexpect/ANSI.py
|
| @@ -0,0 +1,334 @@
|
| +"""This implements an ANSI terminal emulator as a subclass of screen.
|
| +
|
| +$Id: ANSI.py 491 2007-12-16 20:04:57Z noah $
|
| +"""
|
| +# references:
|
| +# http://www.retards.org/terminals/vt102.html
|
| +# http://vt100.net/docs/vt102-ug/contents.html
|
| +# http://vt100.net/docs/vt220-rm/
|
| +# http://www.termsys.demon.co.uk/vtansi.htm
|
| +
|
| +import screen
|
| +import FSM
|
| +import copy
|
| +import string
|
| +
|
| +def Emit (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.write_ch(fsm.input_symbol)
|
| +
|
| +def StartNumber (fsm):
|
| +
|
| + fsm.memory.append (fsm.input_symbol)
|
| +
|
| +def BuildNumber (fsm):
|
| +
|
| + ns = fsm.memory.pop()
|
| + ns = ns + fsm.input_symbol
|
| + fsm.memory.append (ns)
|
| +
|
| +def DoBackOne (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_back ()
|
| +
|
| +def DoBack (fsm):
|
| +
|
| + count = int(fsm.memory.pop())
|
| + screen = fsm.memory[0]
|
| + screen.cursor_back (count)
|
| +
|
| +def DoDownOne (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_down ()
|
| +
|
| +def DoDown (fsm):
|
| +
|
| + count = int(fsm.memory.pop())
|
| + screen = fsm.memory[0]
|
| + screen.cursor_down (count)
|
| +
|
| +def DoForwardOne (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_forward ()
|
| +
|
| +def DoForward (fsm):
|
| +
|
| + count = int(fsm.memory.pop())
|
| + screen = fsm.memory[0]
|
| + screen.cursor_forward (count)
|
| +
|
| +def DoUpReverse (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_up_reverse()
|
| +
|
| +def DoUpOne (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_up ()
|
| +
|
| +def DoUp (fsm):
|
| +
|
| + count = int(fsm.memory.pop())
|
| + screen = fsm.memory[0]
|
| + screen.cursor_up (count)
|
| +
|
| +def DoHome (fsm):
|
| +
|
| + c = int(fsm.memory.pop())
|
| + r = int(fsm.memory.pop())
|
| + screen = fsm.memory[0]
|
| + screen.cursor_home (r,c)
|
| +
|
| +def DoHomeOrigin (fsm):
|
| +
|
| + c = 1
|
| + r = 1
|
| + screen = fsm.memory[0]
|
| + screen.cursor_home (r,c)
|
| +
|
| +def DoEraseDown (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.erase_down()
|
| +
|
| +def DoErase (fsm):
|
| +
|
| + arg = int(fsm.memory.pop())
|
| + screen = fsm.memory[0]
|
| + if arg == 0:
|
| + screen.erase_down()
|
| + elif arg == 1:
|
| + screen.erase_up()
|
| + elif arg == 2:
|
| + screen.erase_screen()
|
| +
|
| +def DoEraseEndOfLine (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.erase_end_of_line()
|
| +
|
| +def DoEraseLine (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + if arg == 0:
|
| + screen.end_of_line()
|
| + elif arg == 1:
|
| + screen.start_of_line()
|
| + elif arg == 2:
|
| + screen.erase_line()
|
| +
|
| +def DoEnableScroll (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.scroll_screen()
|
| +
|
| +def DoCursorSave (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_save_attrs()
|
| +
|
| +def DoCursorRestore (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + screen.cursor_restore_attrs()
|
| +
|
| +def DoScrollRegion (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + r2 = int(fsm.memory.pop())
|
| + r1 = int(fsm.memory.pop())
|
| + screen.scroll_screen_rows (r1,r2)
|
| +
|
| +def DoMode (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + mode = fsm.memory.pop() # Should be 4
|
| + # screen.setReplaceMode ()
|
| +
|
| +def Log (fsm):
|
| +
|
| + screen = fsm.memory[0]
|
| + fsm.memory = [screen]
|
| + fout = open ('log', 'a')
|
| + fout.write (fsm.input_symbol + ',' + fsm.current_state + '\n')
|
| + fout.close()
|
| +
|
| +class term (screen.screen):
|
| + """This is a placeholder.
|
| + In theory I might want to add other terminal types.
|
| + """
|
| + def __init__ (self, r=24, c=80):
|
| + screen.screen.__init__(self, r,c)
|
| +
|
| +class ANSI (term):
|
| +
|
| + """This class encapsulates a generic terminal. It filters a stream and
|
| + maintains the state of a screen object. """
|
| +
|
| + def __init__ (self, r=24,c=80):
|
| +
|
| + term.__init__(self,r,c)
|
| +
|
| + #self.screen = screen (24,80)
|
| + self.state = FSM.FSM ('INIT',[self])
|
| + self.state.set_default_transition (Log, 'INIT')
|
| + self.state.add_transition_any ('INIT', Emit, 'INIT')
|
| + self.state.add_transition ('\x1b', 'INIT', None, 'ESC')
|
| + self.state.add_transition_any ('ESC', Log, 'INIT')
|
| + self.state.add_transition ('(', 'ESC', None, 'G0SCS')
|
| + self.state.add_transition (')', 'ESC', None, 'G1SCS')
|
| + self.state.add_transition_list ('AB012', 'G0SCS', None, 'INIT')
|
| + self.state.add_transition_list ('AB012', 'G1SCS', None, 'INIT')
|
| + self.state.add_transition ('7', 'ESC', DoCursorSave, 'INIT')
|
| + self.state.add_transition ('8', 'ESC', DoCursorRestore, 'INIT')
|
| + self.state.add_transition ('M', 'ESC', DoUpReverse, 'INIT')
|
| + self.state.add_transition ('>', 'ESC', DoUpReverse, 'INIT')
|
| + self.state.add_transition ('<', 'ESC', DoUpReverse, 'INIT')
|
| + self.state.add_transition ('=', 'ESC', None, 'INIT') # Selects application keypad.
|
| + self.state.add_transition ('#', 'ESC', None, 'GRAPHICS_POUND')
|
| + self.state.add_transition_any ('GRAPHICS_POUND', None, 'INIT')
|
| + self.state.add_transition ('[', 'ESC', None, 'ELB')
|
| + # ELB means Escape Left Bracket. That is ^[[
|
| + self.state.add_transition ('H', 'ELB', DoHomeOrigin, 'INIT')
|
| + self.state.add_transition ('D', 'ELB', DoBackOne, 'INIT')
|
| + self.state.add_transition ('B', 'ELB', DoDownOne, 'INIT')
|
| + self.state.add_transition ('C', 'ELB', DoForwardOne, 'INIT')
|
| + self.state.add_transition ('A', 'ELB', DoUpOne, 'INIT')
|
| + self.state.add_transition ('J', 'ELB', DoEraseDown, 'INIT')
|
| + self.state.add_transition ('K', 'ELB', DoEraseEndOfLine, 'INIT')
|
| + self.state.add_transition ('r', 'ELB', DoEnableScroll, 'INIT')
|
| + self.state.add_transition ('m', 'ELB', None, 'INIT')
|
| + self.state.add_transition ('?', 'ELB', None, 'MODECRAP')
|
| + self.state.add_transition_list (string.digits, 'ELB', StartNumber, 'NUMBER_1')
|
| + self.state.add_transition_list (string.digits, 'NUMBER_1', BuildNumber, 'NUMBER_1')
|
| + self.state.add_transition ('D', 'NUMBER_1', DoBack, 'INIT')
|
| + self.state.add_transition ('B', 'NUMBER_1', DoDown, 'INIT')
|
| + self.state.add_transition ('C', 'NUMBER_1', DoForward, 'INIT')
|
| + self.state.add_transition ('A', 'NUMBER_1', DoUp, 'INIT')
|
| + self.state.add_transition ('J', 'NUMBER_1', DoErase, 'INIT')
|
| + self.state.add_transition ('K', 'NUMBER_1', DoEraseLine, 'INIT')
|
| + self.state.add_transition ('l', 'NUMBER_1', DoMode, 'INIT')
|
| + ### It gets worse... the 'm' code can have infinite number of
|
| + ### number;number;number before it. I've never seen more than two,
|
| + ### but the specs say it's allowed. crap!
|
| + self.state.add_transition ('m', 'NUMBER_1', None, 'INIT')
|
| + ### LED control. Same problem as 'm' code.
|
| + self.state.add_transition ('q', 'NUMBER_1', None, 'INIT')
|
| +
|
| + # \E[?47h appears to be "switch to alternate screen"
|
| + # \E[?47l restores alternate screen... I think.
|
| + self.state.add_transition_list (string.digits, 'MODECRAP', StartNumber, 'MODECRAP_NUM')
|
| + self.state.add_transition_list (string.digits, 'MODECRAP_NUM', BuildNumber, 'MODECRAP_NUM')
|
| + self.state.add_transition ('l', 'MODECRAP_NUM', None, 'INIT')
|
| + self.state.add_transition ('h', 'MODECRAP_NUM', None, 'INIT')
|
| +
|
| +#RM Reset Mode Esc [ Ps l none
|
| + self.state.add_transition (';', 'NUMBER_1', None, 'SEMICOLON')
|
| + self.state.add_transition_any ('SEMICOLON', Log, 'INIT')
|
| + self.state.add_transition_list (string.digits, 'SEMICOLON', StartNumber, 'NUMBER_2')
|
| + self.state.add_transition_list (string.digits, 'NUMBER_2', BuildNumber, 'NUMBER_2')
|
| + self.state.add_transition_any ('NUMBER_2', Log, 'INIT')
|
| + self.state.add_transition ('H', 'NUMBER_2', DoHome, 'INIT')
|
| + self.state.add_transition ('f', 'NUMBER_2', DoHome, 'INIT')
|
| + self.state.add_transition ('r', 'NUMBER_2', DoScrollRegion, 'INIT')
|
| + ### It gets worse... the 'm' code can have infinite number of
|
| + ### number;number;number before it. I've never seen more than two,
|
| + ### but the specs say it's allowed. crap!
|
| + self.state.add_transition ('m', 'NUMBER_2', None, 'INIT')
|
| + ### LED control. Same problem as 'm' code.
|
| + self.state.add_transition ('q', 'NUMBER_2', None, 'INIT')
|
| +
|
| + def process (self, c):
|
| +
|
| + self.state.process(c)
|
| +
|
| + def process_list (self, l):
|
| +
|
| + self.write(l)
|
| +
|
| + def write (self, s):
|
| +
|
| + for c in s:
|
| + self.process(c)
|
| +
|
| + def flush (self):
|
| +
|
| + pass
|
| +
|
| + def write_ch (self, ch):
|
| +
|
| + """This puts a character at the current cursor position. cursor
|
| + position if moved forward with wrap-around, but no scrolling is done if
|
| + the cursor hits the lower-right corner of the screen. """
|
| +
|
| + #\r and \n both produce a call to crlf().
|
| + ch = ch[0]
|
| +
|
| + if ch == '\r':
|
| + # self.crlf()
|
| + return
|
| + if ch == '\n':
|
| + self.crlf()
|
| + return
|
| + if ch == chr(screen.BS):
|
| + self.cursor_back()
|
| + self.put_abs(self.cur_r, self.cur_c, ' ')
|
| + return
|
| +
|
| + if ch not in string.printable:
|
| + fout = open ('log', 'a')
|
| + fout.write ('Nonprint: ' + str(ord(ch)) + '\n')
|
| + fout.close()
|
| + return
|
| + self.put_abs(self.cur_r, self.cur_c, ch)
|
| + old_r = self.cur_r
|
| + old_c = self.cur_c
|
| + self.cursor_forward()
|
| + if old_c == self.cur_c:
|
| + self.cursor_down()
|
| + if old_r != self.cur_r:
|
| + self.cursor_home (self.cur_r, 1)
|
| + else:
|
| + self.scroll_up ()
|
| + self.cursor_home (self.cur_r, 1)
|
| + self.erase_line()
|
| +
|
| +# def test (self):
|
| +#
|
| +# import sys
|
| +# write_text = 'I\'ve got a ferret sticking up my nose.\n' + \
|
| +# '(He\'s got a ferret sticking up his nose.)\n' + \
|
| +# 'How it got there I can\'t tell\n' + \
|
| +# 'But now it\'s there it hurts like hell\n' + \
|
| +# 'And what is more it radically affects my sense of smell.\n' + \
|
| +# '(His sense of smell.)\n' + \
|
| +# 'I can see a bare-bottomed mandril.\n' + \
|
| +# '(Slyly eyeing his other nostril.)\n' + \
|
| +# 'If it jumps inside there too I really don\'t know what to do\n' + \
|
| +# 'I\'ll be the proud posessor of a kind of nasal zoo.\n' + \
|
| +# '(A nasal zoo.)\n' + \
|
| +# 'I\'ve got a ferret sticking up my nose.\n' + \
|
| +# '(And what is worst of all it constantly explodes.)\n' + \
|
| +# '"Ferrets don\'t explode," you say\n' + \
|
| +# 'But it happened nine times yesterday\n' + \
|
| +# 'And I should know for each time I was standing in the way.\n' + \
|
| +# 'I\'ve got a ferret sticking up my nose.\n' + \
|
| +# '(He\'s got a ferret sticking up his nose.)\n' + \
|
| +# 'How it got there I can\'t tell\n' + \
|
| +# 'But now it\'s there it hurts like hell\n' + \
|
| +# 'And what is more it radically affects my sense of smell.\n' + \
|
| +# '(His sense of smell.)'
|
| +# self.fill('.')
|
| +# self.cursor_home()
|
| +# for c in write_text:
|
| +# self.write_ch (c)
|
| +# print str(self)
|
| +#
|
| +#if __name__ == '__main__':
|
| +# t = ANSI(6,65)
|
| +# t.test()
|
|
|