diff options
| author | Thomas Kluyver <takowl@gmail.com> | 2013-09-19 16:58:47 -0700 |
|---|---|---|
| committer | Thomas Kluyver <takowl@gmail.com> | 2013-09-19 16:58:47 -0700 |
| commit | cdd2e23fe1ee37c57fef8358f2d776eaacec7e3b (patch) | |
| tree | 1690be5b58577a026166cf691244b2fec1b3c9a4 /ANSI.py | |
| parent | 4dab541fcbb826e7e807aee31f10327438938730 (diff) | |
| download | pexpect-cdd2e23fe1ee37c57fef8358f2d776eaacec7e3b.tar.gz | |
Move ANSI -> pexpect.ANSI
Diffstat (limited to 'ANSI.py')
| -rw-r--r-- | ANSI.py | 371 |
1 files changed, 5 insertions, 366 deletions
@@ -1,368 +1,7 @@ -'''This implements an ANSI (VT100) terminal emulator as a subclass of screen. +import warnings -PEXPECT LICENSE +warnings.warn("This module has been moved to pexpect.ANSI, please update imports.", + ImportWarning) +del warnings - This license is approved by the OSI and FSF as GPL-compatible. - http://opensource.org/licenses/isc-license.txt - - Copyright (c) 2012, Noah Spurrier <noah@noah.org> - PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY - PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE - COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -''' - -# references: -# http://en.wikipedia.org/wiki/ANSI_escape_code -# 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 - -# -# The 'Do.*' functions are helper functions for the ANSI class. -# -def DoEmit (fsm): - - screen = fsm.memory[0] - screen.write_ch(fsm.input_symbol) - -def DoStartNumber (fsm): - - fsm.memory.append (fsm.input_symbol) - -def DoBuildNumber (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): - - arg = int(fsm.memory.pop()) - screen = fsm.memory[0] - if arg == 0: - screen.erase_end_of_line() - elif arg == 1: - screen.erase_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 DoLog (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 class is an abstract, generic terminal. - This does nothing. This is a placeholder that - provides a common base class for other terminals - such as an ANSI terminal. ''' - - def __init__ (self, r=24, c=80): - - screen.screen.__init__(self, r,c) - -class ANSI (term): - - '''This class implements an ANSI (VT100) terminal. - It is a stream filter that recognizes ANSI terminal - escape sequences 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 (DoLog, 'INIT') - self.state.add_transition_any ('INIT', DoEmit, 'INIT') - self.state.add_transition ('\x1b', 'INIT', None, 'ESC') - self.state.add_transition_any ('ESC', DoLog, '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', DoStartNumber, 'NUMBER_1') - self.state.add_transition_list (string.digits, 'NUMBER_1', DoBuildNumber, '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 implementation problem as 'm' code. - self.state.add_transition ('q', 'NUMBER_1', None, 'INIT') - - # \E[?47h switch to alternate screen - # \E[?47l restores to normal screen from alternate screen. - self.state.add_transition_list (string.digits, 'MODECRAP', DoStartNumber, 'MODECRAP_NUM') - self.state.add_transition_list (string.digits, 'MODECRAP_NUM', DoBuildNumber, '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', DoLog, 'INIT') - self.state.add_transition_list (string.digits, 'SEMICOLON', DoStartNumber, 'NUMBER_2') - self.state.add_transition_list (string.digits, 'NUMBER_2', DoBuildNumber, 'NUMBER_2') - self.state.add_transition_any ('NUMBER_2', DoLog, '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') - self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X') - - # Create a state for 'q' and 'm' which allows an infinite number of ignored numbers - self.state.add_transition_any ('SEMICOLON_X', DoLog, 'INIT') - self.state.add_transition_list (string.digits, 'SEMICOLON_X', None, 'NUMBER_X') - self.state.add_transition_any ('NUMBER_X', DoLog, 'INIT') - self.state.add_transition ('m', 'NUMBER_X', None, 'INIT') - self.state.add_transition ('q', 'NUMBER_X', None, 'INIT') - self.state.add_transition (';', 'NUMBER_2', None, 'SEMICOLON_X') - - 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. The cursor - position is 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 cr() and lf(), respectively. - ch = ch[0] - - if ch == '\r': - self.cr() - return - if ch == '\n': - self.crlf() - return - if ch == chr(screen.BS): - self.cursor_back() - 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() +from pexpect.ANSI import * # analysis:ignore
\ No newline at end of file |
