patch 9.1.0476: Cannot see matched text in popup menu

Problem:  Cannot see matched text in popup menu
Solution: Introduce 2 new highlighting groups: PmenuMatch and
          PmenuMatchSel (glepnir)

ping @habamax, @neutaaaaan @romainl because vim/colorschemes may need
some updates, @lifepillar for updating vim-colortemplate

closes: #14694

Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/highlight.c b/src/highlight.c
index 9aa149f..a71a100 100644
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -258,6 +258,8 @@
     "default link CurSearch Search",
     "default link PmenuKind Pmenu",
     "default link PmenuKindSel PmenuSel",
+    "default link PmenuMatch Pmenu",
+    "default link PmenuMatchSel PmenuSel",
     "default link PmenuExtra Pmenu",
     "default link PmenuExtraSel PmenuSel",
     CENT("Normal cterm=NONE", "Normal gui=NONE"),
diff --git a/src/insexpand.c b/src/insexpand.c
index 19a4a21..74be94c 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -1432,6 +1432,15 @@
 #define DICT_EXACT	(2)	// "dict" is the exact name of a file
 
 /*
+ * Get current completion leader
+ */
+    char_u *
+ins_compl_leader(void)
+{
+    return compl_leader;
+}
+
+/*
  * Add any identifiers that match the given pattern "pat" in the list of
  * dictionary files "dict_start" to the list of completions.
  */
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 7b58f6b..617f3ce 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -301,7 +301,7 @@
 # define ISP_LATIN1 (char_u *)"@,161-255"
 #endif
 
-# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC,g:MsgArea"
+# define HIGHLIGHT_INIT "8:SpecialKey,~:EndOfBuffer,@:NonText,d:Directory,e:ErrorMsg,i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr,G:CursorLineSign,O:CursorLineFold,r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg,W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn,-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,k:PmenuMatch,<:PmenuMatchSel,[:PmenuKind,]:PmenuKindSel,{:PmenuExtra,}:PmenuExtraSel,x:PmenuSbar,X:PmenuThumb,*:TabLine,#:TabLineSel,_:TabLineFill,!:CursorColumn,.:CursorLine,o:ColorColumn,q:QuickFixLine,z:StatusLineTerm,Z:StatusLineTermNC,g:MsgArea"
 
 // Default python version for pyx* commands
 #if defined(FEAT_PYTHON) && defined(FEAT_PYTHON3)
diff --git a/src/popupmenu.c b/src/popupmenu.c
index 01b6ab1..00b0006 100644
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -417,6 +417,88 @@
 }
 
 /*
+ * displays text on the popup menu with specific attributes.
+ */
+    static void
+pum_screen_put_with_attr(int row, int col, char_u *text, int textlen, int attr)
+{
+    int		i;
+    int		leader_len;
+    int		char_len;
+    int		cells;
+    int		new_attr;
+    char_u	*rt_leader = NULL;
+    char_u	*match_leader = NULL;
+    char_u	*ptr = text;
+    garray_T	*ga = NULL;
+    char_u	*leader = ins_compl_leader();
+    int		in_fuzzy = (get_cot_flags() & COT_FUZZY) != 0;
+
+    if ((highlight_attr[HLF_PMSI] == highlight_attr[HLF_PSI] &&
+         highlight_attr[HLF_PMNI] == highlight_attr[HLF_PNI]))
+    {
+        screen_puts_len(text, textlen, row, col, attr);
+        return;
+    }
+
+#ifdef FEAT_RIGHTLEFT
+    if (leader != NULL && curwin->w_p_rl)
+        rt_leader = reverse_text(leader);
+#endif
+    match_leader = rt_leader != NULL ? rt_leader : leader;
+    leader_len = match_leader ? (int)STRLEN(match_leader) : 0;
+
+    if (match_leader != NULL && leader_len > 0 && in_fuzzy)
+        ga = fuzzy_match_str_with_pos(text, match_leader);
+
+    // Render text with proper attributes
+    while (*ptr != NUL && ptr < text + textlen)
+    {
+        char_len = mb_ptr2len(ptr);
+        cells = mb_ptr2cells(ptr);
+        new_attr = attr;
+
+        if (ga != NULL)
+        {
+            // Handle fuzzy matching
+            for (i = 0; i < ga->ga_len; i++)
+            {
+                int *match_pos = ((int *)ga->ga_data) + i;
+                int actual_char_pos = 0;
+                char_u *temp_ptr = text;
+                while (temp_ptr < ptr)
+                {
+                    temp_ptr += mb_ptr2len(temp_ptr);
+                    actual_char_pos++;
+                }
+                if (actual_char_pos == match_pos[0])
+                {
+                    new_attr = highlight_attr[(attr == highlight_attr[HLF_PSI]
+							? HLF_PMSI : HLF_PMNI)];
+                    break;
+                }
+            }
+        }
+        else if (!in_fuzzy && (ptr - text < leader_len) &&
+				(STRNCMP(text, match_leader, leader_len) == 0))
+                new_attr = highlight_attr[(attr == highlight_attr[HLF_PSI]
+						    ? HLF_PMSI : HLF_PMNI)];
+
+        screen_puts_len(ptr, char_len, row, col, new_attr);
+        col += cells;
+        ptr += char_len;
+    }
+
+    if (ga != NULL)
+    {
+        ga_clear(ga);
+        vim_free(ga);
+    }
+    if (rt_leader)
+        vim_free(rt_leader);
+}
+
+/*
  * Redraw the popup menu, using "pum_first" and "pum_selected".
  */
     void
