Skip to content

Commit cf74ca3

Browse files
aaronmgriffinvim-scripts
authored andcommitted
Version 0.9
NOTE: This is a re-upload. Previous version had old version/updated headers still * Fixed docstring parsing for classes and functions * Fixed parsing of *args and **kwargs type arguments * Better function param parsing to handle things like tuples and lambda defaults args
1 parent 61431ec commit cf74ca3

1 file changed

Lines changed: 49 additions & 30 deletions

File tree

ftplugin/pythoncomplete.vim

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
"pythoncomplete.vim - Omni Completion for python
22
" Maintainer: Aaron Griffin <[email protected]>
3-
" Version: 0.8
4-
" Last Updated: 8 Oct 2007
3+
" Version: 0.9
4+
" Last Updated: 18 Jun 2009
55
"
66
" Changes
77
" TODO:
8-
" User defined docstrings aren't handled right...
98
" 'info' item output can use some formatting work
109
" Add an "unsafe eval" mode, to allow for return type evaluation
1110
" Complete basic syntax along with import statements
1211
" i.e. "import url<c-x,c-o>"
1312
" Continue parsing on invalid line??
1413
"
14+
" v 0.9
15+
" * Fixed docstring parsing for classes and functions
16+
" * Fixed parsing of *args and **kwargs type arguments
17+
" * Better function param parsing to handle things like tuples and
18+
" lambda defaults args
19+
"
1520
" v 0.8
1621
" * Fixed an issue where the FIRST assignment was always used instead of
1722
" using a subsequent assignment for a variable
@@ -69,7 +74,7 @@ function! pythoncomplete#Complete(findstart, base)
6974
while idx > 0
7075
let idx -= 1
7176
let c = line[idx]
72-
if c =~ '\w' || c =~ '\.' || c == '('
77+
if c =~ '\w' || c =~ '\.'
7378
let cword = c . cword
7479
continue
7580
elseif strlen(cword) > 0 || idx == 0
@@ -212,7 +217,7 @@ class Completer(object):
212217
if len(stmt) > 0 and stmt[-1] == '(':
213218
result = eval(_sanitize(stmt[:-1]), self.compldict)
214219
doc = result.__doc__
215-
if doc == None: doc = ''
220+
if doc is None: doc = ''
216221
args = self.get_arguments(result)
217222
return [{'word':self._cleanstr(args),'info':self._cleanstr(doc)}]
218223
elif ridx == -1:
@@ -229,18 +234,18 @@ class Completer(object):
229234

230235
try: maindoc = result.__doc__
231236
except: maindoc = ' '
232-
if maindoc == None: maindoc = ' '
237+
if maindoc is None: maindoc = ' '
233238
for m in all:
234239
if m == "_PyCmplNoType": continue #this is internal
235240
try:
236241
dbg('possible completion: %s' % m)
237242
if m.find(match) == 0:
238-
if result == None: inst = all[m]
243+
if result is None: inst = all[m]
239244
else: inst = getattr(result,m)
240245
try: doc = inst.__doc__
241246
except: doc = maindoc
242247
typestr = str(inst)
243-
if doc == None or doc == '': doc = maindoc
248+
if doc is None or doc == '': doc = maindoc
244249

245250
wrd = m[len(match):]
246251
c = {'word':wrd, 'abbr':m, 'info':self._cleanstr(doc)}
@@ -266,9 +271,9 @@ class Completer(object):
266271
return []
267272

268273
class Scope(object):
269-
def __init__(self,name,indent):
274+
def __init__(self,name,indent,docstr=''):
270275
self.subscopes = []
271-
self.docstr = ''
276+
self.docstr = docstr
272277
self.locals = []
273278
self.parent = None
274279
self.name = name
@@ -287,6 +292,7 @@ class Scope(object):
287292
while d.find(' ') > -1: d = d.replace(' ',' ')
288293
while d[0] in '"\'\t ': d = d[1:]
289294
while d[-1] in '"\'\t ': d = d[:-1]
295+
dbg("Scope(%s)::docstr = %s" % (self,d))
290296
self.docstr = d
291297

292298
def local(self,loc):
@@ -295,7 +301,7 @@ class Scope(object):
295301

296302
def copy_decl(self,indent=0):
297303
""" Copy a scope's declaration only, at the specified indent level - not local variables """
298-
return Scope(self.name,indent)
304+
return Scope(self.name,indent,self.docstr)
299305

300306
def _checkexisting(self,test):
301307
"Convienance function... keep out duplicates"
@@ -306,9 +312,8 @@ class Scope(object):
306312
self.locals.remove(l)
307313

