import code, os, re, string, StringIO, sys, traceback import buffer, color, completer, lex, method, mode, window from lex import Grammar, PatternRule from mode.sh import ShGrammar from point import Point from method import Method from subprocess import Popen, PIPE, STDOUT #PAD = ' ' PAD = '' LIMIT = 79 class ShellExec(Method): sequences = { '\x1b[01;32m': "[green:default]", '\x1b[01;34m': "[blue:default]", '\x1b[01;36m': "[cyan:default]", '\x1b[0m': "[default:default]", } def _execute(self, w, **vargs): a = w.application if a.completion_window_is_open(): a.close_completion_buffer() s = w.buffer.make_string() w.mode.history[-1] = s w.mode.history.append('') w.buffer.set_data('') w.mode.hindex = len(w.mode.history) - 1 if not a.has_buffer_name('*Shell*'): raise Exception, "No shell found!" b = a.bufferlist.get_buffer_by_name('*Shell*') if a.window().buffer is not b: a.switch_buffer(b) p = a.get_mini_buffer_prompt() b.insert_string(b.get_buffer_end(), p + s + '\n', force=True) a.set_mini_buffer_prompt('sh$ ') ok = True args = ['sh', '-c', s] env = {'COLUMNS': '80', 'LINES': '24', 'TERM': os.environ['TERM']} p = Popen(args, bufsize=1024, stderr=STDOUT, stdout=PIPE, close_fds=True, env=env) output = p.stdout.read() output2 = [] i = 0 escaped = [] for c in output: if escaped: escaped.append(c) if c == 'm': seq = ''.join(escaped) if seq in self.sequences: #output2.append(self.sequences[seq]) output2.append('{foo:bar}') escaped = [] elif c == '\x1b': escaped.append(c) elif c == '\n': output2.append(c) i = 0 elif c == '\t': j = i % 8 output2.append(' ' * (8 - j)) i += 8 - j elif c == '\a': pass elif c == '\b': if i > 0: output2.pop(-1) i -= 1 else: output2.append(c) i += 1 output = ''.join(output2) limit = 1000 for w2 in b.windows: limit = min(w.width, limit) if limit == 1000: limit = LIMIT limit -= len(PAD) if output: newlines = [] for line in output.split('\n'): line = line.replace('\x1b[01;32m', "[green:default]") line = line.replace('\x1b[01;34m', "[blue:default]") line = line.replace('\x1b[01;36m', "[cyan:default]") line = line.replace('\x1b[0m', "[default:default]") #line = repr(line) i = 0 while i + limit < len(line): j = limit while j > 0 and line[i + j] != ' ': j -= 1 if j == 0: newlines.append(PAD + line[i:i + limit]) i += j else: newlines.append(PAD + line[i:i + j]) i += j + 1 newlines.append(PAD + line[i:]) #assert newlines[-1] == PAD newlines[-1] = '' #b.insert_lines(b.get_buffer_end(), newlines, force=True) #b.set_lines(newlines, force=True) b.set_data("\n".join(newlines)) for w2 in b.windows: w2.goto_end(force=True) class ShellCancel(Method): def execute(self, w, **vargs): w.application.close_mini_buffer() if w.application.completion_window_is_open(): w.application.close_completion_buffer() class ShellClear(Method): def execute(self, w, **vargs): a = w.application if not a.has_buffer_name('*Shell*'): raise Exception, "No shell found!" b = a.bufferlist.get_buffer_by_name('*Shell*') b.clear() class ShellHistoryPrev(Method): def execute(self, w, **vargs): if w.mode.hindex <= 0: w.mode.hindex = 0 return elif w.mode.hindex == len(w.mode.history) - 1: w.mode.history[-1] = w.buffer.make_string() w.mode.hindex -= 1 w.buffer.set_data(w.mode.history[w.mode.hindex]) class ShellHistoryNext(Method): def execute(self, w, **vargs): if w.mode.hindex == len(w.mode.history) - 1: return w.mode.hindex += 1 w.buffer.set_data(w.mode.history[w.mode.hindex]) #class ShellTab(Method): # def execute(self, w, **vargs): # a = w.application # s = w.buffer.make_string() # # x = w.logical_cursor().x # if not s or s[:x].isspace(): # w.insert_string_at_cursor(' ' * w.mode.tabwidth) # return # # l = lex.Lexer(w.mode, ShGrammar) # tokens = list(l.lex([s])) # # curr_t = None # curr_i = None # for i in range(0, len(tokens)): # t = tokens[i] # if t.x < x and t.end_x() >= x: # curr_i = i # curr_t = t # if curr_t is None: # return # # first_t = curr_t # j = curr_i # # name_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$') # if name_re.match(curr_t.string): # names = [curr_t.string] # elif curr_t.string == '.': # names = [''] # else: # names = [] # # while j >= 1: # j -= 1 # t = tokens[j] # if name_re.match(t.string): # names.insert(0, t.string) # elif t.string == '.': # pass # else: # break # # if not names: # return # # obj = None # g = globals() # i = 0 # name = names[0] # if len(names) > 1: # while i < len(names): # name = names[i] # if obj is None: # if name in w.mode.locals: # obj = w.mode.locals[name] # elif name in w.mode.globals: # obj = w.mode.globals[name] # else: # break # else: # if hasattr(obj, name): # obj = getattr(obj, name) # else: # break # i += 1 # # if i == len(names) - 1: # if obj is not None: # newnames = dir(obj) # else: # newnames = set() # newnames.update(__builtins__) # newnames.update(w.mode.locals) # newnames.update(w.mode.globals) # candidates = [x for x in newnames if x.startswith(name)] # # s = completer.find_common_string(candidates)[len(name):] # w.insert_string_at_cursor(s) # mode.mini.use_completion_window(a, name, candidates) class ShellBaseMethod(Method): subcls = Method subbuf = '*Shell*' def __init__(self): Method.__init__(self) self.submethod = self.subcls() def _execute(self, w, **vargs): a = w.application if not a.has_buffer_name(self.subbuf): raise Exception, "No shell found!" w2 = a.bufferlist.get_buffer_by_name(self.subbuf).windows[0] self.submethod.execute(w2, **vargs) class ShellPageUp(ShellBaseMethod): subcls = method.move.PageUp class ShellPageDown(ShellBaseMethod): subcls = method.move.PageDown class ShellGotoBeginning(ShellBaseMethod): subcls = method.move.GotoBeginning class ShellGotoEnd(ShellBaseMethod): subcls = method.move.GotoEnd class OpenShell(Method): '''Evaluate sh expressions''' def execute(self, w, **vargs): a = w.application if not a.has_buffer_name('*Shell*'): b = buffer.ShellBuffer() a.add_buffer(b) window.Window(b, a) b = a.bufferlist.get_buffer_by_name('*Shell*') if a.window().buffer is not b: a.switch_buffer(b) f = lambda x: None w.application.open_mini_buffer('sh$ ', f, self, None, 'shellmini') class ShellMini(mode.Fundamental): modename = 'ShellMini' grammar = ShGrammar actions = [ShellExec, ShellClear, ShellCancel, ShellHistoryPrev, ShellHistoryNext, #ShellTab, ShellPageUp, ShellPageDown, ShellGotoBeginning, ShellGotoEnd, OpenShell] def __init__(self, w): mode.Fundamental.__init__(self, w) self.globals = dict(w.application.globals()) self.locals = dict(w.application.locals()) self.saved_input = "" self.history = [''] self.hindex = 0 self.add_bindings('shell-exec', ('RETURN',)) self.add_bindings('shell-clear', ('C-l',)) self.add_bindings('shell-cancel', ('C-]', 'C-g')) self.add_bindings('shell-history-prev', ('C-p', 'UP')) self.add_bindings('shell-history-next', ('C-n', 'DOWN')) #self.add_bindings('shell-tab', ('TAB',)) self.add_bindings('shell-page-up', ('M-v',)) self.add_bindings('shell-page-down', ('C-v',)) self.add_bindings('shell-goto-beginning', ('M-<',)) self.add_bindings('shell-goto-end', ('M->',)) install = ShellMini.install