0
0
mirror of https://github.com/vim/vim.git synced 2025-09-28 04:24:06 -04:00

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: #17081

Signed-off-by: glepnir <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
glepnir
2025-04-12 18:35:34 +02:00
committed by Christian Brabandt
parent cf665ccd37
commit d4dbf822dc
9 changed files with 69 additions and 61 deletions

View File

@@ -3621,6 +3621,7 @@ A jump table for the options with a short description can be found at |Q_op|.
lastline '@' 'display' contains lastline/truncate lastline '@' 'display' contains lastline/truncate
trunc '>' truncated text in the trunc '>' truncated text in the
|ins-completion-menu|. |ins-completion-menu|.
truncrl '<' same as "trunc' in 'rightleft' mode
Any one that is omitted will fall back to the default. Any one that is omitted will fall back to the default.
@@ -3645,6 +3646,7 @@ A jump table for the options with a short description can be found at |Q_op|.
lastline NonText |hl-NonText| lastline NonText |hl-NonText|
trunc one of the many Popup menu highlighting groups like trunc one of the many Popup menu highlighting groups like
|hl-PmenuSel| |hl-PmenuSel|
truncrl same as "trunc"
*'findfunc'* *'ffu'* *E1514* *'findfunc'* *'ffu'* *E1514*
'findfunc' 'ffu' string (default empty) 'findfunc' 'ffu' string (default empty)

View File

@@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2025 Apr 08 *version9.txt* For Vim version 9.1. Last change: 2025 Apr 12
VIM REFERENCE MANUAL by Bram Moolenaar VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41631,6 +41631,7 @@ Options: ~
and CTRL-D / CTRL-U for half-pagewise scrolling and CTRL-D / CTRL-U for half-pagewise scrolling
- New option value for 'fillchars': - New option value for 'fillchars':
"trunc" - configure truncation indicator, 'pummaxwidth' "trunc" - configure truncation indicator, 'pummaxwidth'
"truncrl" - like "trunc" but in 'rl' mode, 'pummaxwidth'
Ex commands: ~ Ex commands: ~
- allow to specify a priority when defining a new sign |:sign-define| - allow to specify a priority when defining a new sign |:sign-define|

View File