308314
def get_code(self):
309-
# we need to start with this, to fix up broken completions
310-
# hopefully this name is unique enough...
311-
str = '"""'+self.docstr+'"""\n'
315+
str = ""
316+
if len(self.docstr) > 0: str += '"""'+self.docstr+'"""\n'
312317
for l in self.locals:
313318
if l.startswith('import'): str += l+'\n'
314319
str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n'
@@ -335,11 +340,11 @@ class Scope(object):
335340
return ' '*(self.indent+1)
336341

337342
class Class(Scope):
338-
def __init__(self, name, supers, indent):
339-
Scope.__init__(self,name,indent)
343+
def __init__(self, name, supers, indent, docstr=''):
344+
Scope.__init__(self,name,indent, docstr)
340345
self.supers = supers
341346
def copy_decl(self,indent=0):
342-
c = Class(self.name,self.supers,indent)
347+
c = Class(self.name,self.supers,indent, self.docstr)
343348
for s in self.subscopes:
344349
c.add(s.copy_decl(indent+1))
345350
return c
@@ -356,11 +361,11 @@ class Class(Scope):
356361

357362

358363
class Function(Scope):
359-
def __init__(self, name, params, indent):
360-
Scope.__init__(self,name,indent)
364+
def __init__(self, name, params, indent, docstr=''):
365+
Scope.__init__(self,name,indent, docstr)
361366
self.params = params
362367
def copy_decl(self,indent=0):
363-
return Function(self.name,self.params,indent)
368+
return Function(self.name,self.params,indent, self.docstr)
364369
def get_code(self):
365370
str = "%sdef %s(%s):\n" % \
366371
(self.currentindent(),self.name,','.join(self.params))
@@ -376,7 +381,7 @@ class PyParser:
376381
def _parsedotname(self,pre=None):
377382
#returns (dottedname, nexttoken)
378383
name = []
379-
if pre == None:
384+
if pre is None:
380385
tokentype, token, indent = self.next()
381386
if tokentype != NAME and token != '*':
382387
return ('', token)
@@ -410,17 +415,20 @@ class PyParser:
410415
while True:
411416
tokentype, token, indent = self.next()
412417
if token in (')', ',') and level == 1:
413-
names.append(name)
418+
if '=' not in name: name = name.replace(' ', '')
419+
names.append(name.strip())
414420
name = ''
415421
if token == '(':
416422
level += 1
423+
name += "("
417424
elif token == ')':
418425
level -= 1
419426
if level == 0: break
427+
else: name += ")"
420428
elif token == ',' and level == 1:
421429
pass
422430
else:
423-
name += str(token)
431+
name += "%s " % str(token)
424432
return names
425433

426434
def _parsefunction(self,indent):
@@ -500,17 +508,26 @@ class PyParser:
500508
#Handle 'self' params
501509
if scp.parent != None and type(scp.parent) == Class:
502510
slice = 1
503-
p = scp.params[0]
504-
i = p.find('=')
505-
if i != -1: p = p[:i]
506511
newscope.local('%s = %s' % (scp.params[0],scp.parent.name))
507512
for p in scp.params[slice:]:
508513
i = p.find('=')
509514
if len(p) == 0: continue
515+
pvar = ''
516+
ptype = ''
510517
if i == -1:
511-
newscope.local('%s = _PyCmplNoType()' % p)
518+
pvar = p
519+
ptype = '_PyCmplNoType()'
512520
else:
513-
newscope.local('%s = %s' % (p[:i],_sanitize(p[i+1])))
521+
pvar = p[:i]
522+
ptype = _sanitize(p[i+1:])
523+
if pvar.startswith('**'):
524+
pvar = pvar[2:]
525+
ptype = '{}'
526+
elif pvar.startswith('*'):
527+
pvar = pvar[1:]
528+
ptype = '[]'
529+
530+
newscope.local('%s = %s' % (pvar,ptype))
514531

515532
for s in scp.subscopes:
516533
ns = s.copy_decl(0)
@@ -538,17 +555,19 @@ class PyParser:
538555
self.scope = self.scope.pop(indent)
539556
elif token == 'def':
540557
func = self._parsefunction(indent)
541-
if func == None:
558+
if func is None:
542559
print "function: syntax error..."
543560
continue
561+
dbg("new scope: function")
544562
freshscope = True
545563
self.scope = self.scope.add(func)
546564
elif token == 'class':
547565
cls = self._parseclass(indent)
548-
if cls == None:
566+
if cls is None:
549567
print "class: syntax error..."
550568
continue
551569
freshscope = True
570+
dbg("new scope: class")
552571
self.scope = self.scope.add(cls)
553572

554573
elif token == 'import':

0 commit comments

Comments
 (0)