diff --git a/buffer/emul.py b/buffer/emul.py index c07e31f..390334a 100644 --- a/buffer/emul.py +++ b/buffer/emul.py @@ -16,7 +16,7 @@ class XTermBuffer(Buffer, XTerm): self.modename = modename XTerm.__init__(self) Buffer.__init__(self) - #self.debug = True + self.application = app self._name = name or '*XTerm*' self._pid, self._pty = pty.fork() @@ -47,6 +47,12 @@ class XTermBuffer(Buffer, XTerm): self.insert_string(p, s, act=ACT_NONE, force=True) 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) + def term_do_style(self, s): + pass def term_do_clear(self): self.set_lines([''], force=True) def term_do_home(self): diff --git a/method/shell.py b/method/shell.py index 226be6d..4c88bba 100644 --- a/method/shell.py +++ b/method/shell.py @@ -30,19 +30,19 @@ class Exec(Method): status = os.WEXITSTATUS(result) if not os.WIFEXITED(result): - err = True - errmsg = "%s: killed by signal %r" % (cmdname, os.WTERMSIG(result)) + err = True + msg = "%s: killed by signal %r" % (cmdname, os.WTERMSIG(result)) elif status != 0: - err = True - errmsg = "%s: failed with status %r" % (cmdname, status) + err = True + msg = "%s: failed with status %r" % (cmdname, status) else: - err = False - errmsg = "%s: ok" % (cmdname,) + err = False + msg = "%s: ok" % (cmdname,) if output: switch_to = err or self.show_success w.application.data_buffer(bufname, output, switch_to=switch_to) - w.set_error(errmsg) + w.set_error(msg) def _execute(self, w, **vargs): if w.buffer.btype == 'dir': @@ -77,10 +77,10 @@ class Man(Exec): err = False errmsg = "man: ok" if output: - xterm = term.XTerm() + xterm = term.XTerm(cbuf=True) output = xterm.term_filter(output) switch_to = err or self.show_success - w.application.data_buffer('*Manpage*', output, switch_to=switch_to) + w.application.color_data_buffer('*Manpage*', output, switch_to=switch_to) w.set_error(errmsg) class Pipe(Method): diff --git a/term.py b/term.py index 0857eaa..54a01e3 100644 --- a/term.py +++ b/term.py @@ -10,8 +10,27 @@ def show(c): else: return '\\%03o' % ord(c) +cbuffer_map = { + 'black': 'B', + 'blue': 'b', + 'cyan': 'c', + 'default': 'd', + 'green': 'g', + 'magenta': 'm', + 'red': 'r', + 'white': 'w', + 'yellow': 'y', +} +def make_cbuf(fg, bg, xt): + #return '[%r, %r, %r]' % (fg, bg, xt) + if 'bold' in xt: + return '[%s:%s:*]' % (cbuffer_map[fg], cbuffer_map[bg]) + else: + return '[%s:%s]' % (cbuffer_map[fg], cbuffer_map[bg]) + class Dumb: name = 'dumb' + cbuf = False def _term_insert(self, s): assert self.i <= len(self.outc) if self.i == len(self.outc): @@ -24,16 +43,20 @@ class Dumb: self.outs = '' self.i = 0 self.outc = [] + if self.cbuf: self._term_insert(make_cbuf(self._fg, self._bg, self._xt)) + def term_do_clear_bol(self): pass def term_do_clear_eol(self): del self.outc[self.i:] + if self.cbuf: self._term_insert(make_cbuf(self._fg, self._bg, self._xt)) def term_do_clear_eos(self): pass def term_do_home(self): self.outs = '' self.i = 0 self.outc = [] + if self.cbuf: self._term_insert(make_cbuf(self._fg, self._bg, self._xt)) def term_do_backspace(self): self.i = max(0, self.i - 1) @@ -43,6 +66,7 @@ class Dumb: self.outs += ''.join(self.outc) + '\n' self.i = 0 self.outc = [] + if self.cbuf: self._term_insert(make_cbuf(self._fg, self._bg, self._xt)) def term_do_creturn(self): self.i = 0 def term_do_esc(self, c): @@ -103,9 +127,10 @@ class XTerm(Dumb): num_re = re.compile('^([a-zA-Z0-9]+)#(.+)$') str_re = re.compile('^([a-zA-Z0-9]+)=(.+)$') - style_re = re.compile('^\033[[0-9;]+m') - text_signal_re = re.compile('^\033][0-9]+;.+\007') - cup_re = re.compile('^\033\[[0-9]+;[0-9]+H') + style_re = re.compile(r'^\033\[[0-9;]+m') + #style_re = re.compile(r'^\033\[1m') + text_signal_re = re.compile(r'^\033\][0-9]+;.+\007') + cup_re = re.compile(r'^\033\[[0-9]+;[0-9]+H') callbacks = { 'clear': 'term_do_clear', @@ -135,10 +160,16 @@ class XTerm(Dumb): 'ed': 'term_do_clear_eos', 'el': 'term_do_clear_eol', #'el1': 'term_nop', - } - def __init__(self): + def __init__(self, cbuf=False): self.debug = False + self.cbuf = cbuf + + # style info + self._fg = 'default' + self._bg = 'default' + self._xt = set() + self._meta = [] f = os.popen('infocmp %s' % self.termtype, 'r') self.sequences = {} @@ -153,10 +184,58 @@ class XTerm(Dumb): m = self.str_re.match(field) assert m, "huh?? %r" % field name, val = m.groups() - if val.startswith('\\E'): + if val.startswith('\\E['): + continue + elif val.startswith('\\E'): self.sequences[val.replace('\\E', '\033')] = name f.close() + def parse_style(self, s): + # starts with '\033[' and ends with 'm' + s2 = s[2:-1] + l = s2.split(';') + #if s2 not in ('0', '22', '1'): + # raise Exception("l = %r" % l) + for n in l: + if n == '0': + self._fg = 'default' + self._bg = 'default' + self._xt = set() + # xtra attributes + elif n == '1': self._xt.add('bold') + elif n == '3': self._xt.add('italic') + elif n == '4': self._xt.add('underline') + elif n == '7': self._xt.add('inverse') + elif n == '9': self._xt.add('strike') + elif n == '22': self._xt.discard('bold') + elif n == '23': self._xt.discard('italic') + elif n == '24': self._xt.discard('underline') + elif n == '27': self._xt.discard('inverse') + elif n == '29': self._xt.discard('strike') + # foreground + elif n == '30': self._fg = 'black' + elif n == '31': self._fg = 'red' + elif n == '32': self._fg = 'green' + elif n == '33': self._fg = 'yellow' + elif n == '34': self._fg = 'blue' + elif n == '35': self._fg = 'magenta' + elif n == '36': self._fg = 'cyan' + elif n == '37': self._fg = 'white' + elif n == '39': self._fg = 'default' + # background + elif n == '40': self._bg = 'black' + elif n == '41': self._bg = 'red' + elif n == '42': self._bg = 'green' + elif n == '43': self._bg = 'yellow' + elif n == '44': self._bg = 'blue' + elif n == '45': self._bg = 'magenta' + elif n == '46': self._bg = 'cyan' + elif n == '47': self._bg = 'white' + elif n == '49': self._bg = 'default' + + def term_do_style(self): + if self.cbuf: self._term_insert(make_cbuf(self._fg, self._bg, self._xt)) + def term_nop(self, *args): pass def term_filter(self, s): @@ -174,7 +253,7 @@ class XTerm(Dumb): self._meta = self._meta[3:] if self._meta[0] != '\x1b': for c2 in self._meta[:-1]: - Dumb.term_handle(self, c) + Dumb.term_handle(self, c2) self._meta = [] if self._meta: s = ''.join(self._meta) @@ -191,6 +270,11 @@ class XTerm(Dumb): if name not in ['home']: self._meta = [] elif self.style_re.match(s): + #raise Exception('%r %d' % (s, len(s))) + self.parse_style(s) + self.term_do_style() + #if s == '\x1b[1m': raise("ARGH %r" % self.outc) + #if s == '\x1b[1m': raise("ARGH %r" % [self.outc, self._fg, self._bg, self._xt]) self._meta = [] elif self.text_signal_re.match(s): self._meta = []