@@ -604,10 +604,15 @@ pum_redraw(void)
int last_isabbr = FALSE; int last_isabbr = FALSE;
int orig_attr = -1; int orig_attr = -1;
int scroll_range = pum_size - pum_height; int scroll_range = pum_size - pum_height;
char_u *new_str = NULL;
char_u *ptr = NULL;
int remaining = 0; int remaining = 0;
int fcs_trunc = curwin->w_fill_chars.trunc; int fcs_trunc;
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
fcs_trunc = curwin->w_fill_chars.truncrl;
else
#endif
fcs_trunc = curwin->w_fill_chars.trunc;
hlf_T hlfsNorm[3]; hlf_T hlfsNorm[3];
hlf_T hlfsSel[3]; hlf_T hlfsSel[3];
@@ -722,10 +727,19 @@ pum_redraw(void)
if (rt != NULL) if (rt != NULL)
{ {
char_u *rt_start = rt; char_u *rt_start = rt;
int cells; int cells;
int over_cell = 0;
int truncated = FALSE;
cells = mb_string2cells(rt , -1); cells = mb_string2cells(rt , -1);
truncated = pum_width == p_pmw
&& pum_width - totwidth < cells;
if (pum_width == p_pmw && !truncated
&& (j + 1 < 3 && pum_get_item(idx, order[j + 1]) != NULL))
truncated = TRUE;
if (cells > pum_width) if (cells > pum_width)
{ {
do do
@@ -746,13 +760,9 @@ pum_redraw(void)
} }
} }
// truncated if (truncated)
if (pum_width == p_pmw
&& totwidth + 1 + cells >= pum_width)
{ {
char_u *orig_rt = rt; char_u *orig_rt = rt;
char_u *old_rt = NULL;
int over_cell = 0;
int size = 0; int size = 0;
remaining = pum_width - totwidth - 1; remaining = pum_width - totwidth - 1;
@@ -768,26 +778,19 @@ pum_redraw(void)
size = (int)STRLEN(orig_rt); size = (int)STRLEN(orig_rt);
if (cells < remaining) if (cells < remaining)
over_cell = remaining - cells; over_cell = remaining - cells;
new_str = alloc(size + over_cell + 1 + utf_char2len(fcs_trunc));
if (!new_str) cells = mb_string2cells(orig_rt, size);
return; width = cells + over_cell + 1;
ptr = new_str; rt = orig_rt;
if (fcs_trunc != NUL && fcs_trunc != '>')
ptr += (*mb_char2bytes)(fcs_trunc, ptr); if (fcs_trunc != NUL)
screen_putchar(fcs_trunc, row, col - width + 1, attr);
else else
*ptr++ = '<'; screen_putchar('<', row, col - width + 1, attr);
if (over_cell)
{ if (over_cell > 0)
vim_memset(ptr, ' ', over_cell); screen_fill(row, row + 1, col - width + 2,
ptr += over_cell; col - width + 2 + over_cell, ' ', ' ', attr);
}
memcpy(ptr, orig_rt, size);
ptr[size] = NUL;
old_rt = rt_start;
rt = rt_start = new_str;
vim_free(old_rt);
cells = mb_string2cells(rt, -1);
width = cells;
} }
if (attrs == NULL) if (attrs == NULL)
@@ -809,10 +812,16 @@ pum_redraw(void)
{ {
if (st != NULL) if (st != NULL)
{ {
int size = (int)STRLEN(st); int size = (int)STRLEN(st);
int cells = (*mb_string2cells)(st, size); int cells = (*mb_string2cells)(st, size);
char_u *st_end = NULL; char_u *st_end = NULL;
int over_cell = 0; int over_cell = 0;
int truncated = pum_width == p_pmw
&& pum_width - totwidth < cells;
if (pum_width == p_pmw && !truncated
&& (j + 1 < 3 && pum_get_item(idx, order[j + 1]) != NULL))
truncated = TRUE;
// only draw the text that fits // only draw the text that fits
while (size > 0 while (size > 0
@@ -829,8 +838,7 @@ pum_redraw(void)
} }
// truncated // truncated
if (pum_width == p_pmw if (truncated)
&& totwidth + 1 + cells >= pum_width)
{ {
remaining = pum_width - totwidth - 1; remaining = pum_width - totwidth - 1;
if (cells > remaining) if (cells > remaining)
@@ -846,28 +854,8 @@ pum_redraw(void)
if (cells < remaining) if (cells < remaining)
over_cell = remaining - cells; over_cell = remaining - cells;
new_str = alloc(size + over_cell + 1 + utf_char2len(fcs_trunc)); cells = mb_string2cells(st, size);
if (!new_str) width = cells + over_cell + 1;
return;
memcpy(new_str, st, size);
ptr = new_str + size;
if (over_cell > 0)
{
vim_memset(ptr, ' ', over_cell);
ptr += over_cell;
}
if (fcs_trunc != NUL)
ptr += (*mb_char2bytes)(fcs_trunc, ptr);
else
*ptr++ = '>';
*ptr = NUL;
vim_free(st);
st = new_str;
cells = mb_string2cells(st, -1);
size = (int)STRLEN(st);
width = cells;
} }
if (attrs == NULL) if (attrs == NULL)
@@ -875,6 +863,18 @@ pum_redraw(void)
else else
pum_screen_puts_with_attrs(row, col, cells, pum_screen_puts_with_attrs(row, col, cells,
st, size, attrs); st, size, attrs);
if (truncated)
{
if (over_cell > 0)
screen_fill(row, row + 1, col + cells,
col + cells + over_cell, ' ', ' ', attr);
if (fcs_trunc != NUL)
screen_putchar(fcs_trunc, row,
col + cells + over_cell, attr);
else
screen_putchar('>', row,
col + cells + over_cell, attr);
}
vim_free(st); vim_free(st);
} }

View File

@@ -4714,6 +4714,7 @@ static struct charstab filltab[] =
CHARSTAB_ENTRY(&fill_chars.eob, "eob"), CHARSTAB_ENTRY(&fill_chars.eob, "eob"),
CHARSTAB_ENTRY(&fill_chars.lastline, "lastline"), CHARSTAB_ENTRY(&fill_chars.lastline, "lastline"),
CHARSTAB_ENTRY(&fill_chars.trunc, "trunc"), CHARSTAB_ENTRY(&fill_chars.trunc, "trunc"),
CHARSTAB_ENTRY(&fill_chars.truncrl, "truncrl"),
}; };
static lcs_chars_T lcs_chars; static lcs_chars_T lcs_chars;
static struct charstab lcstab[] = static struct charstab lcstab[] =
@@ -4828,6 +4829,7 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply,
fill_chars.eob = '~'; fill_chars.eob = '~';
fill_chars.lastline = '@'; fill_chars.lastline = '@';
fill_chars.trunc = '>'; fill_chars.trunc = '>';
fill_chars.truncrl = '<';
} }
} }
p = value; p = value;

