lifepillar/vim-mucomplete

Feature request: regex based scoped completions chains

vigoux opened this issue · 4 comments

Hi,
Firt of all, I just discovered mucomplete, and started to use it, and I am loving every single part of it so far, so thank you very much for this awesome plugin !

During my configuration of the plugin, I discovered your scoped chains feature (which is one of the neattest features).

The only thing I want to ask is it is possible to have a kind of regex based scoped completion chain ?

Here is an example of what I mean :

" Without regex
let g:mucomplete#chains = {
			\ 'default': ['tags', 'nsnp'],
			\ 'rust' : {
			\		"default" : ['omni', 'nsnp'],
			\		"rustString" : [],
			\		"rustCommentLine" : [],
			\		"rustCommentBlock" : [],
			\		"rustCommentLineDoc" : [],
			\		"rustCommentBlockDoc" : []
			\		},
			\ 'c' : {
			\		"cComment" : [],
			\		"cString" : []
			\		}
			\ }

" With regex
let g:mucomplete#chains = {
			\ 'default': ['tags', 'nsnp'],
			\ 'rust' : {
			\		"default" : ['omni', 'nsnp'],
			\		"rustString" : [],
			\		"rustComment.*" : [],
			\		},
			\ 'c' : {
			\		"cComment" : [],
			\		"cString" : []
			\		}
			\ }

It might be really nicer to use this way, and if there is not to many performance problems with this, a real game changer !

After some tests, I came up with this, which provides the desired functionality, I did not faced any performance issues btw.

The great thing is that, with chains getting smaller, the loop is not that bad, I will try to find a better way though. I am unable to run the profiling suite though, as I am using neovim instead of vim, and term_* functions don't exist.

Hope this helps.

diff --git a/autoload/mucomplete.vim b/autoload/mucomplete.vim
index 2c6e6fd..04c50aa 100644
--- a/autoload/mucomplete.vim
+++ b/autoload/mucomplete.vim
@@ -1,6 +1,7 @@
 " Chained completion that works as I want!
 " Maintainer: Lifepillar <lifepillar@lifepillar.me>
 " License: This file is placed in the public domain
+" vim: et ts=2 sts=2 sw=2

 let s:save_cpo = &cpo
 set cpo&vim
@@ -314,11 +315,20 @@ endf
 " If the argument is a completion chain (type() returns v:t_list), return it;
 " otherwise, get the completion chain for the current syntax item.
 fun! s:scope_chain(c)
-  return type(a:c) == 3
-        \ ? a:c
-        \ : get(a:c, synIDattr(synID('.', col('.') - 1, 0), 'name'),
-        \       get(a:c, 'default', g:mucomplete#chains['default']))
-endf
+  if type(a:c) ==  v:t_list
+    return a:c
+  else
+    let l:current_syntax = synIDattr(synID('.', col('.') - 1, 0), 'name')
+
+    for l:item in items(a:c)
+      if l:current_syntax =~? l:item[0]
+        return l:item[1]
+      endif
+    endfor
+
+    return get(a:c, 'default', g:mucomplete#chains['default'])
+  endif
+endfun

 " Precondition: pumvisible() is false.
 fun! mucomplete#init(dir, tab_completion) " Initialize/reset internal state

After some profiling, it seems that the solution with a for loop is the best I can get.

Furthermore, with the original implementation (without regexes), running the modified function took 1,75 microsec (on average), and with this implemetentation, it now takes 2.5microsec

Thanks for the code and the benchmarking. I'll take a look!

I edited the code above, because the comparison inside the loop was false.