|
| 1 | +vim9script |
| 2 | + |
| 3 | +# Vim completion script |
| 4 | +# Language: Vimscript |
| 5 | +# Maintainer: Maxim Kim <habamax@gmail.com> |
| 6 | +# Last Change: 2025-07-28 |
| 7 | +# |
| 8 | +# Usage: |
| 9 | +# setlocal omnifunc=vimcomplete#Complete |
| 10 | +# |
| 11 | +# Simple complete function for the Vimscript |
| 12 | + |
| 13 | +var trigger: string = "" |
| 14 | +var prefix: string = "" |
| 15 | + |
| 16 | + |
| 17 | +def GetTrigger(line: string): list<any> |
| 18 | + var result = "" |
| 19 | + var result_len = 0 |
| 20 | + |
| 21 | + if line =~ '->\k*$' |
| 22 | + result = 'function' |
| 23 | + elseif line =~ '\v%(^|\s+)\&\k*$' |
| 24 | + result = 'option' |
| 25 | + elseif line =~ '[\[(]\s*$' |
| 26 | + result = 'expression' |
| 27 | + elseif line =~ '[lvgsb]:\k*$' |
| 28 | + result = 'var' |
| 29 | + result_len = 2 |
| 30 | + else |
| 31 | + result = getcompletiontype(line) ?? 'cmdline' |
| 32 | + endif |
| 33 | + return [result, result_len] |
| 34 | +enddef |
| 35 | + |
| 36 | +export def Complete(findstart: number, base: string): any |
| 37 | + if findstart > 0 |
| 38 | + var line = getline('.')->strpart(0, col('.') - 1) |
| 39 | + var keyword = line->matchstr('\k\+$') |
| 40 | + var stx = synstack(line('.'), col('.') - 1)->map('synIDattr(v:val, "name")')->join() |
| 41 | + if stx =~? 'Comment' || (stx =~ 'String' && stx !~ 'vimStringInterpolationExpr') |
| 42 | + return -2 |
| 43 | + endif |
| 44 | + var trigger_len: number = 0 |
| 45 | + [trigger, trigger_len] = GetTrigger(line) |
| 46 | + if keyword->empty() && trigger->empty() |
| 47 | + return -2 |
| 48 | + endif |
| 49 | + prefix = line |
| 50 | + return line->len() - keyword->len() - trigger_len |
| 51 | + endif |
| 52 | + |
| 53 | + var items = [] |
| 54 | + if trigger == 'function' |
| 55 | + items = getcompletion(base, 'function') |
| 56 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Function', dup: 0})) |
| 57 | + elseif trigger == 'option' |
| 58 | + items = getcompletion(base, 'option') |
| 59 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Option', dup: 0})) |
| 60 | + elseif trigger == 'var' |
| 61 | + items = getcompletion(base, 'var') |
| 62 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Variable', dup: 0})) |
| 63 | + elseif trigger == 'expression' |
| 64 | + items = getcompletion(base, 'expression') |
| 65 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Expression', dup: 0})) |
| 66 | + elseif trigger == 'command' |
| 67 | + var commands = getcompletion(base, 'command') |
| 68 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Command', dup: 0})) |
| 69 | + var functions = getcompletion(base, 'function') |
| 70 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Function', dup: 0})) |
| 71 | + items = commands + functions |
| 72 | + else |
| 73 | + items = getcompletion(prefix, 'cmdline') |
| 74 | + ->mapnew((_, v) => ({word: v->matchstr('\k\+'), kind: 'v', dup: 0})) |
| 75 | + |
| 76 | + if empty(items) && !empty(base) |
| 77 | + items = getcompletion(base, 'expression') |
| 78 | + ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Expression', dup: 0})) |
| 79 | + endif |
| 80 | + endif |
| 81 | + |
| 82 | + return items->empty() ? v:none : items |
| 83 | +enddef |
0 commit comments