diff --git a/application.py b/application.py index e82d737..81f57c2 100755 --- a/application.py +++ b/application.py @@ -7,9 +7,11 @@ import util, window2 from point2 import Point # modes -# TODO: mode_c mode_nasm mode_console mode_sh mode_sql mode_javascript mode_diff mode_tt +# TODO: mode_c mode_nasm mode_sh mode_sql mode_javascript mode_diff mode_tt import mode2 -import mode_mini, mode_search, mode_replace, mode_blame, mode_which, mode_diff +import mode_mini, mode_search, mode_replace, mode_which +import mode_console, mode_consolemini +import mode_blame, mode_diff import mode_python, mode_perl, mode_xml import mode_life, mode_text, mode_mutt @@ -81,7 +83,8 @@ class Application(object): self.modes = { 'blame': mode_blame.Blame, # 'c': mode_c.C, -# 'console': mode_console.Console, + 'console': mode_console.Console, + 'consolemini': mode_consolemini.Console, 'diff': mode_diff.Diff, 'fundamental': mode2.Fundamental, 'mini': mode_mini.Mini, @@ -161,11 +164,13 @@ class Application(object): buffers.append(buffer2.ConsoleBuffer()) self.bufferlist = bufferlist.BufferList(height, width) self.active_slot = 0 - #self.resize_slots() # build windows for our buffers for b in buffers: - window2.Window(b, self, height, width, mode_name=init_mode) + if b.name() == '*Console*': + window2.Window(b, self, height, width, mode_name='console') + else: + window2.Window(b, self, height, width, mode_name=init_mode) self.bufferlist.add_buffer(b) self.bufferlist.set_slot(0, buffers[0]) diff --git a/method.py b/method.py index 3a60880..4b4f1cc 100644 --- a/method.py +++ b/method.py @@ -890,10 +890,10 @@ class OpenConsole(Method): if not a.has_buffer_name('*Console*'): a.add_buffer(buffer2.ConsoleBuffer()) b = a.bufferlist.get_buffer_by_name('*Console*') - if a.w().buffer is not b: + if a.window().buffer is not b: a.switch_buffer(b) f = lambda x: None - w.application.open_mini_buffer('>>> ', f, self, None, 'console') + w.application.open_mini_buffer('>>> ', f, self, None, 'consolemini') class ShellCmd(Method): '''Run a command in a shell and put the output in a new buffer''' diff --git a/mode_console.py b/mode_console.py index 0f2fc2d..0b59e49 100644 --- a/mode_console.py +++ b/mode_console.py @@ -1,158 +1,25 @@ -import code, os, sets, string, StringIO, sys, traceback +import code, string, StringIO, sys, traceback +import color, completer, method, mode2 +from lex2 import Grammar, PatternRule +from point2 import Point -import color, completer, default, highlight, method, mode, point +class ConsoleGrammar(Grammar): + rules = [ + PatternRule(name=r'mesg', pattern=r'^[A-Za-z].*$'), + PatternRule(name=r'input', pattern=r'^>>>.*$'), + PatternRule(name=r'input2', pattern=r'^-->.*$'), + PatternRule(name=r'output', pattern=r'^ .*$'), + ] -class Console(mode.Fundamental): +class Console(mode2.Fundamental): + grammar = ConsoleGrammar() def __init__(self, w): - mode.Fundamental.__init__(self, w) - - self.actions = {} - self.bindings = {} - self.globals = dict(w.application.globals()) - self.locals = dict(w.application.locals()) - self.saved_input = "" - - self.add_bindings('start-of-line', ('C-a', 'HOME',)) - self.add_bindings('end-of-line', ('C-e', 'END',)) - self.add_bindings('backward', ('C-b', 'L_ARROW',)) - self.add_bindings('forward', ('C-f', 'R_ARROW',)) - self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',)) - self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',)) - self.add_bindings('delete-right', ('C-d',)) - self.add_bindings('delete-right-word', ('M-d',)) - self.add_bindings('kill-region', ('C-w',)) - self.add_bindings('copy-region', ('M-w',)) - self.add_bindings('kill', ('C-k',)) - self.add_bindings('copy', ('M-k',)) - self.add_bindings('yank', ('C-y',)) - self.add_bindings('pop-kill', ('M-y',)) - self.add_bindings('right-word', ('M-f',)) - self.add_bindings('left-word', ('M-b',)) - self.add_bindings('set-mark', ('C-@',)) - self.add_bindings('switch-mark', ('C-x C-x',)) - self.add_bindings('undo', ('C-/', 'C-x u',)) - self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',)) - self.add_bindings('toggle-margins', ('M-m',)) - self.add_bindings('transpose-words', ('M-t',)) - self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',)) - self.add_bindings('delete-right-whitespace', ('C-c d',)) - self.add_bindings('insert-space', ('SPACE',)) - self.add_bindings('insert-tab', ('TAB',)) - - self.add_action_and_bindings(ConsoleExec(), ('RETURN',)) - self.add_action_and_bindings(ConsoleCancel(), ('C-]',)) - #self.add_action_and_bindings(ConsoleTab(), ('TAB',)) - - # create all the insert actions for the character ranges we like - for c in string.letters + string.digits + string.punctuation: - self.add_binding('insert-string-%s' % c, c) - - # get mode name + mode2.Fundamental.__init__(self, w) + self.colors = { + 'mesg': color.build('blue', 'default'), + 'input': color.build('cyan', 'default'), + 'input2': color.build('cyan', 'default'), + 'output': color.build('default', 'default'), + } def name(self): return "Console" - -class ConsoleExec(method.Method): - def _execute(self, w, **vargs): - s = w.buffer.make_string() - w.buffer.set_data('') - a = w.application - - if not a.has_buffer_name('*Console*'): - a.add_buffer(buffer.ConsoleBuffer()) - 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 a.globals(), a.locals() - 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.last_traceback - t = sys.exc_traceback - output = str(e) + traceback.format_exc() - - #try: - # output = a.eval(s) - #except Exception, e: - # output = str(e) - if output: - b.insert_string(b.get_buffer_end(), output, force=True) - w.goto_end() - -class ConsoleCancel(method.Method): - def execute(self, w, **vargs): - w.application.close_mini_buffer() - -#class ConsoleTab(method.Method): -# def execute(self, w, **vargs): -# a = w.application -# s = w.buffer.make_string() -# -# if '"' in s or "'" in s or "(" in s or ")" in s or "[" in s or "]" in s: -# return -# -# parts = s.split(".") -# if len(parts) == 0: -# return -# -# v = a.globals() -# v.update(a.locals()) -# obj = None -# for part in parts[:-1]: -# if obj is None: -# if part in v: -# obj = v[part] -# else: -# return -# else: -# if hasattr(obj, part): -# obj = getattr(obj, part) -# else: -# return -# -# if obj is None: -# pool = v.keys() -# else: -# pool = dir(obj) -# candidates = [x for x in pool if x.startswith(parts[-1])] -# -# if len(candidates) == 0: -# return -# -# common = completer.find_common_string(candidates) -# s2 = '.'.join(parts[:-1]) + '.' + common -# -# w.buffer.set_data(s2) -# -# if len(candidates) > 1: -# if not a.has_buffer_name('*Console*'): -# a.add_buffer(buffer.ConsoleBuffer()) -# b = a.bufferlist.get_buffer_by_name('*Console*') -# b.insert_string(b.get_buffer_end(), repr(candidates) + '\n', force=True) diff --git a/mode_consolemini.py b/mode_consolemini.py new file mode 100644 index 0000000..264846f --- /dev/null +++ b/mode_consolemini.py @@ -0,0 +1,175 @@ +import code, string, StringIO, sys, traceback +import color, completer, method, mode2 +from lex2 import Grammar, PatternRule +from point2 import Point + +class Console(mode2.Fundamental): + def __init__(self, w): + mode2.Fundamental.__init__(self, w) + self.bindings = {} + self.globals = dict(w.application.globals()) + self.locals = dict(w.application.locals()) + self.saved_input = "" + + self.history = [''] + self.hindex = 0 + + self.add_bindings('start-of-line', ('C-a', 'HOME',)) + self.add_bindings('end-of-line', ('C-e', 'END',)) + self.add_bindings('backward', ('C-b', 'L_ARROW',)) + self.add_bindings('forward', ('C-f', 'R_ARROW',)) + self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',)) + self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',)) + self.add_bindings('delete-right', ('C-d',)) + self.add_bindings('delete-right-word', ('M-d',)) + self.add_bindings('kill-region', ('C-w',)) + self.add_bindings('copy-region', ('M-w',)) + self.add_bindings('kill', ('C-k',)) + self.add_bindings('copy', ('M-k',)) + self.add_bindings('yank', ('C-y',)) + self.add_bindings('pop-kill', ('M-y',)) + self.add_bindings('right-word', ('M-f',)) + self.add_bindings('left-word', ('M-b',)) + self.add_bindings('set-mark', ('C-@',)) + self.add_bindings('switch-mark', ('C-x C-x',)) + self.add_bindings('undo', ('C-/', 'C-x u',)) + self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',)) + self.add_bindings('toggle-margins', ('M-m',)) + self.add_bindings('transpose-words', ('M-t',)) + self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',)) + self.add_bindings('delete-right-whitespace', ('C-c d',)) + self.add_bindings('insert-space', ('SPACE',)) + self.add_bindings('insert-tab', ('TAB',)) + self.add_action_and_bindings(ConsoleExec(), ('RETURN',)) + self.add_action_and_bindings(ConsoleCancel(), ('C-]',)) + self.add_action_and_bindings(ConsoleHistoryPrev(), ('C-p',)) + self.add_action_and_bindings(ConsoleHistoryNext(), ('C-n',)) + #self.add_action_and_bindings(ConsoleTab(), ('TAB',)) + for c in string.letters + string.digits + string.punctuation: + self.add_binding('insert-string-%s' % c, c) + def name(self): + return "Console" + +class ConsoleExec(method.Method): + def _execute(self, w, **vargs): + 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() + + if output: + newlines = [' %s' % x for x in output.split('\n')] + assert newlines[-1] == ' ' + newlines[-1] = '' + b.insert_lines(b.get_buffer_end(), newlines, force=True) + for w2 in b.windows: + w2.goto_end() + +class ConsoleCancel(method.Method): + def execute(self, w, **vargs): + w.application.close_mini_buffer() + +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() +# +# if '"' in s or "'" in s or "(" in s or ")" in s or "[" in s or "]" in s: +# return +# +# parts = s.split(".") +# if len(parts) == 0: +# return +# +# v = a.globals() +# v.update(a.locals()) +# obj = None +# for part in parts[:-1]: +# if obj is None: +# if part in v: +# obj = v[part] +# else: +# return +# else: +# if hasattr(obj, part): +# obj = getattr(obj, part) +# else: +# return +# +# if obj is None: +# pool = v.keys() +# else: +# pool = dir(obj) +# candidates = [x for x in pool if x.startswith(parts[-1])] +# +# if len(candidates) == 0: +# return +# +# common = completer.find_common_string(candidates) +# s2 = '.'.join(parts[:-1]) + '.' + common +# +# w.buffer.set_data(s2) +# +# if len(candidates) > 1: +# if not a.has_buffer_name('*Console*'): +# a.add_buffer(buffer.ConsoleBuffer()) +# b = a.bufferlist.get_buffer_by_name('*Console*') +# b.insert_string(b.get_buffer_end(), repr(candidates) + '\n', force=True) diff --git a/mode_diff.py b/mode_diff.py index f28c5c5..8a481c5 100644 --- a/mode_diff.py +++ b/mode_diff.py @@ -1,11 +1,6 @@ import color, method, mode2, re from lex2 import Grammar, PatternRule, RegionRule -class MetadataGrammar(Grammar): - rules = [ - PatternRule(name=r'line', pattern=r'^.*$'), - ] - class DiffGrammar(Grammar): rules = [ PatternRule(name=r'left', pattern=r"^\-.*$"), diff --git a/window2.py b/window2.py index 9b24905..75aaba6 100644 --- a/window2.py +++ b/window2.py @@ -392,7 +392,20 @@ class Window(object): self.assure_visible_cursor() def goto_end(self): self.cursor = self.buffer.get_buffer_end() - self.assure_visible_cursor() + (x, y) = self.logical_cursor().xy() + counter = 0 + while counter < self.height - 2: + if x > self.width: + x -= self.width + elif y > 0: + y -= 1 + x = len(self.buffer.lines[y]) + else: + (x, y) = (0, 0) + break + counter += 1 + self.first = Point(x - (x % self.width), y) + self.redraw() # mark manipulation def set_mark_point(self, p):