diff options
author | Bram Moolenaar <Bram@vim.org> | 2006-01-25 22:10:52 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2006-01-25 22:10:52 +0000 |
commit | d12f5c17be85407b7beb8622828ba6bc5903369e (patch) | |
tree | cb86c7b532ba41cd2f914bd2e2636acc09c99fe1 /runtime/autoload | |
parent | 28c258fd24342fe52e85059d68ce69cf9ef5f8cd (diff) | |
download | vim-git-d12f5c17be85407b7beb8622828ba6bc5903369e.tar.gz |
updated for version 7.0187v7.0187
Diffstat (limited to 'runtime/autoload')
-rw-r--r-- | runtime/autoload/pycomplete.vim | 329 | ||||
-rw-r--r-- | runtime/autoload/xmlcomplete.vim | 61 |
2 files changed, 282 insertions, 108 deletions
diff --git a/runtime/autoload/pycomplete.vim b/runtime/autoload/pycomplete.vim index 8cd5a5f6d..56a6b4e26 100644 --- a/runtime/autoload/pycomplete.vim +++ b/runtime/autoload/pycomplete.vim @@ -1,10 +1,20 @@ "pycomplete.vim - Omni Completion for python " Maintainer: Aaron Griffin -" Version: 0.2 -" Last Updated: 5 January 2006 +" Version: 0.3 +" Last Updated: 23 January 2006 +" +" v0.3 Changes: +" added top level def parsing +" for safety, call returns are not evaluated +" handful of parsing changes +" trailing ( and . characters +" argument completion on open parens +" stop parsing at current line - ++performance, local var resolution " " TODO -" * local variables *inside* class members +" RExec subclass +" Code cleanup + make class +" use internal dict, not globals() if !has('python') echo "Error: Required vim compiled with +python" @@ -20,10 +30,10 @@ function! pycomplete#Complete(findstart, base) let idx -= 1 let c = line[idx-1] if c =~ '\w' - continue - elseif ! c =~ '\.' + continue + elseif ! c =~ '\.' idx = -1 - break + break else break endif @@ -39,79 +49,222 @@ endfunction function! s:DefPython() python << PYTHONEOF -import vim -import sys +import vim, sys, types import __builtin__ +import tokenize, keyword, cStringIO LOCALDEFS = \ ['LOCALDEFS', 'clean_up','eval_source_code', \ 'get_completions', '__builtin__', '__builtins__', \ - 'dbg', '__name__', 'vim', 'sys'] -#comment/uncomment one line at a time to enable/disable debugging -def dbg(msg): - pass -# print(msg) - -#it seems that by this point, vim has already stripped the base -# matched in the findstart=1 section, so we will create the -# statement from scratch + 'dbg', '__name__', 'vim', 'sys', 'parse_to_end', \ + 'parse_statement', 'tokenize', 'keyword', 'cStringIO', \ + 'debug_level', 'safe_eval', '_ctor', 'get_arguments', \ + 'strip_calls', 'types', 'parse_block'] + +def dbg(level,msg): + debug_level = 1 + try: + debug_level = vim.eval("g:pycomplete_debug_level") + except: + pass + if level <= debug_level: print(msg) + +def strip_calls(stmt): + parsed='' + level = 0 + for c in stmt: + if c in ['[','(']: + level += 1 + elif c in [')',']']: + level -= 1 + elif level == 0: + parsed += c + ##dbg(10,"stripped: %s" % parsed) + return parsed + def get_completions(base): - stmt = vim.eval('expand("<cWORD>")')+base - dbg("parsed statement => %s" % stmt) + stmt = vim.eval('expand("<cWORD>")') + #dbg(1,"statement: %s - %s" % (stmt, base)) + stmt = stmt+base eval_source_code() + try: - dbg("eval: %s" % stmt) - if len(stmt.split('.')) == 1: - all = globals().keys() + dir(__builtin__) + ridx = stmt.rfind('.') + if stmt[-1] == '(': + match = "" + stmt = strip_calls(stmt[:len(stmt)-1]) + all = get_arguments(eval(stmt)) + elif ridx == -1: match = stmt + all = globals() + __builtin__.__dict__ else: - rindex= stmt.rfind('.') - all = dir(eval(stmt[:rindex])) - match = stmt[rindex+1:] + match = stmt[ridx+1:] + stmt = strip_calls(stmt[:ridx]) + all = eval(stmt).__dict__ + #dbg(15,"completions for: %s, match=%s" % (stmt,match)) completions = [] - dbg("match == %s" % match) - for m in all: - #TODO: remove private (_foo) functions? - if m.find('__') != 0 and \ - m.find(match) == 0 and \ - m not in LOCALDEFS: - dbg("matched... %s, %s" % (m, m.find(match))) - completions.append(m) - dbg("all completions: %s" % completions) + if type(all) == types.DictType: + for m in all: + if m.find('_') != 0 and m.find(match) == 0 and \ + m not in LOCALDEFS: + #dbg(25,"matched... %s, %s" % (m, m.find(match))) + typestr = str(all[m]) + if "function" in typestr: m += '(' + elif "method" in typestr: m += '(' + elif "module" in typestr: m += '.' + elif "class" in typestr: m += '(' + completions.append(m) + completions.sort() + else: + completions.append(all) + #dbg(10,"all completions: %s" % completions) vim.command("let g:pycomplete_completions = %s" % completions) except: - dbg("exception: %s" % sys.exc_info()[1]) vim.command("let g:pycomplete_completions = []") + #dbg(1,"exception: %s" % sys.exc_info()[1]) clean_up() -#yes, this is a quasi-functional python lexer +def get_arguments(func_obj): + def _ctor(obj): + try: + return class_ob.__init__.im_func + except AttributeError: + for base in class_ob.__bases__: + rc = _find_constructor(base) + if rc is not None: return rc + return None + + arg_offset = 1 + if type(func_obj) == types.ClassType: func_obj = _ctor(func_obj) + elif type(func_obj) == types.MethodType: func_obj = func_obj.im_func + else: arg_offset = 0 + + #dbg(20,"%s, offset=%s" % (str(func_obj), arg_offset)) + + arg_text = '' + if type(func_obj) in [types.FunctionType, types.LambdaType]: + try: + cd = func_obj.func_code + real_args = cd.co_varnames[arg_offset:cd.co_argcount] + defaults = func_obj.func_defaults or [] + defaults = list(map(lambda name: "=%s" % name, defaults)) + defaults = [""] * (len(real_args)-len(defaults)) + defaults + items = map(lambda a,d: a+d, real_args, defaults) + if func_obj.func_code.co_flags & 0x4: + items.append("...") + if func_obj.func_code.co_flags & 0x8: + items.append("***") + arg_text = ", ".join(items) + ')' + + except: + #dbg(1,"exception: %s" % sys.exc_info()[1]) + pass + if len(arg_text) == 0: + # The doc string sometimes contains the function signature + # this works for alot of C modules that are part of the + # standard library + doc = getattr(func_obj, '__doc__', '') + if doc: + doc = doc.lstrip() + pos = doc.find('\n') + if pos > 0: + sigline = doc[:pos] + lidx = sigline.find('(') + ridx = sigline.find(')') + retidx = sigline.find('->') + ret = sigline[retidx+2:].strip() + if lidx > 0 and ridx > 0: + arg_text = sigline[lidx+1:ridx] + ')' + if len(ret) > 0: arg_text += ' #returns %s' % ret + #dbg(15,"argument completion: %s" % arg_text) + return arg_text + +def parse_to_end(gen): + stmt='' + level = 0 + for type, str, begin, end, line in gen: + if line == vim.eval('getline(\'.\')'): break + elif str == '\\': continue + elif str == ';': + break + elif type == tokenize.NEWLINE and level == 0: + break + elif str in ['[','(']: + level += 1 + elif str in [')',']']: + level -= 1 + elif level == 0: + stmt += str + #dbg(10,"current statement: %s" % stmt) + return stmt + +def parse_block(gen): + lines = [] + level = 0 + for type, str, begin, end, line in gen: + if line.replace('\n','') == vim.eval('getline(\'.\')'): break + elif type == tokenize.INDENT: + level += 1 + elif type == tokenize.DEDENT: + level -= 1 + if level == 0: break; + else: + stmt = parse_statement(gen,str) + if len(stmt) > 0: lines.append(stmt) + return lines + +def parse_statement(gen,curstr=''): + var = curstr + type, str, begin, end, line = gen.next() + if str == '=': + type, str, begin, end, line = gen.next() + if type == tokenize.NEWLINE: + return '' + elif type == tokenize.STRING or str == 'str': + return '%s = str' % var + elif str == '[' or str == 'list': + return '%s= list' % var + elif str == '{' or str == 'dict': + return '%s = dict' % var + elif type == tokenize.NUMBER: + return '%s = 0' % var + elif str == 'Set': + return '%s = Set' % var + elif str == 'open' or str == 'file': + return '%s = file' % var + else: + inst = str + parse_to_end(gen) + if len(inst) > 0: + #dbg(5,"found [%s = %s]" % (var, inst)) + return '%s = %s' % (var, inst) + return '' + def eval_source_code(): - import tokenize - import keyword - import StringIO - s = StringIO.StringIO('\n'.join(vim.current.buffer[:]) + '\n') + LINE=vim.eval('getline(\'.\')') + s = cStringIO.StringIO('\n'.join(vim.current.buffer[:]) + '\n') g = tokenize.generate_tokens(s.readline) stmts = [] lineNo = 0 try: for type, str, begin, end, line in g: - if begin[0] == lineNo: - continue + if line.replace('\n','') == vim.eval('getline(\'.\')'): break + elif begin[0] == lineNo: continue #junk elif type == tokenize.INDENT or \ type == tokenize.DEDENT or \ type == tokenize.ERRORTOKEN or \ type == tokenize.ENDMARKER or \ - type == tokenize.NEWLINE: + type == tokenize.NEWLINE or \ + type == tokenize.COMMENT: continue #import statement elif str == 'import': - for type, str, begin, end, line in g: - if str == ';' or type == tokenize.NEWLINE: break - dbg("found [import %s]" % str) - stmts.append("import %s" % str) + import_stmt=parse_to_end(g) + if len(import_stmt) > 0: + #dbg(5,"found [import %s]" % import_stmt) + stmts.append("import %s" % import_stmt) #import from statement elif str == 'from': type, str, begin, end, line = g.next() @@ -119,87 +272,68 @@ def eval_source_code(): type, str, begin, end, line = g.next() if str != "import": break - mem = '' + from_stmt=parse_to_end(g) + if len(from_stmt) > 0: + #dbg(5,"found [from %s import %s]" % (mod, from_stmt)) + stmts.append("from %s import %s" % (mod, from_stmt)) + #def statement + elif str == 'def': + funcstr = '' for type, str, begin, end, line in g: - if str == ';' or type == tokenize.NEWLINE: break - mem += (str + ',') - if len(mem) > 0: - dbg("found [from %s import %s]" % (mod, mem[:-1])) - stmts.append("from %s import %s" % (mod, mem[:-1])) + if line.replace('\n','') == vim.eval('getline(\'.\')'): break + elif str == ':': + stmts += parse_block(g) + break + funcstr += str + if len(funcstr) > 0: + #dbg(5,"found [def %s]" % funcstr) + stmts.append("def %s:\n pass" % funcstr) #class declaration elif str == 'class': type, str, begin, end, line = g.next() classname = str - dbg("found [class %s]" % classname) + #dbg(5,"found [class %s]" % classname) level = 0 members = [] - #we don't care about the meat of the members, - # only the signatures, so we'll replace the bodies - # with 'pass' for evaluation for type, str, begin, end, line in g: - if type == tokenize.INDENT: + if line.replace('\n','') == vim.eval('getline(\'.\')'): break + elif type == tokenize.INDENT: level += 1 elif type == tokenize.DEDENT: level -= 1 if level == 0: break; elif str == 'def': - #TODO: if name begins with '_', keep private memberstr = '' for type, str, begin, end, line in g: - if str == ':': break + if line.replace('\n','') == vim.eval('getline(\'.\')'): break + elif str == ':': + stmts += parse_block(g) + break memberstr += str - dbg(" member [%s]" % memberstr) + #dbg(5," member [%s]" % memberstr) members.append(memberstr) - #TODO parse self.blah = something lines - #elif str == "self" && next && str == "." ...blah... classstr = 'class %s:' % classname for m in members: classstr += ("\n def %s:\n pass" % m) stmts.append("%s\n" % classstr) elif keyword.iskeyword(str) or str in globals(): - dbg("keyword = %s" % str) + #dbg(5,"keyword = %s" % str) lineNo = begin[0] else: - if line.find("=") == -1: continue - var = str - type, str, begin, end, line = g.next() - dbg('next = %s' % str) - if str != '=': continue - - type, str, begin, end, line = g.next() - if type == tokenize.NEWLINE: - continue - elif type == tokenize.STRING or str == 'str': - stmts.append('%s = str' % var) - elif str == '[' or str == 'list': - stmts.append('%s= list' % var) - elif str == '{' or str == 'dict': - stmts.append('%s = dict' % var) - elif type == tokenize.NUMBER: - continue - elif str == 'Set': - stmts.append('%s = Set' % var) - elif str == 'open' or str == 'file': - stmts.append('%s = file' % var) - else: - inst = str - for type, str, begin, end, line in g: - if type == tokenize.NEWLINE: - break - inst += str - if len(inst) > 0: - dbg("found [%s = %s]" % (var, inst)) - stmts.append('%s = %s' % (var, inst)) - lineNo = begin[0] + assign = parse_statement(g,str) + if len(assign) > 0: stmts.append(assign) + for s in stmts: try: - dbg("evaluating: %s\n" % s) + #dbg(15,"evaluating: %s\n" % s) exec(s) in globals() except: + #dbg(1,"exception: %s" % sys.exc_info()[1]) pass except: - dbg("exception: %s" % sys.exc_info()[1]) + #dbg(1,"exception: %s" % sys.exc_info()[1]) + pass def clean_up(): for o in globals().keys(): @@ -212,5 +346,6 @@ sys.path.extend(['.','..']) PYTHONEOF endfunction +let g:pycomplete_debug_level = 0 call s:DefPython() " vim: set et ts=4: diff --git a/runtime/autoload/xmlcomplete.vim b/runtime/autoload/xmlcomplete.vim index 2d09eff09..fc4ad7844 100644 --- a/runtime/autoload/xmlcomplete.vim +++ b/runtime/autoload/xmlcomplete.vim @@ -1,7 +1,7 @@ " Vim completion script -" Language: XHTML 1.0 Strict +" Language: XML " Maintainer: Mikolaj Machowski ( mikmach AT wp DOT pl ) -" Last Change: 2005 Nov 22 +" Last Change: 2006 Jan 24 " This function will create Dictionary with users namespace strings and values " canonical (system) names of data files. Names should be lowercase, @@ -54,6 +54,7 @@ endfunction function! xmlcomplete#CompleteTags(findstart, base) if a:findstart " locate the start of the word + let curline = line('.') let line = getline('.') let start = col('.') - 1 let compl_begin = col('.') - 2 @@ -69,11 +70,32 @@ function! xmlcomplete#CompleteTags(findstart, base) endif let b:compl_context = getline('.')[0:(compl_begin)] - let b:compl_context = matchstr(b:compl_context, '.*<\zs.*') + if b:compl_context !~ '<[^>]*$' + " Look like we may have broken tag. Check previous lines. Up to + " 10? + let i = 1 + while 1 + let context_line = getline(curline-i) + if context_line =~ '<[^>]*$' + " Yep, this is this line + let context_lines = getline(curline-i, curline) + let b:compl_context = join(context_lines, ' ') + break + elseif context_line =~ '>[^<]*$' + " Normal tag line, no need for completion at all + let b:compl_context = '' + break + endif + let i += 1 + endwhile + " Make sure we don't have counter + unlet! i + endif + let b:compl_context = matchstr(b:compl_context, '.*\zs<.*') " Make sure we will have only current namespace unlet! b:xml_namespace - let b:xml_namespace = matchstr(b:compl_context, '^\k*\ze:') + let b:xml_namespace = matchstr(b:compl_context, '^<\zs\k*\ze:') if b:xml_namespace == '' let b:xml_namespace = 'DEFAULT' endif @@ -89,7 +111,10 @@ function! xmlcomplete#CompleteTags(findstart, base) let res = [] let res2 = [] " a:base is very short - we need context - let context = b:compl_context + if len(b:compl_context) == 0 && !exists("b:entitiescompl") + return [] + endif + let context = matchstr(b:compl_context, '^<\zs.*') unlet! b:compl_context " Make entities completion @@ -111,13 +136,24 @@ function! xmlcomplete#CompleteTags(findstart, base) let values = intent + values endif - for m in values - if m =~ '^'.a:base - call add(res, m.';') - endif - endfor + if len(a:base) == 1 + for m in values + if m =~ '^'.a:base + call add(res, m.';') + endif + endfor + return res + else + for m in values + if m =~? '^'.a:base + call add(res, m.';') + elseif m =~? a:base + call add(res2, m.';') + endif + endfor - return res + return res + res2 + endif endif if context =~ '>' @@ -265,6 +301,9 @@ function! xmlcomplete#CompleteTags(findstart, base) " Deal with tag completion. let opentag = xmlcomplete#GetLastOpenTag("b:unaryTagsStack") let opentag = substitute(opentag, '^\k*:', '', '') + if opentag == '' + return [] + endif let tags = g:xmldata{'_'.g:xmldata_connection[b:xml_namespace]}[opentag][0] let context = substitute(context, '^\k*:', '', '') |