diff --git a/IDEAS b/IDEAS index 1d326f2..86eca17 100644 --- a/IDEAS +++ b/IDEAS @@ -13,6 +13,7 @@ certainly requires seperate processes or threads. Semantic tab-completion via iperl/ipython buffers... after syntax check, the file will be read into an interactive buffer, which can then be hooked into in order to support tab completion! +(mostly done!) 2008/05/11: diff --git a/buffer.py b/buffer.py index 2cf2b34..cd0f06c 100644 --- a/buffer.py +++ b/buffer.py @@ -412,7 +412,7 @@ class InterpreterBuffer(Buffer): readre = re.compile('^([A-Z]+):(.*)\n$') def __init__(self, parent, app): self.application = app - if hasattr(parent, 'path'): + if parent and hasattr(parent, 'path'): self.parent = parent else: self.parent = None @@ -479,6 +479,15 @@ class IperlBuffer(InterpreterBuffer): _basename = 'IPerl' btype = 'iperl' modename = 'iperl' + def create_name(cls, parent): + if parent and hasattr(parent, 'path'): + if parent.path.endswith('.pm'): + return '*%s:%s*' % (cls._basename, parent.name()) + else: + raise Exception, "not a perl module" + else: + return '*%s*' % cls._basename + create_name = classmethod(create_name) def get_cmd(self): if self.parent: return ('iperl', '-p', '-r', self.parent.path) diff --git a/method/introspect.py b/method/introspect.py index c147688..73fe656 100644 --- a/method/introspect.py +++ b/method/introspect.py @@ -85,9 +85,15 @@ class GetToken(Method): class TokenComplete(Method): '''Complete token names based on other tokens in the buffer''' _mini_prompt = 'Token Complete' + _tabber = completer.TokenCompleter() + class Dummy(object): pass + def _complete(self, s): + dw = self.Dummy() + dw.buffer = self.Dummy() + dw.buffer.method = self + return self._tabber.tab_string(s, dw) def _execute(self, w, **vargs): self.old_window = w - tabber = completer.TokenCompleter() t = w.get_token2() if t is None: w.set_error("No token to complete!") @@ -96,11 +102,10 @@ class TokenComplete(Method): w.set_error("Will not complete reserved token") return - class Dummy(object): pass - dw = Dummy() - dw.buffer = Dummy() + dw = self.Dummy() + dw.buffer = self.Dummy() dw.buffer.method = self - (s2, exists, complete) = tabber.tab_string(t.string, dw) + (s2, exists, complete) = self._tabber.tab_string(t.string, dw) p1 = Point(t.x, t.y) p2 = Point(t.end_x(), t.y) @@ -114,10 +119,8 @@ class TokenComplete(Method): callback(s2) return else: - if exists: - pass w.application.open_mini_buffer("%s: " % self._mini_prompt, callback, - method=self, tabber=tabber, + method=self, tabber=self._tabber, startvalue=s2) class OpenConsole(Method): diff --git a/mode/perl.py b/mode/perl.py index 71ab272..bcddc22 100644 --- a/mode/perl.py +++ b/mode/perl.py @@ -493,6 +493,17 @@ class PerlWrapParagraph(method.WrapParagraph): class PerlSemanticComplete(method.introspect.TokenComplete): _mini_prompt = 'Semantic Complete' + def _prune_candidates(self, t, minlen, candidates): + if not candidates: + return ([], t.string) + i = len(t.string) + while i < minlen: + c = candidates[0][i] + for s in candidates: + if s[i] != c: + return (candidates, candidates[0][:i]) + i += 1 + return (candidates, candidates[0][:minlen]) def _min_completion(self, w, t): a = w.application a.methods['iperl-path-start'].execute(w, switch=False) @@ -502,7 +513,7 @@ class PerlSemanticComplete(method.introspect.TokenComplete): line = w.buffer.lines[t.y] (x1, x2) = (t.x, t.end_x()) - candidates = [t.string + s for s in b.readline_completions(x1, x2, line)] + candidates = b.readline_completions(x1, x2, line) minlen = None for candidate in candidates: @@ -512,6 +523,32 @@ class PerlSemanticComplete(method.introspect.TokenComplete): minlen = min(minlen, len(candidate)) return self._prune_candidates(t, minlen, candidates) + def _execute(self, w, **vargs): + t = w.get_token2() + + if t is None: + w.set_error("No token to complete!") + return + elif regex.reserved_token_names.match(t.name): + w.set_error("Will not complete reserved token") + return + + (candidates, result) = self._min_completion(w, t) + + if candidates: + p1 = Point(t.x, t.y) + p2 = Point(t.end_x(), t.y) + w.buffer.delete(p1, p2) + w.insert_string(p1, result) + + if not candidates: + w.set_error("No completion: %r" % result) + elif len(candidates) == 1: + w.set_error("Unique completion: %r" % result) + elif result in candidates: + w.set_error("Ambiguous completion: %r" % candidates) + else: + w.set_error("Partial completion: %r" % candidates) class PerlOpenModule(method.Method): args = [Argument("module", type=type(""), prompt="Open Perl Module: ")]