diff --git a/README.mdown b/README.mdown index 2ed2db92..8772c57b 100644 --- a/README.mdown +++ b/README.mdown @@ -27,7 +27,7 @@ Jedi supports many of the widely used Python features: - multiple returns / yields - tuple assignments / array indexing / dictionary indexing - exceptions / with-statement / - - \*args / \*\*args + - \*args / \*\*kwargs - decorators - generators (yield statement) diff --git a/functions.py b/functions.py index abdb2d82..580115cc 100644 --- a/functions.py +++ b/functions.py @@ -5,7 +5,12 @@ import evaluate import modules import debug -__all__ = ['complete', 'get_completion_parts', 'set_debug_function'] +__all__ = ['complete', 'goto', 'get_completion_parts', 'set_debug_function'] + + +class NotFoundError(Exception): + """ A custom error to avoid catching the wrong errors """ + pass class Completion(object): @@ -85,7 +90,7 @@ def complete(source, row, column, source_path): """ f = modules.ModuleWithCursor(source_path, source=source, row=row) scope = f.parser.user_scope - path = f.get_row_path(column) + path = f.get_path_until_cursor(column) debug.dbg('completion_start: %s in %s' % (path, scope)) # just parse one statement, take it and evaluate it @@ -124,6 +129,39 @@ def complete(source, row, column, source_path): return [Completion(c, needs_dot, len(like)) for c in set(completions)] +def prepare_goto(source, row, column, source_path, is_like_search): + f = modules.ModuleWithCursor(source_path, source=source, row=row) + scope = f.parser.user_scope + + if is_like_search: + path = f.get_path_until_cursor(column) + path, dot, like = get_completion_parts(path) + else: + path = f.get_path_under_cursor(column) + + debug.dbg('start: %s in %s' % (path, scope)) + + # just parse one statement, take it and evaluate it + r = parsing.PyFuzzyParser(path, source_path) + try: + stmt = r.top.statements[0] + except IndexError: + raise NotFoundError() + else: + stmt.line_nr = row + stmt.indent = column + stmt.parent = scope + scopes = evaluate.follow_statement(stmt, scope=scope) + return scope, scopes + + +def goto(source, row, column, source_path): + dummy, scopes = prepare_goto(source, row, column, source_path, False) + + _clear_caches() + return scopes + + def set_debug_function(func_cb): """ You can define a callback debug function to get all the debug messages. diff --git a/modules.py b/modules.py index 664a53f4..ebe6f840 100644 --- a/modules.py +++ b/modules.py @@ -1,3 +1,4 @@ +import re import tokenize import imp import os @@ -61,7 +62,7 @@ class ModuleWithCursor(Module): self._parser = parsing.PyFuzzyParser(source, path, row) - def get_row_path(self, column): + def get_path_until_cursor(self, column): """ Get the path under the cursor. """ self._is_first = True @@ -122,6 +123,15 @@ class ModuleWithCursor(Module): return string[::-1] + def get_path_under_cursor(self, column): + """ + Return the path under the cursor. If there is a rest of the path left, + it will be added to the stuff before it. + """ + line = self.get_line(self.row) + after = re.search("[\w\d]*", line[column:]).group(0) + return self.get_path_until_cursor(column) + after + def get_line(self, line): if not self._line_cache: self._line_cache = self.source.split('\n') diff --git a/parsetest.py b/parsetest.py index 156ff5dd..dbd5d8a0 100644 --- a/parsetest.py +++ b/parsetest.py @@ -177,4 +177,4 @@ def nexti(iterator, default=list): #exe[0]. #exe[4]['d'] -next(gen_exe).; gen_exe. +next(gen_exe).