diff --git a/application.py b/application.py index 15e955e..d749e13 100755 --- a/application.py +++ b/application.py @@ -2,7 +2,7 @@ import curses, curses.ascii, getpass, os, re, string, sets, sys, termios, time import traceback -import buffer, bufferlist, color, completer, keyinput, method, minibuffer, mode, mode +import buffer, bufferlist, color, completer, keyinput, method, minibuffer, mode import util, window from point import Point @@ -181,15 +181,16 @@ class Application(object): self.registers = {} # initialize tab handlers - method.DATATYPES['path'] = completer.FileCompleter() - method.DATATYPES['buffer'] = completer.BufferCompleter(self) - method.DATATYPES['command'] = completer.CommandCompleter() - method.DATATYPES['shell'] = completer.ShellCompleter() - method.DATATYPES['config'] = completer.ConfigCompleter() - method.DATATYPES['method'] = completer.MethodCompleter() - method.DATATYPES['register'] = completer.RegisterCompleter() - method.DATATYPES['mode'] = completer.ModeCompleter() - method.DATATYPES['perlfunction'] = completer.PerlFunctionCompleter() + method.DATATYPES['path'] = completer.FileCompleter() + method.DATATYPES['buffer'] = completer.BufferCompleter(self) + method.DATATYPES['command'] = completer.CommandCompleter() + method.DATATYPES['shell'] = completer.ShellCompleter() + method.DATATYPES['config'] = completer.ConfigCompleter() + method.DATATYPES['method'] = completer.MethodCompleter() + method.DATATYPES['register'] = completer.RegisterCompleter() + method.DATATYPES['mode'] = completer.ModeCompleter() + method.DATATYPES['perlfunction'] = completer.PerlFunctionCompleter() + method.DATATYPES['pythonfunction'] = completer.PythonFunctionCompleter() # set up curses self.win = curses.newwin(self.y, self.x, 0, 0) diff --git a/completer.py b/completer.py index 7b109ba..481ad99 100644 --- a/completer.py +++ b/completer.py @@ -111,3 +111,9 @@ class PerlFunctionCompleter(Completer): old_window = w.buffer.method.old_window functions = old_window.mode.get_functions() return [n for n in functions if n.startswith(s)] + +class PythonFunctionCompleter(Completer): + def get_candidates(self, s, w=None): + old_window = w.buffer.method.old_window + functions = old_window.mode.get_functions() + return [n for n in functions if n.startswith(s)] diff --git a/mode/python.py b/mode/python.py index 9900587..4beba27 100644 --- a/mode/python.py +++ b/mode/python.py @@ -200,6 +200,9 @@ class Python(mode.Fundamental): 'rawstring.end': ('green', 'default'), 'system_identifier': ('cyan', 'default'), } + config = { + 'python.lib': '.', + } def __init__(self, w): mode.Fundamental.__init__(self, w) # tag matching @@ -207,22 +210,61 @@ class Python(mode.Fundamental): self.add_bindings('close-brace', ('}',)) self.add_bindings('close-bracket', (']',)) # add python-specific methods + self.add_action(PythonInitFunctions()) + self.add_action(PythonListFunctions()) + self.add_action_and_bindings(PythonGotoFunction(), ('C-c M-g',)) self.add_action_and_bindings(PythonCheckSyntax(), ('C-c s',)) self.add_action_and_bindings(PythonDictCleanup(), ('C-c h',)) - # highlighting - self.pythonlib = "." + # other python + self.functions = None + def build_function_map(self): + b = self.window.buffer + self.functions = {} + for i in range(0, len(b.lines)): + m = regex.python_function.match(b.lines[i]) + if m: + self.functions[m.group(1)] = i + def get_functions(self): + if self.functions is None: + self.build_function_map() + return self.functions + def get_function_names(self): + functions = self.get_functions() + pairs = [[functions[key], key] for key in functions] + pairs.sort() + names = [x[1] for x in pairs] + return names -class PythonSetLib(method.Method): - '''Set the path(s) to find perl modules''' - args = [method.Argument("lib", type=type(""), prompt="Python Path: ", - default=default.build_constant("."))] +class PythonInitFunctions(method.Method): + '''Jump to a function defined in this module''' def _execute(self, w, **vargs): - w.mode.pythonlib = vargs['lib'] - + w.mode.build_function_map() + w.application.set_error("Initialized function map") + +class PythonGotoFunction(method.Method): + '''Jump to a function defined in this module''' + args = [method.Argument("name", type(""), "pythonfunction", "Goto Function: ")] + def _execute(self, w, **vargs): + name = vargs['name'] + functions = w.mode.get_functions() + if name in functions: + w.goto(Point(0, functions[name])) + else: + w.application.set_error("Function %r was not found" % name) + +class PythonListFunctions(method.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("*Python-List-Functions*", output, switch_to=True) + class PythonCheckSyntax(method.Method): '''Check the syntax of the current python file''' def _execute(self, w, **vargs): - sys.path.insert(0, w.mode.pythonlib) + pythonlib = w.application.config.get('python.lib') + if pythonlib: + sys.path.insert(0, pythonlib) source = w.buffer.make_string() try: code = compile(source, w.buffer.path, 'exec') diff --git a/regex.py b/regex.py index 2cc3e3e..38ef078 100644 --- a/regex.py +++ b/regex.py @@ -32,3 +32,4 @@ perl_function = re.compile(r"^ *sub ([A-Za-z_][A-Za-z0-9_]*)") python_base = re.compile(r"^[^ ]") python_dict_cleanup = re.compile(r"^( *)((?:[^'\":]|'(?:\.|[^\'])*'|\"(?:\.|[^\'])*)+?)( *)(:)( *)([^ ].*)$") python_assign_cleanup = re.compile(r"^( *)([^ ]+)( *)(=)( *)([^ ].*)$") +python_function = re.compile('^ *def ([A-Za-z_][A-Za-z0-9_]*)') \ No newline at end of file