0
0
mirror of https://github.com/vim/vim.git synced 2025-10-16 07:24:23 -04:00

patch 9.1.1825: completion: flicker when LSP server is slow

Problem:  completion: flicker when LSP server is slow
Solution: reinsert leader text before invoking user function
          (Girish Palya)

Reference:
https://github.com/girishji/vimcomplete/issues/101#issuecomment-3343063245

In insert-mode completion, the leader text is temporarily removed while
searching for candidates. When the LSP server responds slowly, the
client may call `:sleep` to wait, which triggers `out_flush()`. This
causes the deleted text to disappear briefly before being redrawn,
resulting in visible flicker.

This commit reinserts the leader text before invoking the user function,
and removes it again afterward to eliminate flicker.

closes: #18468

Signed-off-by: Girish Palya <girishji@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Girish Palya
2025-10-04 10:55:40 +00:00
committed by Christian Brabandt
parent 420923c0c5
commit c51d1cc578
3 changed files with 27 additions and 17 deletions

View File

@@ -7690,17 +7690,26 @@ remove_old_matches(void)
static void static void
get_cpt_func_completion_matches(callback_T *cb UNUSED) get_cpt_func_completion_matches(callback_T *cb UNUSED)
{ {
int startcol = cpt_sources_array[cpt_sources_index].cs_startcol; cpt_source_T *cpt_src = &cpt_sources_array[cpt_sources_index];
int startcol = cpt_src->cs_startcol;
if (startcol == -2 || startcol == -3) if (startcol == -2 || startcol == -3)
return; return;
if (set_compl_globals(startcol, curwin->w_cursor.col, TRUE) == OK) if (set_compl_globals(startcol, curwin->w_cursor.col, TRUE) == OK)
{ {
// Insert the leader string (previously removed) before expansion.
// This prevents flicker when `func` (e.g. an LSP client) is slow and
// calls 'sleep', which triggers out_flush().
if (!cpt_src->cs_refresh_always)
ins_compl_insert_bytes(ins_compl_leader(), -1);
expand_by_function(0, cpt_compl_pattern.string, cb); expand_by_function(0, cpt_compl_pattern.string, cb);
cpt_sources_array[cpt_sources_index].cs_refresh_always = if (!cpt_src->cs_refresh_always)
compl_opt_refresh_always; ins_compl_delete();
cpt_src->cs_refresh_always = compl_opt_refresh_always;
compl_opt_refresh_always = FALSE; compl_opt_refresh_always = FALSE;
} }
} }

View File

@@ -586,15 +586,19 @@ func Test_completefunc_info()
set completefunc& set completefunc&
endfunc endfunc
func Test_cpt_func_cursorcol() " For ^N completion, `completefunc` receives the same leader string in both the
" 'info' and 'expansion' phases (the leader is not removed before expansion).
" This avoids flicker when `completefunc` (e.g. an LSP client) is slow and calls
" 'sleep', which triggers out_flush().
func Test_completefunc_leader()
func CptColTest(findstart, query) func CptColTest(findstart, query)
if a:findstart if a:findstart
call assert_equal(b:info_compl_line, getline(1)) call assert_equal(b:compl_line, getline(1))
call assert_equal(b:info_cursor_col, col('.')) call assert_equal(b:cursor_col, col('.'))
return col('.') return col('.')
endif endif
call assert_equal(b:expn_compl_line, getline(1)) call assert_equal(b:compl_line, getline(1))
call assert_equal(b:expn_cursor_col, col('.')) call assert_equal(b:cursor_col, col('.'))
return v:none return v:none
endfunc endfunc
@@ -602,17 +606,13 @@ func Test_cpt_func_cursorcol()
new new
" Replace mode " Replace mode
let b:info_compl_line = "foo barxyz" let b:compl_line = "foo barxyz"
let b:expn_compl_line = "foo barbaz" let b:cursor_col = 10
let b:info_cursor_col = 10
let b:expn_cursor_col = 5
call feedkeys("ifoo barbaz\<Esc>2hRxy\<C-N>", "tx") call feedkeys("ifoo barbaz\<Esc>2hRxy\<C-N>", "tx")
" Insert mode " Insert mode
let b:info_compl_line = "foo bar" let b:compl_line = "foo bar"
let b:expn_compl_line = "foo " let b:cursor_col = 8
let b:info_cursor_col = 8
let b:expn_cursor_col = 5
call feedkeys("Sfoo bar\<C-N>", "tx") call feedkeys("Sfoo bar\<C-N>", "tx")
set completeopt=longest set completeopt=longest
@@ -4128,7 +4128,6 @@ func Test_autocomplete_completeopt_preinsert()
endfunc endfunc
set omnifunc=Omni_test complete+=o set omnifunc=Omni_test complete+=o
set completeopt=preinsert autocomplete set completeopt=preinsert autocomplete
" set completeopt=preinsert,menuone autocomplete
func GetLine() func GetLine()
let g:line = getline('.') let g:line = getline('.')
let g:col = col('.') let g:col = col('.')

View File

@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1825,
/**/ /**/
1824, 1824,
/**/ /**/