diff --git a/application.py b/application.py index 53f231b..c378ca7 100755 --- a/application.py +++ b/application.py @@ -2,6 +2,7 @@ import curses, curses.ascii, getpass, os, re, string, sys, termios, time import traceback from subprocess import Popen, PIPE, STDOUT +from collections import defaultdict import buffer, bufferlist, color, completer, keyinput, method, minibuffer, mode import util, window @@ -42,6 +43,7 @@ class Application(object): # initialize some basic stuff # a highlighted_range contains three things: (window, start_p, end_p) + self.state = defaultdict(lambda: {}) self.config = {} self.highlighted_ranges = [] self.mini_active = False diff --git a/mode/perl.py b/mode/perl.py index 1080916..27c5586 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -1,4 +1,4 @@ -import re, sets, string, sys +import os, re, sets, string, sys import color, commands, completer, context, default, method, mode, regex, tab from point import Point from lex import Grammar, PatternRule, ContextPatternRule, RegionRule, OverridePatternRule, PatternGroupRule @@ -91,7 +91,7 @@ class PerlGrammar(Grammar): # some more basic stuff PatternRule(r'package', r"(?<=package )(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*"), - PatternRule(r'sub', r"(?<=sub )[a-zA-Z_][a-zA-Z_0-9]*"), + PatternRule(r'sub', r"(?<=sub )(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*"), PatternRule(r'use', r"(?<=use )(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*"), PatternRule(r'require', r"(?<=require )(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*"), PatternRule(r'perl_label', r'[a-zA-Z_][a-zA-Z0-9_]*:(?!:)'), @@ -487,6 +487,31 @@ class PerlWrapParagraph(method.WrapParagraph): else: w.set_error("did not detect comment or pod lines") +class PerlOpenModule(method.Method): + args = [Argument("module", type=type(""), prompt="Open Perl Module: ")] + def _execute(self, w, **vargs): + path = w.mode.find_module(vargs['module']) + if path: + w.application.methods['open-file'].execute(w, filename=path) + else: + w.set_error("Could not find module %r" % vargs['module']) +class PerlOpenModuleWord(method.Method): + def _execute(self, w, **vargs): + word = pkg = w.get_token().string + path = None + while True: + path = w.mode.find_module(pkg) + if path: + break + parent = pkg.rsplit('::')[0] + if parent == pkg: + break + parent = pkg + if path: + w.application.methods['open-file'].execute(w, filename=path) + else: + w.set_error("Could not find module related to %r" % pkg) + class PerlFunctionCompleter(completer.Completer): def get_candidates(self, s, w=None): old_window = w.buffer.method.old_window @@ -516,10 +541,10 @@ class PerlContext(context.Context): if t.name in m.opentokens and t.string in m.opentags: stack.append(t.string) elif t.name in m.closetokens and t.string in m.closetags: - assert stack[-1] == m.closetags[t.string] - stack.pop(-1) - if not stack: - curr = None + if stack[-1] == m.closetags[t.string]: + stack.pop(-1) + if t.string == '}' and not stack: + curr = None class Perl(mode.Fundamental): modename = 'Perl' @@ -627,7 +652,7 @@ class Perl(mode.Fundamental): actions = [PerlSetLib, PerlCheckSyntax, PerlHashCleanup, PerlViewModulePerldoc, PerlViewWordPerldoc, PerlWrapParagraph, PerlInitFunctions, PerlGotoFunction, PerlWhichFunction, - PerlListFunctions] + PerlListFunctions, PerlOpenModule, PerlOpenModuleWord] completers = { 'perlfunction': PerlFunctionCompleter(), } @@ -664,6 +689,32 @@ class Perl(mode.Fundamental): self.functions = None self.funclines = None + def find_module(self, module): + parts = module.split('::') + parts[-1] += '.pm' + relpath = os.path.join(*parts) + path = None + for d in self.get_inc(): + path2 = os.path.join(d, relpath) + if os.path.exists(path2): + path = path2 + break + return path + + def get_inc(self): + a = self.window.application + if 'inc' not in a.state['perl']: + perllib = a.config.get('perl.lib') + if perllib: + cmd = "PERL5LIB=%r perl -e 'print join(\"\\n\", @INC);'" % perllib + else: + cmd = "perl -e 'print join(\"\\n\", @INC);'" + (status, data) = commands.getstatusoutput(cmd) + if status != 0: + raise Exception, "%r failed" % cmd + a.state['perl']['inc'] = data.split('\n') + return a.state['perl']['inc'] + def get_functions(self): return self.context.get_names() def get_function_names(self):