aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-06-15 05:56:15 +0800
committerGitHub <noreply@github.com>2024-06-15 05:56:15 +0800
commit4b36a7e60148c8feb7781887b119a01d7989a8c2 (patch)
tree46451671cc5f19c9575620661f15a405e324b0ca /src
parentfd950d4998a497cb4258d35af72408105900296a (diff)
parentaacd6c440d21bea9dbe9588da076d3351f9b228c (diff)
downloadrneovim-4b36a7e60148c8feb7781887b119a01d7989a8c2.tar.gz
rneovim-4b36a7e60148c8feb7781887b119a01d7989a8c2.tar.bz2
rneovim-4b36a7e60148c8feb7781887b119a01d7989a8c2.zip
Merge pull request #29311 from zeertzjq/vim-9.1.0476
vim-patch:9.1.{0476,0478,0479,0480,0485}
Diffstat (limited to 'src')
-rw-r--r--src/nvim/highlight.h2
-rw-r--r--src/nvim/highlight_defs.h2
-rw-r--r--src/nvim/highlight_group.c2
-rw-r--r--src/nvim/insexpand.c6
-rw-r--r--src/nvim/option_vars.h14
-rw-r--r--src/nvim/popupmenu.c90
-rw-r--r--src/nvim/search.c33
7 files changed, 131 insertions, 18 deletions
diff --git a/src/nvim/highlight.h b/src/nvim/highlight.h
index 558727fc51..2ba6cf5371 100644
--- a/src/nvim/highlight.h
+++ b/src/nvim/highlight.h
@@ -54,6 +54,8 @@ EXTERN const char *hlf_names[] INIT( = {
[HLF_SPL] = "SpellLocal",
[HLF_PNI] = "Pmenu",
[HLF_PSI] = "PmenuSel",
+ [HLF_PMNI] = "PmenuMatch",
+ [HLF_PMSI] = "PmenuMatchSel",
[HLF_PNK] = "PmenuKind",
[HLF_PSK] = "PmenuKindSel",
[HLF_PNX] = "PmenuExtra",
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 17e3db04da..e0cce81166 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -101,6 +101,8 @@ typedef enum {
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)
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index aa98983b63..3c777e7c4d 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -169,6 +169,8 @@ static const char *highlight_init_both[] = {
"default link PmenuExtraSel PmenuSel",
"default link PmenuKind Pmenu",
"default link PmenuKindSel PmenuSel",
+ "default link PmenuMatch Pmenu",
+ "default link PmenuMatchSel PmenuSel",
"default link PmenuSbar Pmenu",
"default link Substitute Search",
"default link StatusLineTerm StatusLine",
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 139637b8a1..9b6805404f 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -1388,6 +1388,12 @@ bool compl_match_curr_select(int selected)
#define DICT_FIRST (1) ///< use just first element in "dict"
#define DICT_EXACT (2) ///< "dict" is the exact name of a file
+/// Get current completion leader
+char *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/nvim/option_vars.h b/src/nvim/option_vars.h
index bd0fe699d9..404e58661c 100644
--- a/src/nvim/option_vars.h
+++ b/src/nvim/option_vars.h
@@ -55,13 +55,13 @@
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@: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,g:MsgArea,0:Whitespace,I:NormalNC"
+ "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,0:Whitespace,I:NormalNC"
// Default values for 'errorformat'.
// The "%f|%l| %m" one is used for when the contents of the quickfix window is
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index 324254a188..1ef5aac1e9 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -25,6 +25,7 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
#include "nvim/extmark_defs.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
@@ -48,6 +49,7 @@
#include "nvim/plines.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
+#include "nvim/search.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
@@ -435,6 +437,73 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
pum_redraw();
}
+/// Displays text on the popup menu with specific attributes.
+static void pum_puts_with_attr(int col, char *text, hlf_T hlf)
+{
+ char *leader = ins_compl_leader();
+
+ if (leader == NULL || *leader == NUL || (hlf != HLF_PSI && hlf != HLF_PNI)
+ || (win_hl_attr(curwin, HLF_PMSI) == win_hl_attr(curwin, HLF_PSI)
+ && win_hl_attr(curwin, HLF_PMNI) == win_hl_attr(curwin, HLF_PNI))) {
+ grid_line_puts(col, text, -1, win_hl_attr(curwin, (int)hlf));
+ return;
+ }
+
+ char *rt_leader = NULL;
+ if (curwin->w_p_rl) {
+ rt_leader = reverse_text(leader);
+ }
+ char *match_leader = rt_leader != NULL ? rt_leader : leader;
+ size_t leader_len = strlen(match_leader);
+
+ const bool in_fuzzy = (get_cot_flags() & COT_FUZZY) != 0;
+
+ garray_T *ga = NULL;
+ if (in_fuzzy) {
+ ga = fuzzy_match_str_with_pos(text, match_leader);
+ }
+
+ // Render text with proper attributes
+ const char *ptr = text;
+ while (*ptr != NUL) {
+ int char_len = utfc_ptr2len(ptr);
+ int cells = utf_ptr2cells(ptr);
+ int new_attr = win_hl_attr(curwin, (int)hlf);
+
+ if (ga != NULL) {
+ // Handle fuzzy matching
+ for (int i = 0; i < ga->ga_len; i++) {
+ uint32_t *match_pos = ((uint32_t *)ga->ga_data) + i;
+ uint32_t actual_char_pos = 0;
+ const char *temp_ptr = text;
+ while (temp_ptr < ptr) {
+ temp_ptr += utfc_ptr2len(temp_ptr);
+ actual_char_pos++;
+ }
+ if (actual_char_pos == match_pos[0]) {
+ new_attr = win_hl_attr(curwin, hlf == HLF_PSI ? HLF_PMSI : HLF_PMNI);
+ break;
+ }
+ }
+ } else if (!in_fuzzy && ptr < text + leader_len
+ && strncmp(text, match_leader, leader_len) == 0) {
+ new_attr = win_hl_attr(curwin, hlf == HLF_PSI ? HLF_PMSI : HLF_PMNI);
+ }
+
+ grid_line_puts(col, ptr, char_len, new_attr);
+ col += cells;
+ ptr += char_len;
+ }
+
+ if (ga != NULL) {
+ ga_clear(ga);
+ xfree(ga);
+ }
+ if (rt_leader) {
+ xfree(rt_leader);
+ }
+}
+
/// Redraw the popup menu, using "pum_first" and "pum_selected".
void pum_redraw(void)
{
@@ -446,11 +515,9 @@ void pum_redraw(void)
int thumb_height = 1;
int n;
-#define HA(hlf) (win_hl_attr(curwin, (hlf)))
- // "word" "kind" "extra text"
- const int attrsNorm[3] = { HA(HLF_PNI), HA(HLF_PNK), HA(HLF_PNX) };
- const int attrsSel[3] = { HA(HLF_PSI), HA(HLF_PSK), HA(HLF_PSX) };
-#undef HA
+ // "word" "kind" "extra text"
+ const hlf_T hlfsNorm[3] = { HLF_PNI, HLF_PNK, HLF_PNX };
+ const hlf_T hlfsSel[3] = { HLF_PSI, HLF_PSK, HLF_PSX };
int grid_width = pum_width;
int col_off = 0;
@@ -517,8 +584,9 @@ void pum_redraw(void)
for (int i = 0; i < pum_height; i++) {
int idx = i + pum_first;
- const int *const attrs = (idx == pum_selected) ? attrsSel : attrsNorm;
- int attr = attrs[0]; // start with "word" highlight
+ const hlf_T *const hlfs = (idx == pum_selected) ? hlfsSel : hlfsNorm;
+ hlf_T hlf = hlfs[0]; // start with "word" highlight
+ int attr = win_hl_attr(curwin, (int)hlf);
grid_line_start(&pum_grid, row);
@@ -540,7 +608,8 @@ void pum_redraw(void)
int totwidth = 0;
for (int round = 0; round < 3; round++) {
- attr = attrs[round];
+ hlf = hlfs[round];
+ attr = win_hl_attr(curwin, (int)hlf);
int width = 0;
char *s = NULL;
@@ -593,13 +662,12 @@ void pum_redraw(void)
size++;
}
}
- grid_line_puts(grid_col - size + 1, rt, -1, attr);
+ pum_puts_with_attr(grid_col - size + 1, rt, hlf);
xfree(rt_start);
xfree(st);
grid_col -= width;
} else {
- // use grid_line_puts() to truncate the text
- grid_line_puts(grid_col, st, -1, attr);
+ pum_puts_with_attr(grid_col, st, hlf);
xfree(st);
grid_col += width;
}
diff --git a/src/nvim/search.c b/src/nvim/search.c
index bee124e305..994a0794b0 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -21,12 +21,14 @@
#include "nvim/errors.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
@@ -3542,6 +3544,37 @@ int fuzzy_match_str(char *const str, const char *const pat)
return score;
}
+/// 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 *const str, const char *const pat)
+{
+ if (str == NULL || pat == NULL) {
+ return NULL;
+ }
+
+ garray_T *match_positions = xmalloc(sizeof(garray_T));
+ ga_init(match_positions, sizeof(uint32_t), 10);
+
+ unsigned matches[MAX_FUZZY_MATCHES];
+ int score = 0;
+ if (!fuzzy_match(str, pat, false, &score, matches, MAX_FUZZY_MATCHES)
+ || score == 0) {
+ ga_clear(match_positions);
+ xfree(match_positions);
+ return NULL;
+ }
+
+ int j = 0;
+ for (const char *p = pat; *p != NUL; MB_PTR_ADV(p)) {
+ if (!ascii_iswhite(utf_ptr2char(p))) {
+ GA_APPEND(uint32_t, match_positions, matches[j]);
+ j++;
+ }
+ }
+
+ return match_positions;
+}
+
/// Copy a list of fuzzy matches into a string list after sorting the matches by
/// the fuzzy score. Frees the memory allocated for "fuzmatch".
void fuzzymatches_to_strmatches(fuzmatch_str_T *const fuzmatch, char ***const matches,