From 6e5671b00df14d2848b157beb42dae01205a6455 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 16 Apr 2025 07:29:44 +0800 Subject: [PATCH] vim-patch:9.1.1296: completion: incorrect truncation logic Problem: completion: incorrect truncation logic (after: v9.1.1284) Solution: replace string allocation with direct screen rendering and fixe RTL/LTR truncation calculations (glepnir) closes: vim/vim#17081 https://github.com/vim/vim/commit/d4dbf822dcb9fd95379bebab85def391e1179b21 Co-authored-by: glepnir --- runtime/doc/options.txt | 2 ++ runtime/lua/vim/_meta/options.lua | 2 ++ src/nvim/buffer_defs.h | 1 + src/nvim/options.lua | 2 ++ src/nvim/optionstr.c | 1 + src/nvim/popupmenu.c | 14 +++++++++----- test/functional/ui/popupmenu_spec.lua | 10 +++++----- test/old/testdir/test_popup.vim | 2 +- 8 files changed, 23 insertions(+), 11 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index f55e7b80c5..4740b03c17 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2642,6 +2642,7 @@ A jump table for the options with a short description can be found at |Q_op|. lastline '@' 'display' contains lastline/truncate trunc '>' truncated text in the |ins-completion-menu|. + truncrl '<' same as "trunc' in 'rightleft' mode Any one that is omitted will fall back to the default. @@ -2681,6 +2682,7 @@ A jump table for the options with a short description can be found at |Q_op|. lastline NonText |hl-NonText| trunc one of the many Popup menu highlighting groups like |hl-PmenuSel| + truncrl same as "trunc" *'findfunc'* *'ffu'* *E1514* 'findfunc' 'ffu' string (default "") diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua index 17f64be99d..a73204c88b 100644 --- a/runtime/lua/vim/_meta/options.lua +++ b/runtime/lua/vim/_meta/options.lua @@ -2334,6 +2334,7 @@ vim.bo.ft = vim.bo.filetype --- lastline '@' 'display' contains lastline/truncate --- trunc '>' truncated text in the --- `ins-completion-menu`. +--- truncrl '<' same as "trunc' in 'rightleft' mode --- --- Any one that is omitted will fall back to the default. --- @@ -2376,6 +2377,7 @@ vim.bo.ft = vim.bo.filetype --- lastline NonText `hl-NonText` --- trunc one of the many Popup menu highlighting groups like --- `hl-PmenuSel` +--- truncrl same as "trunc" --- --- @type string vim.o.fillchars = "" diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 3e56711499..cd7cf408d6 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1057,6 +1057,7 @@ typedef struct { schar_T eob; schar_T lastline; schar_T trunc; + schar_T truncrl; } fcs_chars_T; /// Structure which contains all information that belongs to a window. diff --git a/src/nvim/options.lua b/src/nvim/options.lua index fe971a39b7..504e5defa1 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -3062,6 +3062,7 @@ local options = { lastline '@' 'display' contains lastline/truncate trunc '>' truncated text in the |ins-completion-menu|. + truncrl '<' same as "trunc' in 'rightleft' mode Any one that is omitted will fall back to the default. @@ -3101,6 +3102,7 @@ local options = { lastline NonText |hl-NonText| trunc one of the many Popup menu highlighting groups like |hl-PmenuSel| + truncrl same as "trunc" ]=], expand_cb = 'expand_set_chars_option', full_name = 'fillchars', diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index dbf5851130..9d5b2f8ff8 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -2133,6 +2133,7 @@ static const struct chars_tab fcs_tab[] = { CHARSTAB_ENTRY(&fcs_chars.eob, "eob", "~", NULL), CHARSTAB_ENTRY(&fcs_chars.lastline, "lastline", "@", NULL), CHARSTAB_ENTRY(&fcs_chars.trunc, "trunc", ">", NULL), + CHARSTAB_ENTRY(&fcs_chars.truncrl, "truncrl", "<", NULL), }; static lcs_chars_T lcs_chars; diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index 3e6ae16293..7060367c13 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -577,7 +577,8 @@ void pum_redraw(void) int thumb_pos = 0; int thumb_height = 1; int n; - schar_T fcs_trunc = curwin->w_p_fcs_chars.trunc; + const schar_T fcs_trunc = pum_rl ? curwin->w_p_fcs_chars.truncrl + : curwin->w_p_fcs_chars.trunc; // "word" "kind" "extra text" const hlf_T hlfsNorm[3] = { HLF_PNI, HLF_PNK, HLF_PNX }; @@ -720,7 +721,9 @@ void pum_redraw(void) char *rt = reverse_text(st); char *rt_start = rt; int cells = (int)mb_string2cells(rt); - if (pum_width == p_pmw && totwidth + 1 + cells >= pum_width) { + if (pum_width == p_pmw + && (pum_width - totwidth < cells + || (j + 1 < 3 && pum_get_item(idx, order[j + 1]) != NULL))) { need_fcs_trunc = true; } @@ -749,7 +752,9 @@ void pum_redraw(void) grid_col -= width; } else { int cells = (int)mb_string2cells(st); - if (pum_width == p_pmw && totwidth + 1 + cells >= pum_width) { + if (pum_width == p_pmw + && (pum_width - totwidth < cells + || (j + 1 < 3 && pum_get_item(idx, order[j + 1]) != NULL))) { need_fcs_trunc = true; } @@ -818,8 +823,7 @@ void pum_redraw(void) const int lcol = col_off - pum_width + 1; grid_line_fill(lcol, grid_col + 1, schar_from_ascii(' '), orig_attr); if (need_fcs_trunc) { - linebuf_char[lcol] = fcs_trunc != NUL && fcs_trunc != schar_from_ascii('>') - ? fcs_trunc : schar_from_ascii('<'); + linebuf_char[lcol] = fcs_trunc != NUL ? fcs_trunc : schar_from_ascii('<'); if (pum_width > 1 && linebuf_char[lcol + 1] == NUL) { linebuf_char[lcol + 1] = schar_from_ascii(' '); } diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index a0039ca103..e910cb7d8e 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -5891,7 +5891,7 @@ describe('builtin popupmenu', function() ## grid 4 {s:123456789>}| {n:一二三四 >}| - {n:abcdefghi>}| + {n:abcdefghij}| {n:上下左右 }| ]], float_pos = { [4] = { -1, 'NW', 2, 1, 0, false, 100, 1, 1, 0 } }, @@ -5901,7 +5901,7 @@ describe('builtin popupmenu', function() 123456789_123456789_123456789_^ | {s:123456789>}{1: }| {n:一二三四 >}{1: }| - {n:abcdefghi>}{1: }| + {n:abcdefghij}{1: }| {n:上下左右 }{1: }| {1:~ }|*2 {2:-- Omni completion (^O^N^P) }{5:match 1 of 4} | @@ -5925,7 +5925,7 @@ describe('builtin popupmenu', function() ## grid 4 {s:<987654321}| {n:< 四三二一}| - {n:') - command('set fcs+=trunc:…') + command('set fcs+=truncrl:…') feed('S') if multigrid then screen:expect({ diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim index 4a3ca0d57c..bc727d1b0a 100644 --- a/test/old/testdir/test_popup.vim +++ b/test/old/testdir/test_popup.vim @@ -2132,7 +2132,7 @@ func Test_pum_maxwidth_multibyte() call VerifyScreenDump(buf, 'Test_pum_maxwidth_16', {'rows': 8}) call term_sendkeys(buf, "\") - call term_sendkeys(buf, ":set fcs+=trunc:…\") + call term_sendkeys(buf, ":set fcs+=truncrl:…\") call term_sendkeys(buf, "S\\") call VerifyScreenDump(buf, 'Test_pum_maxwidth_17', {'rows': 8}) call term_sendkeys(buf, "\")