# HG changeset patch # User vimboss # Date 1137191740 0 # Node ID 732c7ae5743ec2d22423a8bb631e2d3c5fb8e549 # Parent 81fe2ccc1207699c377b42f1d8ca426a70177afd updated for version 7.0180 diff --git a/runtime/autoload/pycomplete.vim b/runtime/autoload/pycomplete.vim new file mode 100644 --- /dev/null +++ b/runtime/autoload/pycomplete.vim @@ -0,0 +1,216 @@ +"pycomplete.vim - Omni Completion for python +" Maintainer: Aaron Griffin +" Version: 0.2 +" Last Updated: 5 January 2006 +" +" TODO +" * local variables *inside* class members + +if !has('python') + echo "Error: Required vim compiled with +python" + finish +endif + +function! pycomplete#Complete(findstart, base) + "findstart = 1 when we need to get the text length + if a:findstart + let line = getline('.') + let idx = col('.') + while idx > 0 + let idx -= 1 + let c = line[idx-1] + if c =~ '\w' + continue + elseif ! c =~ '\.' + idx = -1 + break + else + break + endif + endwhile + + return idx + "findstart = 0 when we need to return the list of completions + else + execute "python get_completions('" . a:base . "')" + return g:pycomplete_completions + endif +endfunction + +function! s:DefPython() +python << PYTHONEOF +import vim +import sys +import __builtin__ + +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 +def get_completions(base): + stmt = vim.eval('expand("")')+base + dbg("parsed statement => %s" % stmt) + eval_source_code() + try: + dbg("eval: %s" % stmt) + if len(stmt.split('.')) == 1: + all = globals().keys() + dir(__builtin__) + match = stmt + else: + rindex= stmt.rfind('.') + all = dir(eval(stmt[:rindex])) + match = stmt[rindex+1:] + + 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) + vim.command("let g:pycomplete_completions = %s" % completions) + except: + dbg("exception: %s" % sys.exc_info()[1]) + vim.command("let g:pycomplete_completions = []") + clean_up() + +#yes, this is a quasi-functional python lexer +def eval_source_code(): + import tokenize + import keyword + import StringIO + s = StringIO.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 + #junk + elif type == tokenize.INDENT or \ + type == tokenize.DEDENT or \ + type == tokenize.ERRORTOKEN or \ + type == tokenize.ENDMARKER or \ + type == tokenize.NEWLINE: + 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 from statement + elif str == 'from': + type, str, begin, end, line = g.next() + mod = str + + type, str, begin, end, line = g.next() + if str != "import": break + mem = '' + 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])) + #class declaration + elif str == 'class': + type, str, begin, end, line = g.next() + classname = str + dbg("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: + 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 + memberstr += str + dbg(" 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) + 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] + for s in stmts: + try: + dbg("evaluating: %s\n" % s) + exec(s) in globals() + except: + pass + except: + dbg("exception: %s" % sys.exc_info()[1]) + +def clean_up(): + for o in globals().keys(): + if o not in LOCALDEFS: + try: + exec('del %s' % o) in globals() + except: pass + +sys.path.extend(['.','..']) +PYTHONEOF +endfunction + +call s:DefPython() +" vim: set et ts=4: diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 7.0aa. Last change: 2006 Jan 09 +*eval.txt* For Vim version 7.0aa. Last change: 2006 Jan 13 VIM REFERENCE MANUAL by Bram Moolenaar @@ -3273,6 +3273,10 @@ maparg({name}[, {mode}]) *maparg()* translated like in the output of the ":map" command listing. The mappings local to the current buffer are checked first, then the global mappings. + This function can be used to map a key even when it's already + mapped, and have it do the original mapping too. Sketch: > + exe 'nnoremap ==' . maparg('', 'n') + mapcheck({name}[, {mode}]) *mapcheck()* Check if there is a mapping that matches with {name} in mode diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1,4 +1,4 @@ -*map.txt* For Vim version 7.0aa. Last change: 2006 Jan 09 +*map.txt* For Vim version 7.0aa. Last change: 2006 Jan 13 VIM REFERENCE MANUAL by Bram Moolenaar @@ -191,6 +191,8 @@ already exists which is equal. Example of what will fail: > :map ,w /[#&!] :map ,w /[.,;] +If you want to map a key and then have it do what it was originally mapped to, +have a look at |maparg()|. "", "", "