From baf8c60e9ac72bab9b2e693d69b5f2d6400c1363 Mon Sep 17 00:00:00 2001 From: David Halter Date: Sun, 8 Apr 2012 04:25:06 +0200 Subject: [PATCH] the auto completion is working! and may god bless you all! ;-) --- ftest.py | 16 +++++++++++- functions.py | 54 +++++++++++++++++++++++++++++++-------- plugin/jedi.vim | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ py_functions.vim | 63 --------------------------------------------- test.py | 2 +- 5 files changed, 125 insertions(+), 76 deletions(-) create mode 100644 plugin/jedi.vim delete mode 100644 py_functions.vim diff --git a/ftest.py b/ftest.py index 482be403..c4100098 100755 --- a/ftest.py +++ b/ftest.py @@ -2,7 +2,7 @@ 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.modules.module_find_path.insert(0, '.') @@ -12,3 +12,17 @@ for i in range(1): completions = functions.complete(code, 50, 200) 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) diff --git a/functions.py b/functions.py index bb37a7d9..8733ae23 100644 --- a/functions.py +++ b/functions.py @@ -6,7 +6,7 @@ import evaluate import modules import debug -__all__ = ['complete', 'complete_test', 'set_debug_function'] +__all__ = ['complete', 'get_completion_parts', 'complete_test', 'set_debug_function'] class FileWithCursor(modules.File): @@ -37,7 +37,7 @@ class FileWithCursor(modules.File): line = self.get_line(self._row_temp) if self._is_first: self._is_first = False - line = line[:column - 1] + line = line[:column] else: line = line + '\n' # add lines with a backslash at the end @@ -57,6 +57,7 @@ class FileWithCursor(modules.File): close_brackets = [')', ']', '}'] gen = tokenize.generate_tokens(fetch_line) + # TODO can happen: raise TokenError, ("EOF in multi-line statement" string = '' level = 0 for token_type, tok, start, end, line in gen: @@ -99,16 +100,44 @@ class FileWithCursor(modules.File): raise StopIteration() -class CompletionMatch(object): - def __init__(self, name, has_dot): +class Completion(object): + def __init__(self, name, needs_dot, like_name_length): self.name = name - self.has_dot = has_dot + self.needs_dot = needs_dot + self.like_name_length = like_name_length + + @property + def complete(self): + dot = '.' if self.needs_dot else '' + return dot + self.name.names[-1][self.like_name_length:] + + @property + def description(self): + return str(self.name.parent) + + @property + def help(self): + try: + return str(self.name.parent.docstr) + except: + return '' + + @property + def type(self): + return '' # type(self.name) def __str__(self): - dot = '' if self.has_dot else '.' - return dot + self.name.names[-1] + return self.name.names[-1] +def get_completion_parts(path): + """ + Returns the parts for the completion + :return: tuple - (path, dot, like) + """ + match = re.match(r'^(.*?)(\.|)(\w?[\w\d]*)$', path, flags=re.S) + return match.groups() + def complete(source, row, column, file_callback=None): """ An auto completer for python files. @@ -127,9 +156,8 @@ def complete(source, row, column, file_callback=None): path = f.get_row_path(column) debug.dbg('completion_start: %s in %s' % (path, scope)) - match = re.match(r'^(.+?)(?:(\.)(\w?[\w\d]*))?$', path, flags=re.S) - path, dot, like = match.groups() # just parse one statement, take it and evaluate it + path, dot, like = get_completion_parts(path) r = parsing.PyFuzzyParser(path) try: stmt = r.top.statements[0] @@ -143,8 +171,12 @@ def complete(source, row, column, file_callback=None): for s in scopes: completions += s.get_defined_names() - completions = [CompletionMatch(c, bool(dot)) for c in completions - if like in c.names[-1]] + print repr(path), repr(dot), repr(like), row, column + print len(completions) + needs_dot = not dot and path + completions = [Completion(c, needs_dot, len(like)) for c in completions + if c.names[-1].lower().startswith(like.lower())] + print 'nr2', len(completions) return completions diff --git a/plugin/jedi.vim b/plugin/jedi.vim new file mode 100644 index 00000000..01db24e6 --- /dev/null +++ b/plugin/jedi.vim @@ -0,0 +1,66 @@ +"py_fuzzycomplete.vim - Omni Completion for python in vim +" Maintainer: David Halter +" Version: 0.1 +" +" This part of the software is just the vim interface. The main source code +" lies in the python files around it. + +if !has('python') + echomsg "Error: Required vim compiled with +python" + finish +endif + + +function! jedi#Complete(findstart, base) + if a:findstart == 1 + return col('.') + else +python << PYTHONEOF +if 1: + row, column = vim.current.window.cursor + source = '\n'.join(vim.current.buffer) + try: + completions = functions.complete(source, row, column) + out = [] + for c in completions: + d = dict(word=c.complete, + abbr=str(c), + menu=c.description, # 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) + + strout = str(out) + except Exception as e: + print 'error:', e + strout = '' + + print 'end', strout + vim.command('return ' + strout) +PYTHONEOF + endif +endfunction + + +" ------------------------------------------------------------------------ +" Initialization of Jedi +" ------------------------------------------------------------------------ +" +let s:current_file=expand("") + +python << PYTHONEOF +""" here we initialize the jedi stuff """ +import vim + +# update the system path, to include the python scripts +import sys +from os.path import dirname +sys.path.insert(0, dirname(dirname(vim.eval('s:current_file')))) + +import functions +PYTHONEOF + +" vim: set et ts=4: diff --git a/py_functions.vim b/py_functions.vim deleted file mode 100644 index 88cdff6a..00000000 --- a/py_functions.vim +++ /dev/null @@ -1,63 +0,0 @@ -"py_fuzzycomplete.vim - Omni Completion for python in vim -" Maintainer: David Halter -" Version: 0.1 -" -" This part of the software is just the vim interface. The main source code -" lies in the python files around it. - -if !has('python') - echo "Error: Required vim compiled with +python" - finish -endif - -function! pythoncomplete#Complete(findstart, base) - "findstart = 1 when we need to get the text length - " TODO check wheter this is really needed - if a:findstart == 1 - let line = getline('.') - let idx = col('.') - while idx > 0 - let idx -= 1 - let c = line[idx] - if c =~ '\w' - continue - elseif ! c =~ '\.' - let idx = -1 - break - else - break - endif - endwhile - - return idx - "findstart = 0 when we need to return the list of completions - else - execute "python vimcomplete()" - return g:pythoncomplete_completions - endif -endfunction - -function! s:DefPython() -python << PYTHONEOF -import functions - -def vimcomplete(): - (row, column) = vim.current.window.cursor - code = '\n'.join(vim.current.buffer) - all = functions.complete(code, row, column) - - dictstr = '[' - # have to do this for double quoting - for cmpl in all: - dictstr += '{' - for x in cmpl: dictstr += '"%s":"%s",' % (x,cmpl[x]) - dictstr += '"icase":0},' - if dictstr[-1] == ',': dictstr = dictstr[:-1] - dictstr += ']' - vim.command("silent let g:pythoncomplete_completions = %s" % dictstr) - -PYTHONEOF -endfunction - -call s:DefPython() -" vim: set et ts=4: diff --git a/test.py b/test.py index 1940ee45..516f0b32 100644 --- a/test.py +++ b/test.py @@ -47,7 +47,7 @@ class A(): return 8 + a.test() class init: def __init__(self, a, b=3, c = A): - a=0;self.a = a;self.a + a=0;self.a = a.i aclass = A()