@@ -567,8 +649,7 @@
 					    size++;
 					}
 				    }
-				    screen_puts_len(rt, (int)STRLEN(rt),
-						   row, col - size + 1, attr);
+				    pum_screen_put_with_attr(row, col -size + 1, rt, (int)STRLEN(rt), attr);
 				    vim_free(rt_start);
 				}
 				vim_free(st);
@@ -596,7 +677,7 @@
 				    else
 					--cells;
 				}
-				screen_puts_len(st, size, row, col, attr);
+				pum_screen_put_with_attr(row, col, st, size, attr);
 				vim_free(st);
 			    }
 			    col += width;
diff --git a/src/proto/insexpand.pro b/src/proto/insexpand.pro
index 6b34c0f..dbd5ef7 100644
--- a/src/proto/insexpand.pro
+++ b/src/proto/insexpand.pro
@@ -30,6 +30,7 @@
 unsigned int get_cot_flags(void);
 int pum_wanted(void);
 void ins_compl_show_pum(void);
+char_u *ins_compl_leader(void);
 char_u *find_word_start(char_u *ptr);
 char_u *find_word_end(char_u *ptr);
 void ins_compl_clear(void);
diff --git a/src/proto/search.pro b/src/proto/search.pro
index d9cb16a..08526c8 100644
--- a/src/proto/search.pro
+++ b/src/proto/search.pro
@@ -40,6 +40,7 @@
 void f_matchfuzzy(typval_T *argvars, typval_T *rettv);
 void f_matchfuzzypos(typval_T *argvars, typval_T *rettv);
 int fuzzy_match_str(char_u *str, char_u *pat);
+garray_T *fuzzy_match_str_with_pos(char_u *str, char_u *pat);
 void fuzmatch_str_free(fuzmatch_str_T *fuzmatch, int count);
 int fuzzymatches_to_strmatches(fuzmatch_str_T *fuzmatch, char_u ***matches, int count, int funcsort);
 /* vim: set ft=c : */
