vim-patch:9.1.1170: wildmenu highlighting in popup can be improved (#32728)

Problem:  wildmenu highlighting in popup can be improved
Solution: Check if the completion items contain submatches of the
          entered text (Girish Palya).

This update enables highlighting in the popup menu even when the matched
fragment or pattern appears within an item (string) rather than only at the
beginning. This is especially useful for custom completion, where menu items
may not always start with the typed pattern.

For specific use cases, refer to the two examples in
https://github.com/vim/vim/pull/16759

A sliding window approach is used with direct string comparison. Performance
is not a concern, as highlighting is applied only to displayed lines, even if
the menu list is arbitrarily long.

closes: vim/vim#16785

4ec46f3210

Co-authored-by: Girish Palya <girishji@gmail.com>
This commit is contained in:
zeertzjq
2025-03-05 06:51:36 +08:00
committed by GitHub
parent 97dc02687a
commit b0341136c1
3 changed files with 56 additions and 7 deletions

View File

@@ -430,12 +430,10 @@ static int *pum_compute_text_attrs(char *text, hlf_T hlf, int user_hlattr)
size_t leader_len = strlen(leader);
garray_T *ga = NULL;
bool matched_start = false;
int matched_len = -1;
if (in_fuzzy) {
ga = fuzzy_match_str_with_pos(text, leader);
} else {
matched_start = mb_strnicmp(text, leader, leader_len) == 0;
}
const char *ptr = text;
@@ -456,10 +454,16 @@ static int *pum_compute_text_attrs(char *text, hlf_T hlf, int user_hlattr)
break;
}
}
} else if (matched_start && ptr < text + leader_len) {
new_attr = win_hl_attr(curwin, is_select ? HLF_PMSI : HLF_PMNI);
new_attr = hl_combine_attr(win_hl_attr(curwin, HLF_PMNI), new_attr);
new_attr = hl_combine_attr(win_hl_attr(curwin, (int)hlf), new_attr);
} else {
if (matched_len < 0 && mb_strnicmp(ptr, leader, leader_len) == 0) {
matched_len = (int)leader_len;
}
if (matched_len > 0) {
new_attr = win_hl_attr(curwin, is_select ? HLF_PMSI : HLF_PMNI);
new_attr = hl_combine_attr(win_hl_attr(curwin, HLF_PMNI), new_attr);
new_attr = hl_combine_attr(win_hl_attr(curwin, (int)hlf), new_attr);
matched_len--;
}
}
new_attr = hl_combine_attr(win_hl_attr(curwin, HLF_PNI), new_attr);

View File

@@ -5145,6 +5145,29 @@ describe('builtin popupmenu', function()
]])
end)
-- oldtest: Test_wildmenu_pum_hl_nonfirst()
it('highlight matched text in the middle in cmdline pum', function()
exec([[
set wildoptions=pum wildchar=<tab> wildmode=noselect,full
hi PmenuMatchSel guifg=Blue guibg=Grey
hi PmenuMatch guifg=Blue guibg=Plum1
func T(a, c, p)
return ["oneA", "o neBneB", "aoneC"]
endfunc
command -nargs=1 -complete=customlist,T MyCmd
]])
feed(':MyCmd ne<tab>')
screen:expect([[
|
{1:~ }|*15
{1:~ }{n: o}{mn:ne}{n:A }{1: }|
{1:~ }{n: o }{mn:ne}{n:BneB }{1: }|
{1:~ }{n: ao}{mn:ne}{n:C }{1: }|
:MyCmd ne^ |
]])
end)
it(
'cascading highlights for matched text (PmenuMatch, PmenuMatchSel) in cmdline pum',
function()

View File

@@ -3025,6 +3025,28 @@ func Test_wildmenu_pum_rightleft()
call StopVimInTerminal(buf)
endfunc
" Test highlighting when pattern matches non-first character of item
func Test_wildmenu_pum_hl_nonfirst()
CheckScreendump
let lines =<< trim END
set wildoptions=pum wildchar=<tab> wildmode=noselect,full
hi PmenuMatchSel ctermfg=6 ctermbg=7
hi PmenuMatch ctermfg=4 ctermbg=225
func T(a, c, p)
return ["oneA", "o neBneB", "aoneC"]
endfunc
command -nargs=1 -complete=customlist,T MyCmd
END
call writefile(lines, 'Xwildmenu_pum_hl_nonf', 'D')
let buf = RunVimInTerminal('-S Xwildmenu_pum_hl_nonf', #{rows: 10, cols: 50})
call term_sendkeys(buf, ":MyCmd ne\<tab>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_hl_match_nonf', {})
call term_sendkeys(buf, "\<Esc>")
call StopVimInTerminal(buf)
endfunc
" Test highlighting matched text in cmdline completion popup menu.
func Test_wildmenu_pum_hl_match()
CheckScreendump