View File

@@ -3851,6 +3851,7 @@ typedef struct
int eob; int eob;
int lastline; int lastline;
int trunc; int trunc;
int truncrl;
} fill_chars_T; } fill_chars_T;
/* /*

View File

@@ -1,7 +1,7 @@
|1+0&#ffffff0|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_> @44 |1+0&#ffffff0|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_> @44
|1+0#0000001#e0e0e08|2|3|4|5|6|7|8|9|>| +0#4040ff13#ffffff0@64 |1+0#0000001#e0e0e08|2|3|4|5|6|7|8|9|>| +0#4040ff13#ffffff0@64
|一*0#0000001#ffd7ff255|二|三|四| +&|>| +0#4040ff13#ffffff0@64 |一*0#0000001#ffd7ff255|二|三|四| +&|>| +0#4040ff13#ffffff0@64
|a+0#0000001#ffd7ff255|b|c|d|e|f|g|h|i|>| +0#4040ff13#ffffff0@64 |a+0#0000001#ffd7ff255|b|c|d|e|f|g|h|i|j| +0#4040ff13#ffffff0@64
|上*0#0000001#ffd7ff255|下|左|右| +&@1| +0#4040ff13#ffffff0@64 |上*0#0000001#ffd7ff255|下|左|右| +&@1| +0#4040ff13#ffffff0@64
|~| @73 |~| @73
|~| @73 |~| @73

View File

@@ -1,7 +1,7 @@
| +0&#ffffff0@43> |_|9|8|7|6|5|4|3|2|1|_|9|8|7|6|5|4|3|2|1|_|9|8|7|6|5|4|3|2|1 | +0&#ffffff0@43> |_|9|8|7|6|5|4|3|2|1|_|9|8|7|6|5|4|3|2|1|_|9|8|7|6|5|4|3|2|1
| +0#4040ff13&@64|<+0#0000001#e0e0e08|9|8|7|6|5|4|3|2|1 | +0#4040ff13&@64|<+0#0000001#e0e0e08|9|8|7|6|5|4|3|2|1
| +0#4040ff13#ffffff0@64|<+0#0000001#ffd7ff255| |四*&|三|二|一 | +0#4040ff13#ffffff0@64|<+0#0000001#ffd7ff255| |四*&|三|二|一
| +0#4040ff13#ffffff0@64|<+0#0000001#ffd7ff255|i|h|g|f|e|d|c|b|a | +0#4040ff13#ffffff0@64|j+0#0000001#ffd7ff255|i|h|g|f|e|d|c|b|a
| +0#4040ff13#ffffff0@64| +0#0000001#ffd7ff255@1|右*&|左|下|上 | +0#4040ff13#ffffff0@64| +0#0000001#ffd7ff255@1|右*&|左|下|上
| +0#4040ff13#ffffff0@73|~ | +0#4040ff13#ffffff0@73|~
| @73|~ | @73|~

View File

@@ -2126,7 +2126,7 @@ func Test_pum_maxwidth_multibyte()
call VerifyScreenDump(buf, 'Test_pum_maxwidth_16', {'rows': 8}) call VerifyScreenDump(buf, 'Test_pum_maxwidth_16', {'rows': 8})
call term_sendkeys(buf, "\<ESC>") call term_sendkeys(buf, "\<ESC>")
call term_sendkeys(buf, ":set fcs+=trunc:…\<CR>") call term_sendkeys(buf, ":set fcs+=truncrl:…\<CR>")
call term_sendkeys(buf, "S\<C-X>\<C-O>") call term_sendkeys(buf, "S\<C-X>\<C-O>")
call VerifyScreenDump(buf, 'Test_pum_maxwidth_17', {'rows': 8}) call VerifyScreenDump(buf, 'Test_pum_maxwidth_17', {'rows': 8})
call term_sendkeys(buf, "\<ESC>") call term_sendkeys(buf, "\<ESC>")

View File

@@ -704,6 +704,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 */
/**/
1296,
/**/ /**/
1295, 1295,
/**/ /**/