]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
runtime(vim): add simple vimscript complete function
authorMaxim Kim <habamax@gmail.com>
Fri, 8 Aug 2025 11:42:49 +0000 (13:42 +0200)
committerChristian Brabandt <cb@256bit.org>
Fri, 8 Aug 2025 11:42:49 +0000 (13:42 +0200)
closes: #17871

Signed-off-by: Maxim Kim <habamax@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
runtime/autoload/vimcomplete.vim [new file with mode: 0644]
runtime/ftplugin/vim.vim

diff --git a/runtime/autoload/vimcomplete.vim b/runtime/autoload/vimcomplete.vim
new file mode 100644 (file)
index 0000000..81fdf0f
--- /dev/null
@@ -0,0 +1,83 @@
+vim9script
+
+# Vim completion script
+# Language:    Vimscript
+# Maintainer:  Maxim Kim <habamax@gmail.com>
+# Last Change: 2025-07-28
+#
+# Usage:
+# setlocal omnifunc=vimcomplete#Complete
+#
+# Simple complete function for the Vimscript
+
+var trigger: string = ""
+var prefix: string = ""
+
+
+def GetTrigger(line: string): list<any>
+    var result = ""
+    var result_len = 0
+
+    if line =~ '->\k*$'
+        result = 'function'
+    elseif line =~ '\v%(^|\s+)\&\k*$'
+        result = 'option'
+    elseif line =~ '[\[(]\s*$'
+        result = 'expression'
+    elseif line =~ '[lvgsb]:\k*$'
+        result = 'var'
+        result_len = 2
+    else
+        result = getcompletiontype(line) ?? 'cmdline'
+    endif
+    return [result, result_len]
+enddef
+
+export def Complete(findstart: number, base: string): any
+    if findstart > 0
+        var line = getline('.')->strpart(0, col('.') - 1)
+        var keyword = line->matchstr('\k\+$')
+        var stx = synstack(line('.'), col('.') - 1)->map('synIDattr(v:val, "name")')->join()
+        if stx =~? 'Comment' || (stx =~ 'String' && stx !~ 'vimStringInterpolationExpr')
+            return -2
+        endif
+        var trigger_len: number = 0
+        [trigger, trigger_len] = GetTrigger(line)
+        if keyword->empty() && trigger->empty()
+            return -2
+        endif
+        prefix = line
+        return line->len() - keyword->len() - trigger_len
+    endif
+
+    var items = []
+    if trigger == 'function'
+        items = getcompletion(base, 'function')
+            ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Function', dup: 0}))
+    elseif trigger == 'option'
+        items = getcompletion(base, 'option')
+            ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Option', dup: 0}))
+    elseif trigger == 'var'
+        items = getcompletion(base, 'var')
+            ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Variable', dup: 0}))
+    elseif trigger == 'expression'
+        items = getcompletion(base, 'expression')
+            ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Expression', dup: 0}))
+    elseif trigger == 'command'
+        var commands = getcompletion(base, 'command')
+            ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Command', dup: 0}))
+        var functions = getcompletion(base, 'function')
+            ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Function', dup: 0}))
+        items = commands + functions
+    else
+        items = getcompletion(prefix, 'cmdline')
+            ->mapnew((_, v) => ({word: v->matchstr('\k\+'), kind: 'v', dup: 0}))
+
+        if empty(items) && !empty(base)
+            items = getcompletion(base, 'expression')
+                ->mapnew((_, v) => ({word: v, kind: 'v', menu: 'Expression', dup: 0}))
+        endif
+    endif
+
+    return items->empty() ? v:none : items
+enddef
index 28ca9b3265abf440009da6c949909b5185aaab68..5ee3812b4c087c87125369d9e2cf6e571950f6b0 100644 (file)
@@ -8,6 +8,7 @@
 "                    @lacygoill
 " Last Change:       2025 Mar 05
 " 2025 Aug 06 by Vim Project (add gf maps #17881)
+" 2025 Aug 08 by Vim Project (add vimscript complete function #17871)
 
 " Only do this when not done yet for this buffer
 if exists("b:did_ftplugin")
@@ -22,7 +23,7 @@ set cpo&vim
 
 if !exists('*VimFtpluginUndo')
   func VimFtpluginUndo()
-    setl fo< isk< com< tw< commentstring< include< define< keywordprg<
+    setl fo< isk< com< tw< commentstring< include< define< keywordprg< omnifunc<
     sil! delc -buffer VimKeywordPrg
     if exists('b:did_add_maps')
       silent! nunmap <buffer> [[
@@ -121,6 +122,11 @@ setlocal include=\\v^\\s*import\\s*(autoload)?
 " set 'define' to recognize export commands
 setlocal define=\\v^\\s*export\\s*(def\|const\|var\|final)
 
+if has("vim9script")
+  " set omnifunc completion
+  setlocal omnifunc=vimcomplete#Complete
+endif
+
 " Format comments to be up to 78 characters long
 if &tw == 0
   setlocal tw=78