mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 15:24:46 +08:00
module imports are working now
This commit is contained in:
30
evaluate.py
30
evaluate.py
@@ -12,6 +12,14 @@ import debug
|
|||||||
import builtin
|
import builtin
|
||||||
|
|
||||||
|
|
||||||
|
memoize_caches = []
|
||||||
|
|
||||||
|
|
||||||
|
def clear_caches():
|
||||||
|
for m in memoize_caches:
|
||||||
|
m.clear()
|
||||||
|
|
||||||
|
|
||||||
def memoize(default=None):
|
def memoize(default=None):
|
||||||
"""
|
"""
|
||||||
This is a typical memoization decorator, BUT there is one difference:
|
This is a typical memoization decorator, BUT there is one difference:
|
||||||
@@ -23,6 +31,7 @@ def memoize(default=None):
|
|||||||
"""
|
"""
|
||||||
def func(function):
|
def func(function):
|
||||||
memo = {}
|
memo = {}
|
||||||
|
memoize_caches.append(memo)
|
||||||
|
|
||||||
def wrapper(*args):
|
def wrapper(*args):
|
||||||
if args in memo:
|
if args in memo:
|
||||||
@@ -201,12 +210,13 @@ def strip_imports(scopes):
|
|||||||
if isinstance(s, parsing.Import):
|
if isinstance(s, parsing.Import):
|
||||||
print 'dini mueter, steile griech!'
|
print 'dini mueter, steile griech!'
|
||||||
try:
|
try:
|
||||||
new = follow_import(s)
|
new_scopes = follow_import(s)
|
||||||
except modules.ModuleNotFound:
|
except modules.ModuleNotFound:
|
||||||
debug.dbg('Module not found: ' + str(s))
|
debug.dbg('Module not found: ' + str(s))
|
||||||
else:
|
else:
|
||||||
result.append(new)
|
result += new_scopes
|
||||||
result += strip_imports(i for i in new.get_imports() if i.star)
|
for n in new_scopes:
|
||||||
|
result += strip_imports(i for i in n.get_imports() if i.star)
|
||||||
else:
|
else:
|
||||||
result.append(s)
|
result.append(s)
|
||||||
return result
|
return result
|
||||||
@@ -319,9 +329,13 @@ def follow_import(_import):
|
|||||||
if _import.namespace:
|
if _import.namespace:
|
||||||
ns_list += _import.namespace.names
|
ns_list += _import.namespace.names
|
||||||
|
|
||||||
scope, rest = modules.find_module(ns_list)
|
loaded_in = _import.get_parent_until()
|
||||||
if rest:
|
|
||||||
scope = follow_path(rest.__iter__(), scope)
|
|
||||||
|
|
||||||
debug.dbg('after import', scope, rest)
|
scope, rest = modules.find_module(loaded_in, ns_list)
|
||||||
return scope
|
if rest:
|
||||||
|
scopes = follow_path(rest.__iter__(), scope)
|
||||||
|
else:
|
||||||
|
scopes = [scope]
|
||||||
|
|
||||||
|
debug.dbg('after import', scopes, rest)
|
||||||
|
return scopes
|
||||||
|
|||||||
24
ftest.py
24
ftest.py
@@ -3,26 +3,16 @@
|
|||||||
import functions
|
import functions
|
||||||
|
|
||||||
#functions.debug.debug_function = functions.debug.print_to_stdout
|
#functions.debug.debug_function = functions.debug.print_to_stdout
|
||||||
functions.debug.ignored_modules += ['parsing', 'builtin']
|
#functions.debug.ignored_modules += ['parsing', 'builtin']
|
||||||
functions.modules.module_find_path.insert(0, '.')
|
functions.modules.module_find_path.insert(0, '.')
|
||||||
|
|
||||||
with open('test.py') as f:
|
f_name = 'test.py'
|
||||||
|
import os
|
||||||
|
path = os.getcwd() + '/' + f_name
|
||||||
|
|
||||||
|
with open(path) as f:
|
||||||
code = f.read()
|
code = f.read()
|
||||||
for i in range(1):
|
for i in range(1):
|
||||||
completions = functions.complete(code, 50, 200)
|
completions = functions.complete(code, 150, 200, path)
|
||||||
|
|
||||||
print '\n', ', '.join(str(c) for c in completions)
|
print '\n', ', '.join(str(c) for c in completions)
|
||||||
|
|
||||||
out = []
|
|
||||||
for c in completions:
|
|
||||||
d = dict(word=str(c),
|
|
||||||
abbr=c.complete,
|
|
||||||
menu=c.description, # the stuff directly behind the completion
|
|
||||||
info=c.help, # docstr and similar stuff
|
|
||||||
kind=c.type, # completion type
|
|
||||||
icase=1, # case insensitive
|
|
||||||
dup=1, # allow duplicates (maybe later remove this)
|
|
||||||
)
|
|
||||||
out.append(d)
|
|
||||||
|
|
||||||
print str(out)
|
|
||||||
|
|||||||
52
functions.py
52
functions.py
@@ -12,23 +12,23 @@ __all__ = ['complete', 'get_completion_parts', 'complete_test', 'set_debug_funct
|
|||||||
class FileWithCursor(modules.File):
|
class FileWithCursor(modules.File):
|
||||||
"""
|
"""
|
||||||
Manages all files, that are parsed and caches them.
|
Manages all files, that are parsed and caches them.
|
||||||
Important are the params source and module_name, one of them has to
|
Important are the params source and module_path, one of them has to
|
||||||
be there.
|
be there.
|
||||||
|
|
||||||
:param source: The source code of the file.
|
:param source: The source code of the file.
|
||||||
:param module_name: The module name of the file.
|
:param module_path: The module name of the file.
|
||||||
:param row: The row, the user is currently in. Only important for the \
|
:param row: The row, the user is currently in. Only important for the \
|
||||||
main file.
|
main file.
|
||||||
"""
|
"""
|
||||||
def __init__(self, module_name, source, row):
|
def __init__(self, module_path, source, row):
|
||||||
super(FileWithCursor, self).__init__(module_name, source)
|
super(FileWithCursor, self).__init__(module_path, source)
|
||||||
self.row = row
|
self.row = row
|
||||||
|
|
||||||
# this two are only used, because there is no nonlocal in Python 2
|
# this two are only used, because there is no nonlocal in Python 2
|
||||||
self._row_temp = None
|
self._row_temp = None
|
||||||
self._relevant_temp = None
|
self._relevant_temp = None
|
||||||
|
|
||||||
self._parser = parsing.PyFuzzyParser(source, row)
|
self._parser = parsing.PyFuzzyParser(source, module_path, row)
|
||||||
|
|
||||||
def get_row_path(self, column):
|
def get_row_path(self, column):
|
||||||
""" Get the path under the cursor. """
|
""" Get the path under the cursor. """
|
||||||
@@ -122,9 +122,29 @@ class Completion(object):
|
|||||||
except:
|
except:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@property
|
def get_type(self):
|
||||||
def type(self):
|
return type(self.name.parent)
|
||||||
return '' # type(self.name)
|
|
||||||
|
def get_vim_type(self):
|
||||||
|
"""
|
||||||
|
This is the only function, which is vim specific, it returns the vim
|
||||||
|
type, see help(complete-items)
|
||||||
|
"""
|
||||||
|
typ = self.get_type()
|
||||||
|
if typ == parsing.Statement:
|
||||||
|
return 'v' # variable
|
||||||
|
elif typ == parsing.Function:
|
||||||
|
return 'f' # function / method
|
||||||
|
elif typ in [parsing.Class, evaluate.Instance]:
|
||||||
|
return 't' # typedef -> abused as class
|
||||||
|
elif typ == parsing.Import:
|
||||||
|
return 'd' # define -> abused as import
|
||||||
|
if typ == parsing.Param:
|
||||||
|
return 'm' # member -> abused as param
|
||||||
|
else:
|
||||||
|
debug.dbg('other python type: ', typ)
|
||||||
|
|
||||||
|
return ''
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name.names[-1]
|
return self.name.names[-1]
|
||||||
@@ -138,7 +158,7 @@ def get_completion_parts(path):
|
|||||||
match = re.match(r'^(.*?)(\.|)(\w?[\w\d]*)$', path, flags=re.S)
|
match = re.match(r'^(.*?)(\.|)(\w?[\w\d]*)$', path, flags=re.S)
|
||||||
return match.groups()
|
return match.groups()
|
||||||
|
|
||||||
def complete(source, row, column, file_callback=None):
|
def complete(source, row, column, source_path):
|
||||||
"""
|
"""
|
||||||
An auto completer for python files.
|
An auto completer for python files.
|
||||||
|
|
||||||
@@ -148,17 +168,20 @@ def complete(source, row, column, file_callback=None):
|
|||||||
:type row: int
|
:type row: int
|
||||||
:param col: The column to complete in.
|
:param col: The column to complete in.
|
||||||
:type col: int
|
:type col: int
|
||||||
|
:param source_path: The path in the os, the current module is in.
|
||||||
|
:type source_path: int
|
||||||
|
|
||||||
:return: list of completion objects
|
:return: list of completion objects
|
||||||
:rtype: list
|
:rtype: list
|
||||||
"""
|
"""
|
||||||
f = FileWithCursor('__main__', source=source, row=row)
|
f = FileWithCursor(source_path, source=source, row=row)
|
||||||
scope = f.parser.user_scope
|
scope = f.parser.user_scope
|
||||||
path = f.get_row_path(column)
|
path = f.get_row_path(column)
|
||||||
debug.dbg('completion_start: %s in %s' % (path, scope))
|
debug.dbg('completion_start: %s in %s' % (path, scope))
|
||||||
|
|
||||||
# just parse one statement, take it and evaluate it
|
# just parse one statement, take it and evaluate it
|
||||||
path, dot, like = get_completion_parts(path)
|
path, dot, like = get_completion_parts(path)
|
||||||
r = parsing.PyFuzzyParser(path)
|
r = parsing.PyFuzzyParser(path, source_path)
|
||||||
try:
|
try:
|
||||||
stmt = r.top.statements[0]
|
stmt = r.top.statements[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@@ -171,13 +194,11 @@ def complete(source, row, column, file_callback=None):
|
|||||||
for s in scopes:
|
for s in scopes:
|
||||||
completions += s.get_defined_names()
|
completions += s.get_defined_names()
|
||||||
|
|
||||||
print repr(path), repr(dot), repr(like), row, column
|
|
||||||
print len(completions)
|
|
||||||
needs_dot = not dot and path
|
needs_dot = not dot and path
|
||||||
completions = [Completion(c, needs_dot, len(like)) for c in completions
|
completions = [Completion(c, needs_dot, len(like)) for c in completions
|
||||||
if c.names[-1].lower().startswith(like.lower())]
|
if c.names[-1].lower().startswith(like.lower())]
|
||||||
print 'nr2', len(completions)
|
|
||||||
|
|
||||||
|
_clear_caches()
|
||||||
return completions
|
return completions
|
||||||
|
|
||||||
|
|
||||||
@@ -245,3 +266,6 @@ def set_debug_function(func_cb):
|
|||||||
:param func_cb: The callback function for debug messages, with n params.
|
:param func_cb: The callback function for debug messages, with n params.
|
||||||
"""
|
"""
|
||||||
debug.debug_function = func_cb
|
debug.debug_function = func_cb
|
||||||
|
|
||||||
|
def _clear_caches():
|
||||||
|
evaluate.clear_caches()
|
||||||
|
|||||||
43
modules.py
43
modules.py
@@ -1,5 +1,6 @@
|
|||||||
import imp
|
import imp
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
import debug
|
import debug
|
||||||
import parsing
|
import parsing
|
||||||
@@ -20,11 +21,11 @@ class File(object):
|
|||||||
Manages all files, that are parsed and caches them.
|
Manages all files, that are parsed and caches them.
|
||||||
|
|
||||||
:param source: The source code of the file.
|
:param source: The source code of the file.
|
||||||
:param module_name: The module name of the file.
|
:param module_path: The module path of the file.
|
||||||
"""
|
"""
|
||||||
def __init__(self, module_name, source):
|
def __init__(self, module_path, source):
|
||||||
self.source = source
|
self.source = source
|
||||||
self.module_name = module_name
|
self.module_path = module_path
|
||||||
self._line_cache = None
|
self._line_cache = None
|
||||||
self._parser = None
|
self._parser = None
|
||||||
|
|
||||||
@@ -32,30 +33,34 @@ class File(object):
|
|||||||
def parser(self):
|
def parser(self):
|
||||||
if self._parser:
|
if self._parser:
|
||||||
return self._parser
|
return self._parser
|
||||||
if not self.module_name and not self.source:
|
if not self.module_path and not self.source:
|
||||||
raise AttributeError("Submit a module name or the source code")
|
raise AttributeError("Submit a module name or the source code")
|
||||||
elif self.module_name:
|
elif self.module_path:
|
||||||
return self._load_module()
|
return self._load_module()
|
||||||
|
|
||||||
def _load_module(self):
|
def _load_module(self):
|
||||||
self._parser = parsing.PyFuzzyParser(self.source)
|
self._parser = parsing.PyFuzzyParser(self.source, self.module_path)
|
||||||
del self.source # efficiency
|
del self.source # efficiency
|
||||||
return self._parser
|
return self._parser
|
||||||
|
|
||||||
def find_module(point_path):
|
def find_module(current_module, point_path):
|
||||||
"""
|
"""
|
||||||
Find a module with a path (of the module, like usb.backend.libusb10).
|
Find a module with a path (of the module, like usb.backend.libusb10).
|
||||||
|
|
||||||
|
Relative imports: http://www.python.org/dev/peps/pep-0328
|
||||||
|
are only used like this (py3000): from .module import name.
|
||||||
|
|
||||||
|
:param current_ns_path: A path to the current namespace.
|
||||||
:param point_path: A name from the parser.
|
:param point_path: A name from the parser.
|
||||||
:return: The rest of the path, and the module top scope.
|
:return: The rest of the path, and the module top scope.
|
||||||
"""
|
"""
|
||||||
def follow_str(ns, string):
|
def follow_str(ns, string):
|
||||||
debug.dbg('follow_module', ns, string)
|
debug.dbg('follow_module', ns, string)
|
||||||
if ns:
|
if ns:
|
||||||
path = ns[1]
|
path = [ns[1]]
|
||||||
else:
|
else:
|
||||||
# TODO modules can be system modules, without '.' in path
|
# TODO modules can be system modules, without '.' in path
|
||||||
path = module_find_path
|
path = None
|
||||||
debug.dbg('search_module', string, path)
|
debug.dbg('search_module', string, path)
|
||||||
try:
|
try:
|
||||||
i = imp.find_module(string, path)
|
i = imp.find_module(string, path)
|
||||||
@@ -67,8 +72,9 @@ def find_module(point_path):
|
|||||||
raise
|
raise
|
||||||
return i
|
return i
|
||||||
|
|
||||||
# now execute those paths
|
|
||||||
current_namespace = None
|
current_namespace = None
|
||||||
|
sys.path.insert(0, os.path.dirname(current_module.module_path))
|
||||||
|
# now execute those paths
|
||||||
rest = []
|
rest = []
|
||||||
for i, s in enumerate(point_path):
|
for i, s in enumerate(point_path):
|
||||||
try:
|
try:
|
||||||
@@ -80,8 +86,19 @@ def find_module(point_path):
|
|||||||
raise ModuleNotFound(
|
raise ModuleNotFound(
|
||||||
'The module you searched has not been found')
|
'The module you searched has not been found')
|
||||||
|
|
||||||
if current_namespace[0]:
|
sys.path.pop(0)
|
||||||
f = File(current_namespace[2], current_namespace[0].read())
|
path = current_namespace[1]
|
||||||
|
is_package_directory = current_namespace[2][2] == imp.PKG_DIRECTORY
|
||||||
|
|
||||||
|
if is_package_directory or current_namespace[0]:
|
||||||
|
# is a directory module
|
||||||
|
if is_package_directory:
|
||||||
|
path += '/__init__.py'
|
||||||
|
with open(path) as f:
|
||||||
|
source = f.read()
|
||||||
else:
|
else:
|
||||||
f = builtin.Parser(current_namespace[1])
|
source = current_namespace[0].read()
|
||||||
|
f = File(path, source)
|
||||||
|
else:
|
||||||
|
f = builtin.Parser(path)
|
||||||
return f.parser.top, rest
|
return f.parser.top, rest
|
||||||
|
|||||||
75
parsing.py
75
parsing.py
@@ -99,7 +99,6 @@ class Scope(Simple):
|
|||||||
self.subscopes = []
|
self.subscopes = []
|
||||||
self.imports = []
|
self.imports = []
|
||||||
self.statements = []
|
self.statements = []
|
||||||
self.global_vars = []
|
|
||||||
self.docstr = docstr
|
self.docstr = docstr
|
||||||
|
|
||||||
def add_scope(self, sub, decorators):
|
def add_scope(self, sub, decorators):
|
||||||
@@ -154,18 +153,6 @@ class Scope(Simple):
|
|||||||
i += s.get_imports()
|
i += s.get_imports()
|
||||||
return i
|
return i
|
||||||
|
|
||||||
def add_global(self, name):
|
|
||||||
"""
|
|
||||||
Global means in these context a function (subscope) which has a global
|
|
||||||
statement.
|
|
||||||
This is only relevant for the top scope.
|
|
||||||
|
|
||||||
:param name: The name of the global.
|
|
||||||
:type name: Name
|
|
||||||
"""
|
|
||||||
self.global_vars.append(name)
|
|
||||||
# set no parent here, because globals are not defined in this scope.
|
|
||||||
|
|
||||||
def get_code(self, first_indent=False, indention=" "):
|
def get_code(self, first_indent=False, indention=" "):
|
||||||
"""
|
"""
|
||||||
:return: Returns the code of the current scope.
|
:return: Returns the code of the current scope.
|
||||||
@@ -203,11 +190,10 @@ class Scope(Simple):
|
|||||||
|
|
||||||
# function and class names
|
# function and class names
|
||||||
n += [s.name for s in self.subscopes]
|
n += [s.name for s in self.subscopes]
|
||||||
n += self.global_vars
|
|
||||||
|
|
||||||
for i in self.imports:
|
for i in self.imports:
|
||||||
if not i.star:
|
if not i.star:
|
||||||
n += i.get_names()
|
n += i.get_defined_names()
|
||||||
|
|
||||||
return n
|
return n
|
||||||
|
|
||||||
@@ -229,12 +215,41 @@ class Scope(Simple):
|
|||||||
try:
|
try:
|
||||||
name = self.command
|
name = self.command
|
||||||
except:
|
except:
|
||||||
name = 'global'
|
name = self.module_path
|
||||||
|
|
||||||
return "<%s: %s@%s-%s>" % \
|
return "<%s: %s@%s-%s>" % \
|
||||||
(self.__class__.__name__, name, self.line_nr, self.line_end)
|
(self.__class__.__name__, name, self.line_nr, self.line_end)
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalScope(Scope):
|
||||||
|
"""
|
||||||
|
The top scope, which is a module.
|
||||||
|
I don't know why I didn't name it Module :-)
|
||||||
|
"""
|
||||||
|
def __init__(self, module_path, docstr=''):
|
||||||
|
super(GlobalScope, self).__init__(module_path, docstr)
|
||||||
|
self.module_path = module_path
|
||||||
|
self.global_vars = []
|
||||||
|
|
||||||
|
def add_global(self, name):
|
||||||
|
"""
|
||||||
|
Global means in these context a function (subscope) which has a global
|
||||||
|
statement.
|
||||||
|
This is only relevant for the top scope.
|
||||||
|
|
||||||
|
:param name: The name of the global.
|
||||||
|
:type name: Name
|
||||||
|
"""
|
||||||
|
self.global_vars.append(name)
|
||||||
|
# set no parent here, because globals are not defined in this scope.
|
||||||
|
|
||||||
|
def get_set_vars(self):
|
||||||
|
n = []
|
||||||
|
n += super(GlobalScope, self).get_set_vars()
|
||||||
|
n += self.global_vars
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
class Class(Scope):
|
class Class(Scope):
|
||||||
"""
|
"""
|
||||||
Used to store the parsed contents of a python class.
|
Used to store the parsed contents of a python class.
|
||||||
@@ -420,7 +435,7 @@ class Import(Simple):
|
|||||||
:type star: bool
|
:type star: bool
|
||||||
"""
|
"""
|
||||||
def __init__(self, indent, line_nr, line_end, namespace, alias='', \
|
def __init__(self, indent, line_nr, line_end, namespace, alias='', \
|
||||||
from_ns='', star=False):
|
from_ns='', star=False, relative_count=None):
|
||||||
super(Import, self).__init__(indent, line_nr, line_end)
|
super(Import, self).__init__(indent, line_nr, line_end)
|
||||||
|
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
@@ -436,6 +451,7 @@ class Import(Simple):
|
|||||||
from_ns.parent = self
|
from_ns.parent = self
|
||||||
|
|
||||||
self.star = star
|
self.star = star
|
||||||
|
self.relative_count = relative_count
|
||||||
|
|
||||||
def get_code(self):
|
def get_code(self):
|
||||||
if self.alias:
|
if self.alias:
|
||||||
@@ -449,7 +465,7 @@ class Import(Simple):
|
|||||||
else:
|
else:
|
||||||
return "import " + ns_str + '\n'
|
return "import " + ns_str + '\n'
|
||||||
|
|
||||||
def get_names(self):
|
def get_defined_names(self):
|
||||||
if self.star:
|
if self.star:
|
||||||
return [self]
|
return [self]
|
||||||
return [self.alias] if self.alias else [self.namespace]
|
return [self.alias] if self.alias else [self.namespace]
|
||||||
@@ -805,12 +821,12 @@ class PyFuzzyParser(object):
|
|||||||
:param user_line: The line, the user is currently on.
|
:param user_line: The line, the user is currently on.
|
||||||
:type user_line: int
|
:type user_line: int
|
||||||
"""
|
"""
|
||||||
def __init__(self, code, user_line=None):
|
def __init__(self, code, module_path=None, user_line=None):
|
||||||
self.user_line = user_line
|
self.user_line = user_line
|
||||||
self.code = code + '\n' # end with \n, because the parser needs it
|
self.code = code + '\n' # end with \n, because the parser needs it
|
||||||
|
|
||||||
# initialize global Scope
|
# initialize global Scope
|
||||||
self.top = Scope(0, 0)
|
self.top = GlobalScope(module_path)
|
||||||
self.scope = self.top
|
self.scope = self.top
|
||||||
self.current = (None, None, None)
|
self.current = (None, None, None)
|
||||||
|
|
||||||
@@ -1072,6 +1088,7 @@ class PyFuzzyParser(object):
|
|||||||
continue
|
continue
|
||||||
elif '=' in tok and not tok in ['>=', '<=', '==', '!=']:
|
elif '=' in tok and not tok in ['>=', '<=', '==', '!=']:
|
||||||
# there has been an assignement -> change vars
|
# there has been an assignement -> change vars
|
||||||
|
if level == 0:
|
||||||
set_vars = used_vars
|
set_vars = used_vars
|
||||||
used_vars = []
|
used_vars = []
|
||||||
elif tok in ['{', '(', '[']:
|
elif tok in ['{', '(', '[']:
|
||||||
@@ -1139,8 +1156,8 @@ class PyFuzzyParser(object):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
token_type, tok, indent = self.next()
|
token_type, tok, indent = self.next()
|
||||||
debug.dbg('main: tok=[%s] type=[%s] indent=[%s]'\
|
#debug.dbg('main: tok=[%s] type=[%s] indent=[%s]'\
|
||||||
% (tok, token_type, indent))
|
# % (tok, token_type, indent))
|
||||||
|
|
||||||
while token_type == tokenize.DEDENT and self.scope != self.top:
|
while token_type == tokenize.DEDENT and self.scope != self.top:
|
||||||
debug.dbg('dedent', self.scope)
|
debug.dbg('dedent', self.scope)
|
||||||
@@ -1187,10 +1204,19 @@ class PyFuzzyParser(object):
|
|||||||
for m, alias in imports:
|
for m, alias in imports:
|
||||||
i = Import(indent, start_line, self.line_nr, m, alias)
|
i = Import(indent, start_line, self.line_nr, m, alias)
|
||||||
self.scope.add_import(i)
|
self.scope.add_import(i)
|
||||||
|
debug.dbg("new import: %s" % (i))
|
||||||
self.freshscope = False
|
self.freshscope = False
|
||||||
elif tok == 'from':
|
elif tok == 'from':
|
||||||
|
# take care for relative imports
|
||||||
|
relative_count = 0
|
||||||
|
while 1:
|
||||||
|
token_type, tok, indent = self.next()
|
||||||
|
if tok != '.':
|
||||||
|
break;
|
||||||
|
relative_count += 1
|
||||||
|
# the from import
|
||||||
mod, token_type, tok, start_indent, start_line2 = \
|
mod, token_type, tok, start_indent, start_line2 = \
|
||||||
self._parsedotname()
|
self._parsedotname(self.current)
|
||||||
if not mod or tok != "import":
|
if not mod or tok != "import":
|
||||||
debug.warning("from: syntax error@%s" %
|
debug.warning("from: syntax error@%s" %
|
||||||
self.line_nr)
|
self.line_nr)
|
||||||
@@ -1202,8 +1228,9 @@ class PyFuzzyParser(object):
|
|||||||
if star:
|
if star:
|
||||||
name = None
|
name = None
|
||||||
i = Import(indent, start_line, self.line_nr, name,
|
i = Import(indent, start_line, self.line_nr, name,
|
||||||
alias, mod, star)
|
alias, mod, star, relative_count)
|
||||||
self.scope.add_import(i)
|
self.scope.add_import(i)
|
||||||
|
debug.dbg("new from: %s" % (i))
|
||||||
self.freshscope = False
|
self.freshscope = False
|
||||||
#loops
|
#loops
|
||||||
elif tok == 'for':
|
elif tok == 'for':
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ if !has('python')
|
|||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" ------------------------------------------------------------------------
|
||||||
|
" Completion
|
||||||
|
" ------------------------------------------------------------------------
|
||||||
|
|
||||||
function! jedi#Complete(findstart, base)
|
function! jedi#Complete(findstart, base)
|
||||||
if a:findstart == 1
|
if a:findstart == 1
|
||||||
@@ -17,17 +20,19 @@ function! jedi#Complete(findstart, base)
|
|||||||
else
|
else
|
||||||
python << PYTHONEOF
|
python << PYTHONEOF
|
||||||
if 1:
|
if 1:
|
||||||
|
# TODO change the finstart column, to switch cases, if they are not right.
|
||||||
row, column = vim.current.window.cursor
|
row, column = vim.current.window.cursor
|
||||||
|
buf_path = vim.current.buffer.name
|
||||||
source = '\n'.join(vim.current.buffer)
|
source = '\n'.join(vim.current.buffer)
|
||||||
try:
|
try:
|
||||||
completions = functions.complete(source, row, column)
|
completions = functions.complete(source, row, column, buf_path)
|
||||||
out = []
|
out = []
|
||||||
for c in completions:
|
for c in completions:
|
||||||
d = dict(word=c.complete,
|
d = dict(word=c.complete,
|
||||||
abbr=str(c),
|
abbr=str(c),
|
||||||
menu=c.description, # stuff directly behind the completion
|
menu=c.description, # stuff directly behind the completion
|
||||||
info=c.help, # docstr and similar stuff
|
info=c.help, # docstr and similar stuff
|
||||||
kind=c.type, # completion type
|
kind=c.get_vim_type(), # completion type
|
||||||
icase=1, # case insensitive
|
icase=1, # case insensitive
|
||||||
dup=1, # allow duplicates (maybe later remove this)
|
dup=1, # allow duplicates (maybe later remove this)
|
||||||
)
|
)
|
||||||
@@ -35,10 +40,11 @@ if 1:
|
|||||||
|
|
||||||
strout = str(out)
|
strout = str(out)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print 'error:', e
|
# print to stdout, will be in :messages
|
||||||
|
print(traceback.format_exc())
|
||||||
strout = ''
|
strout = ''
|
||||||
|
|
||||||
print 'end', strout
|
#print 'end', strout
|
||||||
vim.command('return ' + strout)
|
vim.command('return ' + strout)
|
||||||
PYTHONEOF
|
PYTHONEOF
|
||||||
endif
|
endif
|
||||||
@@ -48,7 +54,7 @@ endfunction
|
|||||||
" ------------------------------------------------------------------------
|
" ------------------------------------------------------------------------
|
||||||
" Initialization of Jedi
|
" Initialization of Jedi
|
||||||
" ------------------------------------------------------------------------
|
" ------------------------------------------------------------------------
|
||||||
"
|
|
||||||
let s:current_file=expand("<sfile>")
|
let s:current_file=expand("<sfile>")
|
||||||
|
|
||||||
python << PYTHONEOF
|
python << PYTHONEOF
|
||||||
@@ -60,6 +66,8 @@ import sys
|
|||||||
from os.path import dirname
|
from os.path import dirname
|
||||||
sys.path.insert(0, dirname(dirname(vim.eval('s:current_file'))))
|
sys.path.insert(0, dirname(dirname(vim.eval('s:current_file'))))
|
||||||
|
|
||||||
|
import traceback # for exception output
|
||||||
|
|
||||||
import functions
|
import functions
|
||||||
PYTHONEOF
|
PYTHONEOF
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user