import code, re, string, StringIO, sys, traceback import color, completer, lex, method, mode from lex import Grammar, PatternRule from mode.python import PythonGrammar from point import Point PAD = ' ' LIMIT = 79 class ConsoleExec(method.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: a.set_mini_buffer_prompt('>>> ') t = sys.exc_traceback output = str(e) + traceback.format_exc() 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'): 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) for w2 in b.windows: w2.goto_end(force=True) class ConsoleCancel(method.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.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() class ConsoleHistoryPrev(method.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.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.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, PythonGrammar) 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 ConsoleBaseMethod(method.Method): subcls = method.Method subbuf = '*Console*' def __init__(self): method.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(ConsoleBaseMethod): subcls = method.move.PageUp class ConsolePageDown(ConsoleBaseMethod): subcls = method.move.PageDown class ConsoleGotoBeginning(ConsoleBaseMethod): subcls = method.move.GotoBeginning class ConsoleGotoEnd(ConsoleBaseMethod): subcls = method.move.GotoEnd class ConsoleMini(mode.Fundamental): modename = 'ConsoleMini' grammar = PythonGrammar actions = [ConsoleExec, ConsoleClear, ConsoleCancel, ConsoleHistoryPrev, ConsoleHistoryNext, ConsoleTab, ConsolePageUp, ConsolePageDown, ConsoleGotoBeginning, ConsoleGotoEnd] 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('console-exec', ('RETURN',)) self.add_bindings('console-clear', ('C-l',)) self.add_bindings('console-cancel', ('C-]',)) self.add_bindings('console-history-prev', ('C-p', 'UP')) self.add_bindings('console-history-next', ('C-n', 'DOWN')) self.add_bindings('console-tab', ('TAB',)) self.add_bindings('console-page-up', ('M-v',)) self.add_bindings('console-page-down', ('C-v',)) self.add_bindings('console-goto-beginning', ('M-<',)) self.add_bindings('console-goto-end', ('M->',)) install = ConsoleMini.install