diff --git a/src/search.c b/src/search.c
index 43c40e0..864bfe3 100644
--- a/src/search.c
+++ b/src/search.c
@@ -5092,6 +5092,125 @@
 }
 
 /*
+ * Fuzzy match the position of string 'pat' in string 'str'.
+ * Returns a dynamic array of matching positions. If there is no match,
+ * returns NULL.
+ */
+    garray_T *
+fuzzy_match_str_with_pos(char_u *str UNUSED, char_u *pat UNUSED)
+{
+#ifdef FEAT_SEARCH_EXTRA
+    int		    score = 0;
+    garray_T	    *match_positions = ALLOC_ONE(garray_T);
+    typval_T	    tv_str;
+    list_T	    *l = NULL;
+    list_T	    *retlist = NULL;
+    list_T	    *match_str_list = NULL;
+    list_T	    *match_pos_list = NULL;
+    list_T	    *match_score_list = NULL;
+    listitem_T	    *score_item = NULL;
+    listitem_T	    *positions_item = NULL;
+    list_T	    *positions_outer_list = NULL;
+    listitem_T	    *outer_li = NULL;
+    list_T	    *positions_inner_list = NULL;
+
+    if (match_positions == NULL)
+        return NULL;
+    ga_init2(match_positions, sizeof(int), 10);
+    if (str == NULL || pat == NULL)
+    {
+        ga_clear(match_positions);
+        return NULL;
+    }
+    l = list_alloc();
+    if (l == NULL)
+    {
+        ga_clear(match_positions);
+        return NULL;
+    }
+
+    tv_str.v_type = VAR_STRING;
+    tv_str.vval.v_string = vim_strsave(str);
+    if (tv_str.vval.v_string == NULL || list_append_tv(l, &tv_str) == FAIL)
+        goto cleanup;
+
+    retlist = list_alloc();
+    if (retlist == NULL)
+        goto cleanup;
+
+    match_str_list = list_alloc();
+    match_pos_list = list_alloc();
+    match_score_list = list_alloc();
+    if (match_str_list == NULL || match_pos_list == NULL || match_score_list == NULL)
+        goto cleanup;
+
+    list_append_list(retlist, match_str_list);
+    list_append_list(retlist, match_pos_list);
+    list_append_list(retlist, match_score_list);
+
+    fuzzy_match_in_list(l, pat, FALSE, NULL, NULL, TRUE, retlist, 1);
+
+    if (retlist->lv_len != 3)
+        goto cleanup;
+
+    score_item = list_find(retlist, 2);
+    if (score_item != NULL && score_item->li_tv.v_type == VAR_LIST)
+    {
+        list_T *score_list = score_item->li_tv.vval.v_list;
+        if (score_list->lv_len > 0)
+        {
+            listitem_T *first_score_item = score_list->lv_first;
+            if (first_score_item != NULL && first_score_item->li_tv.v_type == VAR_NUMBER)
+                score = first_score_item->li_tv.vval.v_number;
+        }
+    }
+    if (score == 0)
+        goto cleanup;
+
+    positions_item = list_find(retlist, 1);
+    if (positions_item != NULL && positions_item->li_tv.v_type == VAR_LIST)
+    {
+        positions_outer_list = positions_item->li_tv.vval.v_list;
+        if (positions_outer_list->lv_len > 0)
+        {
+            outer_li = positions_outer_list->lv_first;
+            if (outer_li != NULL && outer_li->li_tv.v_type == VAR_LIST)
+            {
+                positions_inner_list = outer_li->li_tv.vval.v_list;
+                for (listitem_T *li = positions_inner_list->lv_first; li != NULL; li = li->li_next)
+                {
+                    if (li->li_tv.v_type == VAR_NUMBER)
+                    {
+                        int pos = li->li_tv.vval.v_number;
+                        ga_grow(match_positions, 1);
+                        ((int *)match_positions->ga_data)[match_positions->ga_len] = pos;
+                        match_positions->ga_len++;
+                    }
+                }
+            }
+        }
+    }
+
+    vim_free(tv_str.vval.v_string);
+    list_free(retlist);
+    list_free(l);
+    return match_positions;
+
+cleanup:
+    vim_free(tv_str.vval.v_string);
+    list_free(match_str_list);
+    list_free(match_pos_list);
+    list_free(match_score_list);
+    list_free(retlist);
+    list_free(l);
+    ga_clear(match_positions);
+    return NULL;
+#else
+    return NULL;
+#endif
+}
+
+/*
  * Free an array of fuzzy string matches "fuzmatch[count]".
  */
     void
