comparison runtime/autoload/pythoncomplete.vim @ 2120:f63ace015c63

Updated runtime and language files.
author Bram Moolenaar <bram@zimbu.org>
date Wed, 17 Mar 2010 20:02:06 +0100
parents e63691e7c504
children ffad29dc7eee
comparison
equal deleted inserted replaced
2119:111554354870 2120:f63ace015c63
1 "pythoncomplete.vim - Omni Completion for python 1 "pythoncomplete.vim - Omni Completion for python
2 " Maintainer: Aaron Griffin <aaronmgriffin@gmail.com> 2 " Maintainer: Aaron Griffin <aaronmgriffin@gmail.com>
3 " Version: 0.7 3 " Version: 0.9
4 " Last Updated: 19 Oct 2006 4 " Last Updated: 18 Jun 2009
5 " 5 "
6 " Changes 6 " Changes
7 " TODO: 7 " TODO:
8 " User defined docstrings aren't handled right...
9 " 'info' item output can use some formatting work 8 " 'info' item output can use some formatting work
10 " Add an "unsafe eval" mode, to allow for return type evaluation 9 " Add an "unsafe eval" mode, to allow for return type evaluation
11 " Complete basic syntax along with import statements 10 " Complete basic syntax along with import statements
12 " i.e. "import url<c-x,c-o>" 11 " i.e. "import url<c-x,c-o>"
13 " Continue parsing on invalid line?? 12 " Continue parsing on invalid line??
13 "
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 "
20 " v 0.8
21 " * Fixed an issue where the FIRST assignment was always used instead of
22 " using a subsequent assignment for a variable
23 " * Fixed a scoping issue when working inside a parameterless function
24 "
14 " 25 "
15 " v 0.7 26 " v 0.7
16 " * Fixed function list sorting (_ and __ at the bottom) 27 " * Fixed function list sorting (_ and __ at the bottom)
17 " * Removed newline removal from docs. It appears vim handles these better in 28 " * Removed newline removal from docs. It appears vim handles these better in
18 " recent patches 29 " recent patches
61 let idx = col('.') 72 let idx = col('.')
62 let cword = '' 73 let cword = ''
63 while idx > 0 74 while idx > 0
64 let idx -= 1 75 let idx -= 1
65 let c = line[idx] 76 let c = line[idx]
66 if c =~ '\w' || c =~ '\.' || c == '(' 77 if c =~ '\w' || c =~ '\.'
67 let cword = c . cword 78 let cword = c . cword
68 continue 79 continue
69 elseif strlen(cword) > 0 || idx == 0 80 elseif strlen(cword) > 0 || idx == 0
70 break 81 break
71 endif 82 endif
204 all = {} 215 all = {}
205 ridx = stmt.rfind('.') 216 ridx = stmt.rfind('.')
206 if len(stmt) > 0 and stmt[-1] == '(': 217 if len(stmt) > 0 and stmt[-1] == '(':
207 result = eval(_sanitize(stmt[:-1]), self.compldict) 218 result = eval(_sanitize(stmt[:-1]), self.compldict)
208 doc = result.__doc__ 219 doc = result.__doc__
209 if doc == None: doc = '' 220 if doc is None: doc = ''
210 args = self.get_arguments(result) 221 args = self.get_arguments(result)
211 return [{'word':self._cleanstr(args),'info':self._cleanstr(doc)}] 222 return [{'word':self._cleanstr(args),'info':self._cleanstr(doc)}]
212 elif ridx == -1: 223 elif ridx == -1:
213 match = stmt 224 match = stmt
214 all = self.compldict 225 all = self.compldict
221 dbg("completing: stmt:%s" % stmt) 232 dbg("completing: stmt:%s" % stmt)
222 completions = [] 233 completions = []
223 234
224 try: maindoc = result.__doc__ 235 try: maindoc = result.__doc__
225 except: maindoc = ' ' 236 except: maindoc = ' '
226 if maindoc == None: maindoc = ' ' 237 if maindoc is None: maindoc = ' '
227 for m in all: 238 for m in all:
228 if m == "_PyCmplNoType": continue #this is internal 239 if m == "_PyCmplNoType": continue #this is internal
229 try: 240 try:
230 dbg('possible completion: %s' % m) 241 dbg('possible completion: %s' % m)
231 if m.find(match) == 0: 242 if m.find(match) == 0:
232 if result == None: inst = all[m] 243 if result is None: inst = all[m]
233 else: inst = getattr(result,m) 244 else: inst = getattr(result,m)
234 try: doc = inst.__doc__ 245 try: doc = inst.__doc__
235 except: doc = maindoc 246 except: doc = maindoc
236 typestr = str(inst) 247 typestr = str(inst)
237 if doc == None or doc == '': doc = maindoc 248 if doc is None or doc == '': doc = maindoc
238 249
239 wrd = m[len(match):] 250 wrd = m[len(match):]
240 c = {'word':wrd, 'abbr':m, 'info':self._cleanstr(doc)} 251 c = {'word':wrd, 'abbr':m, 'info':self._cleanstr(doc)}
241 if "function" in typestr: 252 if "function" in typestr:
242 c['word'] += '(' 253 c['word'] += '('
258 i = sys.exc_info() 269 i = sys.exc_info()
259 dbg("completion: %s,%s [stmt='%s']" % (i[0],i[1],stmt)) 270 dbg("completion: %s,%s [stmt='%s']" % (i[0],i[1],stmt))
260 return [] 271 return []
261 272
262 class Scope(object): 273 class Scope(object):
263 def __init__(self,name,indent): 274 def __init__(self,name,indent,docstr=''):
264 self.subscopes = [] 275 self.subscopes = []
265 self.docstr = '' 276 self.docstr = docstr
266 self.locals = [] 277 self.locals = []
267 self.parent = None 278 self.parent = None
268 self.name = name 279 self.name = name
269 self.indent = indent 280 self.indent = indent
270 281
279 d = str.replace('\n',' ') 290 d = str.replace('\n',' ')
280 d = d.replace('\t',' ') 291 d = d.replace('\t',' ')
281 while d.find(' ') > -1: d = d.replace(' ',' ') 292 while d.find(' ') > -1: d = d.replace(' ',' ')
282 while d[0] in '"\'\t ': d = d[1:] 293 while d[0] in '"\'\t ': d = d[1:]
283 while d[-1] in '"\'\t ': d = d[:-1] 294 while d[-1] in '"\'\t ': d = d[:-1]
295 dbg("Scope(%s)::docstr = %s" % (self,d))
284 self.docstr = d 296 self.docstr = d
285 297
286 def local(self,loc): 298 def local(self,loc):
287 if not self._hasvaralready(loc): 299 self._checkexisting(loc)
288 self.locals.append(loc) 300 self.locals.append(loc)
289 301
290 def copy_decl(self,indent=0): 302 def copy_decl(self,indent=0):
291 """ Copy a scope's declaration only, at the specified indent level - not local variables """ 303 """ Copy a scope's declaration only, at the specified indent level - not local variables """
292 return Scope(self.name,indent) 304 return Scope(self.name,indent,self.docstr)
293 305
294 def _hasvaralready(self,test): 306 def _checkexisting(self,test):
295 "Convienance function... keep out duplicates" 307 "Convienance function... keep out duplicates"
296 if test.find('=') > -1: 308 if test.find('=') > -1:
297 var = test.split('=')[0].strip() 309 var = test.split('=')[0].strip()
298 for l in self.locals: 310 for l in self.locals:
299 if l.find('=') > -1 and var == l.split('=')[0].strip(): 311 if l.find('=') > -1 and var == l.split('=')[0].strip():
300 return True 312 self.locals.remove(l)
301 return False
302 313
303 def get_code(self): 314 def get_code(self):
304 # we need to start with this, to fix up broken completions 315 str = ""
305 # hopefully this name is unique enough... 316 if len(self.docstr) > 0: str += '"""'+self.docstr+'"""\n'
306 str = '"""'+self.docstr+'"""\n'
307 for l in self.locals: 317 for l in self.locals:
308 if l.startswith('import'): str += l+'\n' 318 if l.startswith('import'): str += l+'\n'
309 str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n' 319 str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n'
310 for sub in self.subscopes: 320 for sub in self.subscopes:
311 str += sub.get_code() 321 str += sub.get_code()
328 def childindent(self): 338 def childindent(self):
329 #print 'parse child indent: [%s]' % (self.indent+1) 339 #print 'parse child indent: [%s]' % (self.indent+1)
330 return ' '*(self.indent+1) 340 return ' '*(self.indent+1)
331 341
332 class Class(Scope): 342 class Class(Scope):
333 def __init__(self, name, supers, indent): 343 def __init__(self, name, supers, indent, docstr=''):
334 Scope.__init__(self,name,indent) 344 Scope.__init__(self,name,indent, docstr)
335 self.supers = supers 345 self.supers = supers
336 def copy_decl(self,indent=0): 346 def copy_decl(self,indent=0):
337 c = Class(self.name,self.supers,indent) 347 c = Class(self.name,self.supers,indent, self.docstr)
338 for s in self.subscopes: 348 for s in self.subscopes:
339 c.add(s.copy_decl(indent+1)) 349 c.add(s.copy_decl(indent+1))
340 return c 350 return c
341 def get_code(self): 351 def get_code(self):
342 str = '%sclass %s' % (self.currentindent(),self.name) 352 str = '%sclass %s' % (self.currentindent(),self.name)
349 str += '%spass\n' % self.childindent() 359 str += '%spass\n' % self.childindent()
350 return str 360 return str
351 361
352 362
353 class Function(Scope): 363 class Function(Scope):
354 def __init__(self, name, params, indent): 364 def __init__(self, name, params, indent, docstr=''):
355 Scope.__init__(self,name,indent) 365 Scope.__init__(self,name,indent, docstr)
356 self.params = params 366 self.params = params
357 def copy_decl(self,indent=0): 367 def copy_decl(self,indent=0):
358 return Function(self.name,self.params,indent) 368 return Function(self.name,self.params,indent, self.docstr)
359 def get_code(self): 369 def get_code(self):
360 str = "%sdef %s(%s):\n" % \ 370 str = "%sdef %s(%s):\n" % \
361 (self.currentindent(),self.name,','.join(self.params)) 371 (self.currentindent(),self.name,','.join(self.params))
362 if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n' 372 if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n'
363 str += "%spass\n" % self.childindent() 373 str += "%spass\n" % self.childindent()
369 self.scope = self.top 379 self.scope = self.top
370 380
371 def _parsedotname(self,pre=None): 381 def _parsedotname(self,pre=None):
372 #returns (dottedname, nexttoken) 382 #returns (dottedname, nexttoken)
373 name = [] 383 name = []
374 if pre == None: 384 if pre is None:
375 tokentype, token, indent = self.next() 385 tokentype, token, indent = self.next()
376 if tokentype != NAME and token != '*': 386 if tokentype != NAME and token != '*':
377 return ('', token) 387 return ('', token)
378 else: token = pre 388 else: token = pre
379 name.append(token) 389 name.append(token)
403 names = [] 413 names = []
404 level = 1 414 level = 1
405 while True: 415 while True:
406 tokentype, token, indent = self.next() 416 tokentype, token, indent = self.next()
407 if token in (')', ',') and level == 1: 417 if token in (')', ',') and level == 1:
408 names.append(name) 418 if '=' not in name: name = name.replace(' ', '')
419 names.append(name.strip())
409 name = '' 420 name = ''
410 if token == '(': 421 if token == '(':
411 level += 1 422 level += 1
423 name += "("
412 elif token == ')': 424 elif token == ')':
413 level -= 1 425 level -= 1
414 if level == 0: break 426 if level == 0: break
427 else: name += ")"
415 elif token == ',' and level == 1: 428 elif token == ',' and level == 1:
416 pass 429 pass
417 else: 430 else:
418 name += str(token) 431 name += "%s " % str(token)
419 return names 432 return names
420 433
421 def _parsefunction(self,indent): 434 def _parsefunction(self,indent):
422 self.scope=self.scope.pop(indent) 435 self.scope=self.scope.pop(indent)
423 tokentype, fname, ind = self.next() 436 tokentype, fname, ind = self.next()
493 if type(scp) == Function: 506 if type(scp) == Function:
494 slice = 0 507 slice = 0
495 #Handle 'self' params 508 #Handle 'self' params
496 if scp.parent != None and type(scp.parent) == Class: 509 if scp.parent != None and type(scp.parent) == Class:
497 slice = 1 510 slice = 1
498 p = scp.params[0]
499 i = p.find('=')
500 if i != -1: p = p[:i]
501 newscope.local('%s = %s' % (scp.params[0],scp.parent.name)) 511 newscope.local('%s = %s' % (scp.params[0],scp.parent.name))
502 for p in scp.params[slice:]: 512 for p in scp.params[slice:]:
503 i = p.find('=') 513 i = p.find('=')
514 if len(p) == 0: continue
515 pvar = ''
516 ptype = ''
504 if i == -1: 517 if i == -1:
505 newscope.local('%s = _PyCmplNoType()' % p) 518 pvar = p
519 ptype = '_PyCmplNoType()'
506 else: 520 else:
507 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))
508 531
509 for s in scp.subscopes: 532 for s in scp.subscopes:
510 ns = s.copy_decl(0) 533 ns = s.copy_decl(0)
511 newscope.add(ns) 534 newscope.add(ns)
512 for l in scp.locals: newscope.local(l) 535 for l in scp.locals: newscope.local(l)
530 553
531 if tokentype == DEDENT or token == "pass": 554 if tokentype == DEDENT or token == "pass":
532 self.scope = self.scope.pop(indent) 555 self.scope = self.scope.pop(indent)
533 elif token == 'def': 556 elif token == 'def':
534 func = self._parsefunction(indent) 557 func = self._parsefunction(indent)
535 if func == None: 558 if func is None:
536 print "function: syntax error..." 559 print "function: syntax error..."
537 continue 560 continue
561 dbg("new scope: function")
538 freshscope = True 562 freshscope = True
539 self.scope = self.scope.add(func) 563 self.scope = self.scope.add(func)
540 elif token == 'class': 564 elif token == 'class':
541 cls = self._parseclass(indent) 565 cls = self._parseclass(indent)
542 if cls == None: 566 if cls is None:
543 print "class: syntax error..." 567 print "class: syntax error..."
544 continue 568 continue
545 freshscope = True 569 freshscope = True
570 dbg("new scope: class")
546 self.scope = self.scope.add(cls) 571 self.scope = self.scope.add(cls)
547 572
548 elif token == 'import': 573 elif token == 'import':
549 imports = self._parseimportlist() 574 imports = self._parseimportlist()
550 for mod, alias in imports: 575 for mod, alias in imports:
567 if freshscope: self.scope.doc(token) 592 if freshscope: self.scope.doc(token)
568 elif tokentype == NAME: 593 elif tokentype == NAME:
569 name,token = self._parsedotname(token) 594 name,token = self._parsedotname(token)
570 if token == '=': 595 if token == '=':
571 stmt = self._parseassignment() 596 stmt = self._parseassignment()
597 dbg("parseassignment: %s = %s" % (name, stmt))
572 if stmt != None: 598 if stmt != None:
573 self.scope.local("%s = %s" % (name,stmt)) 599 self.scope.local("%s = %s" % (name,stmt))
574 freshscope = False 600 freshscope = False
575 except StopIteration: #thrown on EOF 601 except StopIteration: #thrown on EOF
576 pass 602 pass