diff --git a/application.py b/application.py index 0226d39..ade6baa 100755 --- a/application.py +++ b/application.py @@ -10,11 +10,11 @@ from point2 import Point import mode2 import mode_mini, mode_search, mode_replace, mode_which import mode_console, mode_consolemini +import mode_c, mode_python, mode_perl, mode_nasm, mode_sh import mode_blame, mode_diff -import mode_c, mode_python, mode_perl, mode_nasm, mode_sh, mode_javascript, mode_sql -import mode_xml, mode_tt -import mode_life, mode_text, mode_mutt -import mode_bds +import mode_javascript, mode_sql, mode_xml, mode_tt +import mode_text, mode_mutt +import mode_bds, mode_life def run(buffers, jump_to_line=None, init_mode=None): # save terminal state so we can restore it when the program exits @@ -704,12 +704,8 @@ def open_plain_file(path, nl, name=None): return b if __name__ == "__main__": - ciphers = { 'none': open_plain_file, - 'aes': open_aes_file } - - linetypes = { 'win': '\r\n', - 'mac': '\r', - 'unix': '\n' } + ciphers = { 'none': open_plain_file, 'aes': open_aes_file } + linetypes = { 'win': '\r\n', 'mac': '\r', 'unix': '\n' } import optparse diff --git a/method.py b/method.py index 4cb457b..b1f0427 100644 --- a/method.py +++ b/method.py @@ -68,10 +68,10 @@ class Argument: class Method: _is_method = True + args = [] def __init__(self): self.name = self._name() - self.help = self._help() - self.args = self._args() + self.help = self.__doc__ def _name(cls): s = cls.__name__ @@ -86,12 +86,6 @@ class Method: return s2 _name = classmethod(_name) - def _help(self): - return self.__doc__ - - def _args(self): - return [] - def _pre_execute(self, w, **vargs): pass @@ -113,21 +107,18 @@ class Method: class GotoChar(Method): '''Jump to the specified character''' - def _args(self): - return [Argument("charno", type=type(0), prompt="Goto char: ")] + args = [Argument("charno", type=type(0), prompt="Goto char: ")] def _execute(self, w, **vargs): w.goto_char(vargs["charno"]) class ForwardChars(Method): '''Move forward the specified number of characters''' - def _args(self): - return [Argument("charno", type=type(0), prompt="Forward chars: ")] + args = [Argument("charno", type=type(0), prompt="Forward chars: ")] def _execute(self, w, **vargs): w.forward_chars(vargs["charno"]) class GotoLine(Method): '''Jump to the specified line number''' - def _args(self): - return [Argument("lineno", type=type(0), prompt="Goto line: ")] + args = [Argument("lineno", type=type(0), prompt="Goto line: ")] def _execute(self, w, **vargs): n = vargs["lineno"] if n < 0: @@ -139,8 +130,7 @@ class GotoLine(Method): w.goto_line(n) class ForwardLines(Method): '''Move forward the specified number of characters''' - def _args(self): - return [Argument("lineno", type=type(0), prompt="Forward lines: ")] + args = [Argument("lineno", type=type(0), prompt="Forward lines: ")] def _execute(self, w, **vargs): w.forward_lines(vargs["lineno"]) @@ -161,13 +151,10 @@ class ReverseSearch(Method): w.application.open_mini_buffer('I-Search: ', lambda x: None, self, None, 'search') class Replace(Method): '''Replace occurances of string X with string Y''' - def _args(self): - return [Argument('before', prompt="Replace: ", - default=default.last_replace_before, - load_default=True), - Argument('after', prompt="Replace With: ", - default=default.last_replace_after, - load_default=True)] + args = [Argument('before', prompt="Replace: ", + default=default.last_replace_before, load_default=True), + Argument('after', prompt="Replace With: ", + default=default.last_replace_after, load_default=True)] def _execute(self, w, **vargs): a = w.application a.last_replace_before = self.before = vargs['before'] @@ -178,8 +165,7 @@ class Replace(Method): # navigating between buffers class OpenFile(Method): '''Open file in a new buffer, or go to file's open buffer''' - def _args(self): - return [Argument('filename', datatype="path", prompt="Open File: ")] + args = [Argument('filename', datatype="path", prompt="Open File: ")] def _execute(self, w, **vargs): path = vargs['filename'] path = os.path.abspath(os.path.realpath(util.expand_tilde(path))) @@ -201,9 +187,8 @@ class OpenFile(Method): SwitchBuffer().execute(w, buffername=b.name()) class OpenAesFile(Method): '''Open AES encrypted file in a new buffer, or go to file's open buffer''' - def _args(self): - return [Argument('filename', datatype="path", prompt="Open AES File: "), - Argument('password', prompt="Use AES Password: ")] + args = [Argument('filename', datatype="path", prompt="Open AES File: "), + Argument('password', prompt="Use AES Password: ")] def _execute(self, w, **vargs): path = vargs['filename'] password = vargs['password'] @@ -217,10 +202,8 @@ class OpenAesFile(Method): SwitchBuffer().execute(w, buffername=path) class SwitchBuffer(Method): '''Switch to a different''' - def _args(self): - return [Argument('buffername', datatype="buffer", - prompt="Switch To Buffer: ", - default=default.last_buffer)] + args = [Argument('buffername', datatype="buffer", prompt="Switch To Buffer: ", + default=default.last_buffer)] def _pre_execute(self, w, **vargs): a = w.application if len(a.bufferlist.buffers) < 1: @@ -236,10 +219,8 @@ class SwitchBuffer(Method): class KillBuffer(Method): '''Close the current buffer''' force=False - def _args(self): - return [Argument('buffername', datatype="buffer", - prompt="Kill Buffer: ", - default=default.current_buffer)] + args = [Argument('buffername', datatype="buffer", prompt="Kill Buffer: ", + default=default.current_buffer)] def _execute(self, w, **vargs): name = vargs['buffername'] app = w.application @@ -254,10 +235,8 @@ class KillBuffer(Method): b.close() class ForceKillBuffer(KillBuffer): force=True - def _args(self): - return [Argument('buffername', datatype="buffer", - prompt="Force Kill Buffer: ", - default=default.current_buffer)] + args = [Argument('buffername', datatype="buffer", prompt="Force Kill Buffer: ", + default=default.current_buffer)] class ListBuffers(Method): '''List all open buffers in a new buffer''' def _execute(self, w, **vargs): @@ -268,9 +247,8 @@ class ListBuffers(Method): w.application.data_buffer("*Buffers*", data, switch_to=True) class SaveBufferAs(Method): '''Save the contents of a buffer to the specified path''' - def _args(self): - return [Argument('path', datatype="path", prompt="Write file: ", - default=default.current_working_dir, load_default=True)] + args = [Argument('path', datatype="path", prompt="Write file: ", + default=default.current_working_dir, load_default=True)] def _execute(self, w, **vargs): curr_buffer = w.buffer curr_buffer_name = curr_buffer.name() @@ -492,8 +470,7 @@ class DumpTokens(Method): w.application.data_buffer("token-dump", output, switch_to=True) class MetaX(Method): '''Invoke commands by name''' - def _args(self): - return [Argument('method', datatype="method", prompt="M-x ")] + args = [Argument('method', datatype="method", prompt="M-x ")] def _execute(self, w, **vargs): name = vargs['method'] if name in w.application.methods: @@ -907,8 +884,7 @@ class OpenConsole(Method): class ShellCmd(Method): '''Run a command in a shell and put the output in a new buffer''' - def _args(self): - return [Argument("cmd", type=type(""), prompt="$ ", datatype='shell')] + args = [Argument("cmd", type=type(""), prompt="$ ", datatype='shell')] def _execute(self, w, **vargs): cmd = "PBUF='%s'; %s" % (w.buffer.name(), vargs['cmd']) (status, data) = commands.getstatusoutput(cmd) @@ -920,8 +896,7 @@ class ShellCmd(Method): w.application.data_buffer("*Shell*", data, switch_to=True) class FileDiff(Method): '''diff the buffer's contents with the given file''' - def _args(self): - return [Argument("path", type=type(""), prompt="Filename: ", datatype='path')] + args = [Argument("path", type=type(""), prompt="Filename: ", datatype='path')] def _execute(self, w, **vargs): cmd = ("/usr/bin/diff", '-u', '-', vargs['path']) pipe = popen2.Popen3(cmd, capturestderr=True) @@ -1072,8 +1047,7 @@ class CvsDiff(Method): class CvsDiff2(Method): '''diff the current file with the version in CVS''' rev_regex = re.compile('^[0-9]+\.[0-9]+$') - def _args(self): - return [Argument("revision", type=type(""), prompt="Old Revision: ")] + args = [Argument("revision", type=type(""), prompt="Old Revision: ")] def _execute(self, w, **vargs): if not hasattr(w.buffer, 'path'): w.application.set_error("Buffer has no corresponding file") @@ -1101,9 +1075,8 @@ class CvsDiff2(Method): class CvsDiff3(Method): '''diff the current file with the version in CVS''' rev_regex = re.compile('^[0-9]+\.[0-9]+$') - def _args(self): - return [Argument("revision1", type=type(""), prompt="Old Revision: "), - Argument("revision2", type=type(""), prompt="New Revision: ")] + args = [Argument("revision1", type=type(""), prompt="Old Revision: "), + Argument("revision2", type=type(""), prompt="New Revision: ")] def _execute(self, w, **vargs): if not hasattr(w.buffer, 'path'): w.application.set_error("Buffer has no corresponding file") @@ -1225,8 +1198,7 @@ class ShowBindingsBuffer(Method): class CmdHelpBuffer(Method): '''Get help with the specified command''' - def _args(self): - return [Argument('method', datatype="method", prompt="Help for command: ")] + args = [Argument('method', datatype="method", prompt="Help for command: ")] def _execute(self, w, **vargs): lines = [] name = vargs['method'] @@ -1281,8 +1253,7 @@ class CmdHelpBuffer(Method): class SetMode(Method): '''Set the mode of the current buffer''' - def _args(self): - return [Argument('mode', datatype='mode', prompt="Enter new mode: ")] + args = [Argument('mode', datatype='mode', prompt="Enter new mode: ")] def _execute(self, w, **vargs): mode_name = vargs['mode'] m = w.application.modes[mode_name](w) @@ -1396,8 +1367,7 @@ class RegisterSave(Method): MAX_TXT = 30 MAX_REG = 20 '''help here''' - def _args(self): - return [Argument('name', datatype="str", prompt="Register name: ")] + args = [Argument('name', datatype="str", prompt="Register name: ")] def _pre_execute(self, w, **vargs): if not w.has_kill(): raise MethodError, "No text on the kill stack" @@ -1415,8 +1385,7 @@ class RegisterRestore(Method): MAX_TXT = 30 MAX_REG = 18 '''help here''' - def _args(self): - return [Argument('name', datatype="str", prompt="Register name: ")] + args = [Argument('name', datatype="str", prompt="Register name: ")] def _execute(self, w, **vargs): name = vargs['name'] if name not in w.application.registers: diff --git a/mode2.py b/mode2.py index e93de22..cced555 100644 --- a/mode2.py +++ b/mode2.py @@ -3,6 +3,9 @@ import color, lex2, method DEBUG = False +class ActionError(Exception): + pass + class Handler: def __init__(self): self.prefixes = sets.Set(["C-x", "C-c", "C-u"]) @@ -14,16 +17,16 @@ class Handler: def add_action(self, action): if action.name in self.window.application.methods: return - assert action.name not in self.window.application.methods, \ - "Action %r already found" % action.name + if action.name in self.window.application.methods: + raise Exception, "Action %r already found" % action.name self.window.application.methods[action.name] = action def del_action(self, name): for binding in self.bindings.keys(): if self.bindings[binding] == name: del self.bindings[binding] def add_binding(self, name, sequence): - assert name in self.window.application.methods, \ - "No action called %r found" % name + if name not in self.window.application.methods: + raise Exception, "No action called %r found" % name self.bindings[sequence] = name def add_bindings(self, name, sequences): for sequence in sequences: @@ -51,7 +54,7 @@ class Handler: return None self.curr_tokens = [] self.last_sequence = sequence - raise Exception, "no action defined for %r" % (sequence) + raise ActionError, "no action defined for %r" % (sequence) class Fundamental(Handler): '''This is the default mode''' @@ -165,20 +168,27 @@ class Fundamental(Handler): def handle_token(self, t): '''self.handle_token(token): handles input "token"''' self.window.active_point = None + #self.window.application.clear_error() + self.window.clear_error() try: act = Handler.handle_token(self, t) if act is None: + self.window.set_error(' '.join(self.curr_tokens)) return else: - self.window.application.clear_error() act.execute(self.window) self.window.application.last_action = act.name + except ActionError, e: + if t != 'C-]': + self.window.set_error(str(e)) + else: + self.window.set_error('Cancelled') except Exception, e: if DEBUG: raise else: err = "%s in mode '%s'" % (e, self.name()) - self.window.application.set_error(err) + self.window.set_error(err) def region_added(self, p, newlines): if self.tabber is not None: diff --git a/mode_perl.py b/mode_perl.py index f49d4d3..2296f7b 100644 --- a/mode_perl.py +++ b/mode_perl.py @@ -1,7 +1,8 @@ import re, sets, string, sys import color, commands, default, lex2, method, mode2, regex, tab2 from point2 import Point -from lex2 import Grammar, ConstantRule, PatternRule, ContextPatternRule, RegionRule, DualRegionRule +from lex2 import Grammar, PatternRule, ContextPatternRule, RegionRule, DualRegionRule +from method import Argument, Method class PodGrammar(Grammar): rules = [ @@ -228,43 +229,43 @@ class Perl(mode2.Fundamental): 'eval_heredoc.start': color.build('cyan', 'default'), 'eval_heredoc.null': color.build('cyan', 'default'), 'eval_heredoc.end': color.build('cyan', 'default'), - + # pod 'pod.start': color.build('red', 'default'), 'pod.null': color.build('red', 'default'), 'pod.entry': color.build('magenta', 'default'), 'pod.end': color.build('red', 'default'), - + # "" strings 'string1.start': color.build('green', 'default'), 'string1.null': color.build('green', 'default'), 'string1.escaped': color.build('magenta', 'default'), 'string1.deref': color.build('yellow', 'default'), 'string1.end': color.build('green', 'default'), - + # '' strings 'string2.start': color.build('green', 'default'), 'string2.null': color.build('green', 'default'), 'string2.end': color.build('green', 'default'), - + # `` strings 'evalstring.start': color.build('cyan', 'default'), 'evalstring.null': color.build('cyan', 'default'), 'string1.escaped': color.build('magenta', 'default'), 'string1.deref': color.build('yellow', 'default'), 'evalstring.end': color.build('cyan', 'default'), - + # quoted region 'quoted': color.build('cyan', 'default'), 'quoted.start': color.build('cyan', 'default'), 'quoted.null': color.build('cyan', 'default'), 'quoted.end': color.build('cyan', 'default'), - + # match regex 'match.start': color.build('cyan', 'default'), 'match.end': color.build('cyan', 'default'), 'match.null': color.build('cyan', 'default'), - + # replace regex 'replace.start': color.build('cyan', 'default'), 'replace.middle': color.build('cyan', 'default'), @@ -276,14 +277,14 @@ class Perl(mode2.Fundamental): 'replace.scalar': color.build('yellow', 'default'), 'replace.hash': color.build('yellow', 'default'), 'replace.cast': color.build('yellow', 'default'), - + # translate regex 'translate.start': color.build('magenta', 'default'), 'translate.middle': color.build('magenta', 'default'), 'translate.end': color.build('magenta', 'default'), 'translate.null': color.build('magenta', 'default'), } - + # perl-specific self.functions = None self.perllib = 'lib' @@ -309,15 +310,14 @@ class Perl(mode2.Fundamental): names = [x[1] for x in pairs] return names -class PerlSetLib(method.Method): +class PerlSetLib(Method): '''Set the path(s) to find perl modules''' - def _args(self): - return [method.Argument("lib", type=type(""), prompt="Location of lib: ", - default=default.build_constant("."))] + args = [Argument("lib", type=type(""), prompt="Location of lib: ", + default=default.build_constant("."))] def _execute(self, w, **vargs): w.mode.perllib = vargs['lib'] -class PerlCheckSyntax(method.Method): +class PerlCheckSyntax(Method): '''Check the syntax of a perl file''' def _execute(self, w, **vargs): app = w.application @@ -329,14 +329,14 @@ class PerlCheckSyntax(method.Method): else: app.data_buffer("*Perl-Check-Syntax*", output) -class PerlViewModulePerldoc(method.Method): +class PerlViewModulePerldoc(Method): '''View documentation about this file using perldoc''' def _execute(self, w, **vargs): cmd = "perldoc -t -T '%s'" % w.buffer.path (status, output) = commands.getstatusoutput(cmd) w.application.data_buffer("*Perldoc*", output, switch_to=True) -class PerlViewWordPerldoc(method.Method): +class PerlViewWordPerldoc(Method): '''View documentation about a package or function using perldoc''' def _try(self, w, word, asfunc=False): if asfunc: @@ -381,11 +381,9 @@ class PerlViewWordPerldoc(method.Method): else: w.application.set_error('nothing found for %r' % word) -class PerlGotoFunction(method.Method): +class PerlGotoFunction(Method): '''Jump to a function defined in this module''' - def _args(self): - return [method.Argument("name", type=type(""), datatype="perlfunction", - prompt="Goto Function: ")] + args = [Argument("name", type(""), "perlfunction", "Goto Function: ")] def _execute(self, w, **vargs): name = vargs['name'] functions = w.mode.get_functions() @@ -394,14 +392,14 @@ class PerlGotoFunction(method.Method): else: w.application.set_error("Function %r was not found" % name) -class PerlListFunctions(method.Method): +class PerlListFunctions(Method): '''Show the user all functions defined in this module''' def _execute(self, w, **vargs): names = w.mode.get_function_names() output = "\n".join(names) + "\n" w.application.data_buffer("*Perl-List-Functions*", output, switch_to=True) -class PerlWhichFunction(method.Method): +class PerlWhichFunction(Method): '''Show the user what function they are in''' def _execute(self, w, **vargs): cursor = w.logical_cursor() @@ -419,7 +417,7 @@ class PerlWhichFunction(method.Method): else: w.application.set_error("line %d: %s" % (i, name)) -class PerlHashCleanup(method.Method): +class PerlHashCleanup(Method): '''Correctly align assignment blocks and literal hashes''' def _execute(self, window, **vargs): cursor = window.logical_cursor() @@ -494,7 +492,7 @@ class PerlHashCleanup(method.Method): window.kill(start_p, end_p) window.insert_string(start_p, data) -#class PerlWrapLine(method.Method): +#class PerlWrapLine(Method): # '''Wrap lines, comments, POD''' # margin = 80 # comment_re = re.compile('^( *)(#+)( *)([^ ].*)$') diff --git a/mode_python.py b/mode_python.py index 078213c..aa86543 100644 --- a/mode_python.py +++ b/mode_python.py @@ -207,9 +207,8 @@ class Python(mode2.Fundamental): class PythonSetLib(method.Method): '''Set the path(s) to find perl modules''' - def _args(self): - return [method.Argument("lib", type=type(""), prompt="Python Path: ", - default=default.build_constant("."))] + args = [method.Argument("lib", type=type(""), prompt="Python Path: ", + default=default.build_constant("."))] def _execute(self, w, **vargs): w.mode.pythonlib = vargs['lib'] @@ -228,9 +227,8 @@ class PythonCheckSyntax(method.Method): class PythonUpdateTags(method.Method): '''Update the CTag data associated with a python buffer''' - def _args(self): - return [method.Argument("lib", prompt="Module Base: ", datatype='path', - default=default.build_constant("."))] + args = [method.Argument("lib", prompt="Module Base: ", datatype='path', + default=default.build_constant("."))] def _execute(self, w, **vargs): w.mode.ctagger = ctag_python.PythonCTagger() w.mode.ctagger.process_paths([vargs['lib']]) diff --git a/window2.py b/window2.py index 220ff91..c72cd46 100644 --- a/window2.py +++ b/window2.py @@ -73,6 +73,8 @@ class Window(object): # some useful pass-through to application def set_error(self, s): self.application.set_error(s) + def clear_error(self): + self.application.clear_error() # mode stuff def set_mode(self, m):