diff --git a/src/testdir/dumps/Test_pum_highlights_03.dump b/src/testdir/dumps/Test_pum_highlights_03.dump
new file mode 100644
index 0000000..259e498
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_highlights_03.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o> @72
+|f+0#00e0e07#ffd7ff255|o|o+0#0000001#e0e0e08| @11| +0#4040ff13#ffffff0@59
+|f+0#0000e05#ffd7ff255|o|o+0#0000001&|b|a|r| @8| +0#4040ff13#ffffff0@59
+|f+0#0000e05#ffd7ff255|o|o+0#0000001&|B|a|z| @8| +0#4040ff13#ffffff0@59
+|f+0#0000e05#ffd7ff255|o|o+0#0000001&|b|a|l|a| @7| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |8| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_highlights_04.dump b/src/testdir/dumps/Test_pum_highlights_04.dump
new file mode 100644
index 0000000..2204dbd
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_highlights_04.dump
@@ -0,0 +1,20 @@
+|你*0&#ffffff0> +&@72
+|你*0#00e0e07#ffd7ff255|好*0#0000001#e0e0e08| +&@10| +0#4040ff13#ffffff0@59
+|你*0#0000e05#ffd7ff255|好*0#0000001&|吗| +&@8| +0#4040ff13#ffffff0@59
+|你*0#0000e05#ffd7ff255|不*0#0000001&|好|吗| +&@6| +0#4040ff13#ffffff0@59
+|你*0#0000e05#ffd7ff255|可*0#0000001&|好|吗| +&@6| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |8| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_highlights_05.dump b/src/testdir/dumps/Test_pum_highlights_05.dump
new file mode 100644
index 0000000..b67c249
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_highlights_05.dump
@@ -0,0 +1,20 @@
+|你*0&#ffffff0|吗> +&@70
+|你*0#00e0e07#ffd7ff255|好*0#0000001#e0e0e08|吗*0#00e0e07#ffd7ff255| +0#0000001#e0e0e08@8| +0#4040ff13#ffffff0@59
+|你*0#0000e05#ffd7ff255|不*0#0000001&|好|吗*0#0000e05&| +0#0000001&@6| +0#4040ff13#ffffff0@59
+|你*0#0000e05#ffd7ff255|可*0#0000001&|好|吗*0#0000e05&| +0#0000001&@6| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |8| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_highlights_06.dump b/src/testdir/dumps/Test_pum_highlights_06.dump
new file mode 100644
index 0000000..cb9ca42
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_highlights_06.dump
@@ -0,0 +1,20 @@
+| +0&#ffffff0@70|o>f|o|f
+| +0#4040ff13&@59| +0#0000001#e0e0e08@11|o|o+0#00e0e07#ffd7ff255|f
+| +0#4040ff13#ffffff0@59| +0#0000001#ffd7ff255@8|r|a|b|o|o+0#0000e05&|f
+| +0#4040ff13#ffffff0@59| +0#0000001#ffd7ff255@8|z|a|B|o|o+0#0000e05&|f
+| +0#4040ff13#ffffff0@59| +0#0000001#ffd7ff255@7|a|l|a|b|o|o+0#0000e05&|f
+| +0#4040ff13#ffffff0@73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |8| +0#0000000&@34
diff --git a/src/testdir/dumps/Test_pum_highlights_07.dump b/src/testdir/dumps/Test_pum_highlights_07.dump
new file mode 100644
index 0000000..259e498
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_highlights_07.dump
@@ -0,0 +1,20 @@
+|f+0&#ffffff0|o> @72
+|f+0#00e0e07#ffd7ff255|o|o+0#0000001#e0e0e08| @11| +0#4040ff13#ffffff0@59
+|f+0#0000e05#ffd7ff255|o|o+0#0000001&|b|a|r| @8| +0#4040ff13#ffffff0@59
+|f+0#0000e05#ffd7ff255|o|o+0#0000001&|B|a|z| @8| +0#4040ff13#ffffff0@59
+|f+0#0000e05#ffd7ff255|o|o+0#0000001&|b|a|l|a| @7| +0#4040ff13#ffffff0@59
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|-+2#0000000&@1| |O|m|n|i| |c|o|m|p|l|e|t|i|o|n| |(|^|O|^|N|^|P|)| |m+0#00e0003&|a|t|c|h| |1| |o|f| |8| +0#0000000&@34
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
index 1142efc..8626288 100644
--- a/src/testdir/test_popup.vim
+++ b/src/testdir/test_popup.vim
@@ -1341,4 +1341,71 @@
   call StopVimInTerminal(buf)
 endfunc
 
