import code import re import StringIO import sys import traceback import completer import util from method import Method import method.move import mode.mini from lex import Lexer, Grammar, PatternRule from mode.python import PythonGrammar PAD = ' ' class ConsoleExec(Method): def _execute(self, w, **vargs): if w.application.completion_window_is_open(): w.application.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 a = w.application if not a.has_buffer_name('*Console*'): raise Exception, "No console found!" b = a.bufferlist.get_buffer_by_name('*Console*') 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) if w.mode.saved_input: s = w.mode.saved_input + '\n' + s try: code_obj = code.compile_command(s) if code_obj is None: w.mode.saved_input = s a.set_mini_buffer_prompt('--> ') output = None else: w.mode.saved_input = '' a.set_mini_buffer_prompt('>>> ') sys.stdout = code_out = StringIO.StringIO() sys.stderr = code_err = StringIO.StringIO() ok = True try: exec code_obj in w.mode.globals, w.mode.locals except Exception, e: ok = False output = str(e) + '\n' sys.stdout = sys.__stdout__ sys.stdout = sys.__stderr__ if ok: output = code_out.getvalue() code_out.close() code_err.close() #except (SyntaxError, OverflowError, ValueError), e: except Exception, e: a.set_mini_buffer_prompt('>>> ') t = sys.exc_traceback output = str(e) + traceback.format_exc() limit = min([w.width for w in b.windows]) - len(PAD) if output: lines = [] for line in output.split('\n'): lines.extend([PAD + l for l in util.wrap_lines(line, limit)]) if lines[-1] == PAD: lines[-1] = '' b.insert_lines(b.get_buffer_end(), lines + [''], force=True) for w2 in b.windows: w2.goto_end(force=True) class ConsoleCancel(Method): def execute(self, w, **vargs): w.application.close_mini_buffer() if w.application.completion_window_is_open(): w.application.close_completion_buffer() class ConsoleClear(Method): def execute(self, w, **vargs): #a = w.application #if not a.has_buffer_name('*Console*'): # raise Exception, "No console found!" #b = a.bufferlist.get_buffer_by_name('*Console*') #b.clear() w.buffer.parentw.buffer.clear() class ConsoleHistoryPrev(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 ConsoleHistoryNext(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 ConsoleTab(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 = Lexer(w.mode, PythonGrammar) tokens = list(l.lex([s])) curr_t = None curr_i = None for i in xrange(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 ConsoleBase(Method): subcls = Method subbuf = '*Console*' 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 console found!" w2 = a.bufferlist.get_buffer_by_name(self.subbuf).windows[0] self.submethod.execute(w2, **vargs) class ConsolePageUp(ConsoleBase): subcls = method.move.PageUp class ConsolePageDown(ConsoleBase): subcls = method.move.PageDown class ConsoleGotoBeginning(ConsoleBase): subcls = method.move.GotoBeginning class ConsoleGotoEnd(ConsoleBase): subcls = method.move.GotoEnd class ConsoleMini(mode.Fundamental): name = 'ConsoleMini' grammar = PythonGrammar actions = [ConsoleExec, ConsoleClear, ConsoleCancel, ConsoleHistoryPrev, ConsoleHistoryNext, ConsoleTab, ConsolePageUp, ConsolePageDown, ConsoleGotoBeginning, ConsoleGotoEnd] _bindings = { 'console-exec': ('RETURN',), 'console-clear': ('C-l',), 'console-cancel': ('C-]', 'C-g'), 'console-history-prev': ('C-p', 'UP'), 'console-history-next': ('C-n', 'DOWN'), 'console-tab': ('TAB',), 'console-page-up': ('M-v',), 'console-page-down': ('C-v',), 'console-goto-beginning': ('M-<',), 'console-goto-end': ('M->',), } 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 install = ConsoleMini.install