Vim Tips Wiki
Tip 968 Printable Monobook Previous Next

created 2005 · complexity intermediate · author Marian Csontos · version 7.0

You can use code completion with CTRL-X CTRL-U. See :help 'completefunc'.

With this small script, you can complete keywords using some kind wildcards. By default '\k\zs' reg-exp is used as wildcard. Useful if you are using identifiers with mixed case, so aCN expands to anyCrazyName or anotherCodeName, but not AnotherCodeName neither BadCodeName.

" settings:
" g:mkw_any - default regular expression used as wildcard
" - possible settings:
" - ''
" every nothing around character in pattern is used as wildcard, so for
" KEY is '\<\k*K\k*E\k*Y\k*\>' used for matching keywords
" - '\k\zs'
" every nothing around characters but the first is used as wildcard, so
" for KEY is '\<K\k*E\k*Y\k*\>' used for matching keywords
" - or any other reg.expression (e.g. '\.\.', '', '_', '\', '::', '`')
" be careful it doesn't mix with language constructs used in your
" sources (as '\.' in C is used for structure members)
" if zero-length match is used:
" - prepend \k\@<= if the first char in pattern must be the first in match
" - postpend \k\@= if the last char in pattern must be the last in match
" b:mkw_any - regular expression to be used for current buffer as wildcard
" other:
" g:mkw_devel - if exists script is reloaded every time it is sourced
if v:version < 700
  echohl ERROR "Smart completion will work only in vim version 7+"
if !exists("g:mkw_any")
  let g:mkw_any = '\k\zs'
if exists("g:mkw_devel") || !exists("g:mkw_loaded")
  " find start of keyword-match (return) and create regexp for finding
  " matching keyword (s:re)
  " a:line - string to search in, search starts at end of string
  " a:anyre - reg.exp looked for to be replaced by '\k\*'
  fun! MKwFindStart(line,anyre)
    " this can not be used because a:anyre could be 0-length:
    "return match(a:line,'\%(\k*'.a:anyre.'\)*\k*$')
    let line = a:line
    " trims trailing keyword-characters
    let answ = match(line,'\k*$')
    if answ < 0
      let answ = strlen(line)
      let line = strpart(line,0,answ)
    " trim trailing occurrences of keyword-characters followed by anyre
    while answ > 0
      let answ = match(line,'\k*'.a:anyre.'$')
      if answ < 0 || answ == strlen(line) | break | endif
      let line = strpart(line,0,answ)
    " set answ and s:re:
    let answ = strlen(line)
    let line = strpart(a:line,answ)
    let s:re = '\<'.substitute(line,a:anyre,'\\k*',"g").'\>'
    "echo line ">>>" s:re
    return answ

  fun! MKwCompleteId(findstart, base)
    if a:findstart
      " locate start column of word
      if !exists("b:mkw_any")
        let mkw_any = g:mkw_any
        let mkw_any = b:mkw_any
      return MKwFindStart(strpart(getline("."),0,(col('.') - 1)),mkw_any)
      " remember cursor position
      let line = line('.')
      let col = col('.')
      " create word list (it serves as reg.exp too, to exclude words found
      " already)
      let res = ""
      while search('\%(\<\%('.res.'\)\>\)\@!'.s:re,'w') > 0
        let tmp = expand("<cword>")
        let res .= (res == "" ? "" : '\|').expand("<cword>")
      " restore cursor position
      call cursor(line,col)
      "echo s:re ":" res
      return split(res,'\\|')
 let g:mkw_loaded = 1
setlocal completefunc=MKwCompleteId