+" Test match relate highlight group in pmenu
+func Test_pum_highlights_match()
+  CheckScreendump
+  let lines =<< trim END
+    func Omni_test(findstart, base)
+      if a:findstart
+        return col(".")
+      endif
+      return {
+            \ 'words': [
+            \ { 'word': 'foo',},
+            \ { 'word': 'foobar',},
+            \ { 'word': 'fooBaz',},
+            \ { 'word': 'foobala',},
+            \ { 'word': '你好',},
+            \ { 'word': '你好吗',},
+            \ { 'word': '你不好吗',},
+            \ { 'word': '你可好吗',},
+            \]}
+    endfunc
+    set omnifunc=Omni_test
+    set completeopt=menu,noinsert,fuzzy
+    hi PmenuMatchSel  ctermfg=6 ctermbg=225
+    hi PmenuMatch     ctermfg=4 ctermbg=225
+  END
+  call writefile(lines, 'Xscript', 'D')
+  let  buf = RunVimInTerminal('-S Xscript', {})
+  call TermWait(buf)
+  call term_sendkeys(buf, "i\<C-X>\<C-O>")
+  call TermWait(buf, 50)
+  call term_sendkeys(buf, "fo")
+  call TermWait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_pum_highlights_03', {})
+  call term_sendkeys(buf, "\<ESC>S\<C-x>\<C-O>")
+  call TermWait(buf, 50)
+  call term_sendkeys(buf, "你")
+  call TermWait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_pum_highlights_04', {})
+  call term_sendkeys(buf, "吗")
+  call TermWait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_pum_highlights_05', {})
+
+  if has('rightleft')
+    call term_sendkeys(buf, "\<C-E>\<ESC>u:set rightleft\<CR>")
+    call TermWait(buf, 50)
+    call term_sendkeys(buf, "i\<C-X>\<C-O>")
+    call TermWait(buf, 50)
+    call term_sendkeys(buf, "fo")
+    call TermWait(buf, 50)
+    call VerifyScreenDump(buf, 'Test_pum_highlights_06', {})
+    call term_sendkeys(buf, "\<C-E>\<ESC>u:set norightleft\<CR>")
+    call TermWait(buf)
+  endif
+
+  call term_sendkeys(buf, ":set completeopt-=fuzzy\<CR>")
+  call TermWait(buf)
+  call term_sendkeys(buf, "\<ESC>S\<C-x>\<C-O>")
+  call TermWait(buf, 50)
+  call term_sendkeys(buf, "fo")
+  call TermWait(buf, 50)
+  call VerifyScreenDump(buf, 'Test_pum_highlights_07', {})
+
+  call term_sendkeys(buf, "\<C-E>\<Esc>u")
+  call TermWait(buf)
+  call StopVimInTerminal(buf)
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 8d8e7f5..12dc575 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    476,
+/**/
     475,
 /**/
     474,
diff --git a/src/vim.h b/src/vim.h
index 654e523..e703239 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1500,6 +1500,8 @@
     , HLF_SPL	    // SpellLocal
     , HLF_PNI	    // popup menu normal item
     , HLF_PSI	    // popup menu selected item
+    , HLF_PMNI	    // popup menu matched text in normal item
+    , HLF_PMSI	    // popup menu matched text in selected item
     , HLF_PNK	    // popup menu normal item "kind"
     , HLF_PSK	    // popup menu selected item "kind"
     , HLF_PNX	    // popup menu normal item "menu" (extra text)
@@ -1525,7 +1527,7 @@
 		  'n', 'a', 'b', 'N', 'G', 'O', 'r', 's', 'S', 'c', 't', 'v', 'V', \
 		  'w', 'W', 'f', 'F', 'A', 'C', 'D', 'T', '-', '>', \
 		  'B', 'P', 'R', 'L', \
-		  '+', '=', '[', ']', '{', '}', 'x', 'X', \
+		  '+', '=', 'k', '<','[', ']', '{', '}', 'x', 'X', \
 		  '*', '#', '_', '!', '.', 'o', 'q', \
 		  'z', 'Z', 'g'}