pmacs3/buffer/emul.py

192 lines
5.8 KiB
Python
Raw Permalink Normal View History

import fcntl, os, select, pty, threading, time
2008-11-03 09:30:06 -05:00
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'
2008-11-03 11:50:05 -05:00
termtype = 'xterm'
delay = 0.1
bufsize = 8192
2009-03-11 23:53:56 -04:00
def __init__(self, app, cmd, args, name=None, modename=None):
if modename:
self.modename = modename
2008-11-03 09:30:06 -05:00
XTerm.__init__(self)
Buffer.__init__(self)
2008-11-08 10:30:04 -05:00
self.application = app
2008-11-03 09:30:06 -05:00
self._name = name or '*XTerm*'
self._pid, self._pty = pty.fork()
if self._pid == 0:
# child process
env = {
'TERM': self.termtype,
'PATH': os.getenv('PATH'),
'USER': os.getenv('USER'),
'HOME': os.getenv('HOME'),
}
os.execvpe(cmd, [cmd] + args, env)
2008-11-03 09:30:06 -05:00
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]):
self.insert_string(p, s, act=ACT_NONE, force=True)
2008-11-03 09:30:06 -05:00
else:
self.overwrite_char(p, s, act=ACT_NONE, force=True)
def term_do_newline(self):
XTerm.term_do_newline(self)
#p = w.logical_cursor()
#self.insert_string(p, "XYZ", act=ACT_NONE, force=True)
2009-03-16 13:53:07 -04:00
def term_do_style(self):
pass
2008-11-03 09:30:06 -05:00
def term_do_clear(self):
self.set_lines([''], force=True)
def term_do_home(self):
w = self._w()
w.cursor = w.first
2009-02-24 14:54:32 -05:00
def term_do_clear_bol(self):
w = self._w()
p2 = w.logical_cursor()
p1 = Point(0, p2.y)
2009-02-24 14:54:32 -05:00
self.delete(p1, p2, force=True)
def term_do_clear_eol(self):
w = self._w()
p1 = w.logical_cursor()
p2 = Point(len(self.lines[p1.y]), p1.y)
2009-02-24 14:54:32 -05:00
self.delete(p1, p2, force=True)
def term_do_clear_eos(self):
w = self._w()
p1 = w.logical_cursor()
p2 = self.get_buffer_end()
self.delete(p1, p2, force=True)
2009-02-24 14:54:32 -05:00
2008-11-03 09:30:06 -05:00
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()
self.insert_string(w.logical_cursor(), "\n", act=ACT_NONE, force=True)
2008-11-03 09:30:06 -05:00
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)
2008-11-08 11:37:20 -05:00
if n == 7:
#bell
pass
elif n == 8:
2008-11-03 09:30:06 -05:00
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:
2008-11-08 11:37:20 -05:00
self._term_insert('%03o' % n)
2008-11-03 09:30:06 -05:00
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
pid, status = os.waitpid(self._pid, os.WNOHANG)
if pid:
return
# wait until we are hooked up and ready to go
while not self.windows:
time.sleep(0.1)
self.application.need_draw = True
# ok, so start reading stuff!
2008-11-03 09:30:06 -05:00
try:
while not self._done:
pid, status = os.waitpid(self._pid, os.WNOHANG)
if pid:
break
2008-11-03 09:30:06 -05:00
if self._towrite:
ifd, ofd, efd = select.select([fd], [fd], [fd], self.delay)
2008-11-03 09:30:06 -05:00
else:
ifd, ofd, efd = select.select([fd], [], [fd], self.delay)
2008-11-03 09:30:06 -05:00
if ifd:
data = os.read(ifd[0], self.bufsize)
2008-11-03 09:30:06 -05:00
self.term_receive(data)
2008-11-08 10:30:04 -05:00
self.application.need_draw = True
2008-11-03 09:30:06 -05:00
if ofd:
self._lock.acquire()
n = os.write(ofd[0], self._towrite)
self._towrite = self._towrite[n:]
self._lock.release()
if efd:
self.term_receive(repr(efd))
#raise Exception, "exception is ready: %s" % repr(efd)
pass
except OSError:
2008-11-03 09:30:06 -05:00
pass
except TypeError:
raise
except AttributeError:
raise
if not pid:
pid, status = os.waitpid(self._pid, os.WNOHANG)
s = '\nprocess %d exited (%d)\n' % (pid, status >> 8)
self._term_insert(s)
self.application.need_draw = True
2008-11-03 09:30:06 -05:00
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")
def close(self):
self._done = True
self._thread.join()