144 lines
4.3 KiB
Python
144 lines
4.3 KiB
Python
import fcntl, os, select, pty, threading
|
|
|
|
from buffer import Buffer, ACT_NORM, ACT_NONE
|
|
from term import XTerm
|
|
from point import Point
|
|
|
|
# evil evil evil evil evil
|
|
class XTermBuffer(Buffer, XTerm):
|
|
btype = 'term'
|
|
modename = 'pipe'
|
|
termtype = 'xterm'
|
|
#termtype = 'vt100'
|
|
def __init__(self, app, cmd, args, name=None):
|
|
XTerm.__init__(self)
|
|
Buffer.__init__(self)
|
|
self.application = app
|
|
self._name = name or '*XTerm*'
|
|
self._pid, self._pty = pty.fork()
|
|
if self._pid == 0:
|
|
# child process
|
|
os.execve(cmd, [cmd] + args, {'TERM': self.termtype})
|
|
|
|
self._lock = threading.Lock()
|
|
self._towrite = ''
|
|
self._done = False
|
|
self._set_nonblock(self._pty)
|
|
self._thread = threading.Thread(target=self.pipe_read)
|
|
self._thread.setDaemon(True)
|
|
self._thread.start()
|
|
|
|
|
|
def _w(self):
|
|
return self.windows[0]
|
|
def _get_height(self):
|
|
return self._w().height
|
|
def _get_width(self):
|
|
return self._w().width
|
|
# TERM STUFF
|
|
def _term_insert(self, s):
|
|
w = self._w()
|
|
p = w.logical_cursor()
|
|
if p.x == len(self.lines[p.y]):
|
|
w.buffer.insert_string(p, s, act=ACT_NONE, force=True)
|
|
else:
|
|
w.buffer.overwrite_char(p, s, act=ACT_NONE, force=True)
|
|
def term_do_clear(self):
|
|
self.set_lines([''], force=True)
|
|
self._meta = []
|
|
def term_do_clear_bol(self):
|
|
w = self._w()
|
|
p1, p2 = w.get_line_left()
|
|
self.delete(p1, p2, force=True)
|
|
self._meta = []
|
|
def term_do_clear_eol(self):
|
|
w = self._w()
|
|
p1, p2 = w.get_line_right()
|
|
self.delete(p1, p2, force=True)
|
|
self._meta = []
|
|
def term_do_clear_eos(self):
|
|
self._meta = []
|
|
|
|
def term_do_backspace(self):
|
|
self._w().backward()
|
|
def term_do_tab(self):
|
|
self._term_insert(' ')
|
|
def term_do_newline(self):
|
|
w = self._w()
|
|
p = w.logical_cursor()
|
|
if p.y < len(self.lines) - 1:
|
|
w.start_of_line()
|
|
w.next_line()
|
|
else:
|
|
w.end_of_line()
|
|
w.buffer.insert_string(w.logical_cursor(), "\n", act=ACT_NONE, force=True)
|
|
def term_do_creturn(self):
|
|
self._w().start_of_line()
|
|
def term_do_delete(self):
|
|
self._w().delete_right()
|
|
def term_handle_print(self, c):
|
|
self._term_insert(c)
|
|
def term_handle_ctl(self, c):
|
|
n = ord(c)
|
|
if n == 7:
|
|
#bell
|
|
pass
|
|
elif n == 8:
|
|
self.term_do_backspace()
|
|
elif n == 9:
|
|
self.term_do_tab()
|
|
elif n == 10:
|
|
self.term_do_newline()
|
|
elif n == 13:
|
|
self.term_do_creturn()
|
|
elif n == 27:
|
|
self.term_do_esc(c)
|
|
elif n == 127:
|
|
self.term_do_delete()
|
|
else:
|
|
self._term_insert('%03o' % n)
|
|
|
|
def term_receive(self, s):
|
|
for c in s:
|
|
self.term_handle(c)
|
|
|
|
# BUFFER STUFF
|
|
def _set_nonblock(self, fd):
|
|
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
|
|
fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NDELAY)
|
|
|
|
def pipe_read(self):
|
|
fd = self._pty
|
|
try:
|
|
while not self._done:
|
|
if self._towrite:
|
|
ifd, ofd, efd = select.select([fd], [fd], [fd], 0.1)
|
|
else:
|
|
ifd, ofd, efd = select.select([fd], [], [fd], 0.1)
|
|
if ifd:
|
|
data = os.read(ifd[0], 1024)
|
|
self.term_receive(data)
|
|
self.application.need_draw = True
|
|
if ofd:
|
|
self._lock.acquire()
|
|
n = os.write(ofd[0], self._towrite)
|
|
self._towrite = self._towrite[n:]
|
|
self._lock.release()
|
|
if efd:
|
|
raise Exception, "exception is ready: %s" % repr(efd)
|
|
except (OSError, TypeError, AttributeError):
|
|
pass
|
|
os.close(fd)
|
|
|
|
def pipe_write(self, s):
|
|
self._lock.acquire()
|
|
self._towrite += s
|
|
self._lock.release()
|
|
|
|
def name(self): return self._name
|
|
def changed(self): return False
|
|
def readonly(self): return True
|
|
def undo(self, move, act): raise Exception, "invalid"
|
|
def redo(self, move, act): raise Exception, "invalid"
|
|
def reload(self): raise Exception, "invalid"
|