Skip to content

Commit 88d7593

Browse files
glepnirchrisbra
authored andcommitted
patch 9.1.1250: cannot set the maximum popup menu width
Problem: cannot set the maximum popup menu width (Lucas Mior) Solution: add the new global option value 'pummaxwidth' (glepnir) fixes: #10901 closes: #16943 Signed-off-by: glepnir <[email protected]> Signed-off-by: Christian Brabandt <[email protected]>
1 parent 757c37d commit 88d7593

18 files changed

Lines changed: 285 additions & 17 deletions

runtime/doc/options.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*options.txt* For Vim version 9.1. Last change: 2025 Mar 26
1+
*options.txt* For Vim version 9.1. Last change: 2025 Mar 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -6476,6 +6476,15 @@ A jump table for the options with a short description can be found at |Q_op|.
64766476
global
64776477
Determines the maximum number of items to show in the popup menu for
64786478
Insert mode completion. When zero as much space as available is used.
6479+
|ins-completion-menu|.
6480+
6481+
*'pummaxwidth'* *'pmw'*
6482+
'pummaxwidth' 'pmw' number (default 0)
6483+
global
6484+
Determines the maximum width to use for the popup menu for completion.
6485+
When zero, there is no maximum width limit, otherwise the popup menu
6486+
will never be wider than this value. Truncated text will be indicated
6487+
by "..." at the end. Takes precedence over 'pumwidth'.
64796488
|ins-completion-menu|.
64806489

64816490
*'pumwidth'* *'pw'*

runtime/doc/tags

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,7 @@ $quote eval.txt /*$quote*
843843
'pm' options.txt /*'pm'*
844844
'pmbcs' options.txt /*'pmbcs'*
845845
'pmbfn' options.txt /*'pmbfn'*
846+
'pmw' options.txt /*'pmw'*
846847
'popt' options.txt /*'popt'*
847848
'pp' options.txt /*'pp'*
848849
'preserveindent' options.txt /*'preserveindent'*
@@ -860,6 +861,7 @@ $quote eval.txt /*$quote*
860861
'prompt' options.txt /*'prompt'*
861862
'pt' options.txt /*'pt'*
862863
'pumheight' options.txt /*'pumheight'*
864+
'pummaxwidth' options.txt /*'pummaxwidth'*
863865
'pumwidth' options.txt /*'pumwidth'*
864866
'pvh' options.txt /*'pvh'*
865867
'pvp' options.txt /*'pvp'*

runtime/doc/version9.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*version9.txt* For Vim version 9.1. Last change: 2025 Mar 26
1+
*version9.txt* For Vim version 9.1. Last change: 2025 Mar 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41627,6 +41627,7 @@ Options: ~
4162741627
- 'rulerformat' now supports the |stl-%!| item
4162841628
- use 'smoothscroll' logic for CTRL-F / CTRL-B for pagewise scrolling
4162941629
and CTRL-D / CTRL-U for half-pagewise scrolling
41630+
- 'pummaxwidth' maximum width for the completion popup menu
4163041631

4163141632
Ex commands: ~
4163241633
- allow to specify a priority when defining a new sign |:sign-define|

runtime/optwin.vim

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
" These commands create the option window.
22
"
33
" Maintainer: The Vim Project <https://github.com/vim/vim>
4-
" Last Change: 2025 Mar 07
4+
" Last Change: 2025 Mar 27
55
" Former Maintainer: Bram Moolenaar <[email protected]>
66

77
" If there already is an option window, jump to that one.
@@ -863,6 +863,8 @@ if has("insert_expand")
863863
call <SID>OptionG("ph", &ph)
864864
call <SID>AddOption("pumwidth", gettext("minimum width of the popup menu"))
865865
call <SID>OptionG("pw", &pw)
866+
call <SID>AddOption("pumaxmwidth", gettext("maximum width of the popup menu"))
867+
call <SID>OptionG("pmw", &pmw)
866868
call <SID>AddOption("completefunc", gettext("user defined function for Insert mode completion"))
867869
call append("$", "\t" .. s:local_to_buffer)
868870
call <SID>OptionL("cfu")

runtime/syntax/vim.vim

Lines changed: 10 additions & 10 deletions
Large diffs are not rendered by default.

src/option.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ EXTERN char_u *p_csl; // 'completeslash'
545545
#endif
546546
EXTERN long p_ph; // 'pumheight'
547547
EXTERN long p_pw; // 'pumwidth'
548+
EXTERN long p_pmw; // 'pummaxwidth'
548549
EXTERN char_u *p_com; // 'comments'
549550
EXTERN char_u *p_cpo; // 'cpoptions'
550551
#ifdef FEAT_CSCOPE

src/optiondefs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,9 @@ static struct vimoption options[] =
20212021
{"pumheight", "ph", P_NUM|P_VI_DEF,
20222022
(char_u *)&p_ph, PV_NONE, NULL, NULL,
20232023
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
2024+
{"pummaxwidth", "pmw", P_NUM|P_VI_DEF,
2025+
(char_u *)&p_pmw, PV_NONE, NULL, NULL,
2026+
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
20242027
{"pumwidth", "pw", P_NUM|P_VI_DEF,
20252028
(char_u *)&p_pw, PV_NONE, NULL, NULL,
20262029
{(char_u *)15L, (char_u *)15L} SCTX_INIT},

src/popupmenu.c

Lines changed: 111 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ pum_display(
115115
do
116116
{
117117
def_width = p_pw;
118+
if (p_pmw > 0 && def_width > p_pmw)
119+
def_width = p_pmw;
118120
above_row = 0;
119121
below_row = cmdline_row;
120122

@@ -226,6 +228,8 @@ pum_display(
226228
pum_size = size;
227229
pum_compute_size();
228230
max_width = pum_base_width;
231+
if (p_pmw > 0 && max_width > p_pmw)
232+
max_width = p_pmw;
229233

230234
// Calculate column
231235
if (State == MODE_CMDLINE)
@@ -275,8 +279,12 @@ pum_display(
275279

276280
content_width = max_width + pum_kind_width + pum_extra_width + 1;
277281
if (pum_width > content_width && pum_width > p_pw)
282+
{
278283
// Reduce width to fit item
279-
pum_width = MAX(content_width , p_pw);
284+
pum_width = MAX(content_width, p_pw);
285+
if (p_pmw > 0 && pum_width > p_pmw)
286+
pum_width = p_pmw;
287+
}
280288
else if (((cursor_col > p_pw || cursor_col > max_width)
281289
#ifdef FEAT_RIGHTLEFT
282290
&& !pum_rl)
@@ -313,6 +321,8 @@ pum_display(
313321
if (pum_width < p_pw)
314322
{
315323
pum_width = p_pw;
324+
if (p_pmw > 0 && pum_width > p_pmw)
325+
pum_width = p_pmw;
316326
#ifdef FEAT_RIGHTLEFT
317327
if (pum_rl)
318328
{
@@ -327,7 +337,11 @@ pum_display(
327337
}
328338
}
329339
else if (pum_width > content_width && pum_width > p_pw)
340+
{
330341
pum_width = MAX(content_width, p_pw);
342+
if (p_pmw > 0 && pum_width > p_pmw)
343+
pum_width = p_pmw;
344+
}
331345
}
332346

333347
}
@@ -341,11 +355,15 @@ pum_display(
341355
#endif
342356
pum_col = 0;
343357
pum_width = Columns - 1;
358+
if (p_pmw > 0 && pum_width > p_pmw)
359+
pum_width = p_pmw;
344360
}
345361
else
346362
{
347363
if (max_width > p_pw)
348364
max_width = p_pw; // truncate
365+
if (p_pmw > 0 && max_width > p_pmw)
366+
max_width = p_pmw;
349367
#ifdef FEAT_RIGHTLEFT
350368
if (pum_rl)
351369
pum_col = max_width - 1;
@@ -582,6 +600,13 @@ pum_redraw(void)
582600
int last_isabbr = FALSE;
583601
int orig_attr = -1;
584602
int scroll_range = pum_size - pum_height;
603+
int need_ellipsis = FALSE;
604+
int char_cells = 0;
605+
int ellipsis_width = 3;
606+
int over_cell = 0;
607+
char_u *new_str = NULL;
608+
int kept_len = 0;
609+
char_u *last_char = NULL;
585610

586611
hlf_T hlfsNorm[3];
587612
hlf_T hlfsSel[3];
@@ -698,8 +723,14 @@ pum_redraw(void)
698723
{
699724
char_u *rt_start = rt;
700725
int cells;
726+
int used_cells = 0;
727+
char_u *old_rt = NULL;
728+
char_u *orig_rt = NULL;
701729

702730
cells = vim_strsize(rt);
731+
need_ellipsis = p_pmw > ellipsis_width
732+
&& pum_width == p_pmw
733+
&& cells > pum_width;
703734
if (cells > pum_width)
704735
{
705736
do
@@ -709,7 +740,42 @@ pum_redraw(void)
709740
MB_PTR_ADV(rt);
710741
} while (cells > pum_width);
711742

712-
if (cells < pum_width)
743+
if (need_ellipsis)
744+
{
745+
orig_rt = rt;
746+
while (*orig_rt != NUL)
747+
{
748+
char_cells = has_mbyte ? (*mb_ptr2cells)(orig_rt) : 1;
749+
if (used_cells + char_cells > ellipsis_width)
750+
break;
751+
used_cells += char_cells;
752+
MB_PTR_ADV(orig_rt);
753+
last_char = orig_rt;
754+
}
755+
756+
if (last_char != NULL)
757+
{
758+
if (used_cells < ellipsis_width)
759+
{
760+
over_cell = ellipsis_width - used_cells;
761+
MB_PTR_ADV(orig_rt);
762+
last_char = orig_rt;
763+
}
764+
kept_len = STRLEN(last_char);
765+
new_str = alloc(ellipsis_width + over_cell + kept_len + 1);
766+
if (!new_str)
767+
return;
768+
vim_memset(new_str, '.', ellipsis_width);
769+
if (over_cell > 0)
770+
vim_memset(new_str + ellipsis_width, ' ', over_cell);
771+
memcpy(new_str + ellipsis_width + over_cell, last_char, kept_len);
772+
new_str[ellipsis_width + kept_len + over_cell] = NUL;
773+
old_rt = rt_start;
774+
rt = rt_start = new_str;
775+
vim_free(old_rt);
776+
}
777+
}
778+
else if (cells < pum_width)
713779
{
714780
// Most left character requires 2-cells
715781
// but only 1 cell is available on
@@ -739,8 +805,13 @@ pum_redraw(void)
739805
{
740806
if (st != NULL)
741807
{
742-
int size = (int)STRLEN(st);
743-
int cells = (*mb_string2cells)(st, size);
808+
int size = (int)STRLEN(st);
809+
int cells = (*mb_string2cells)(st, size);
810+
int used_cells = 0;
811+
char_u *st_end = NULL;
812+
need_ellipsis = p_pmw > ellipsis_width
813+
&& pum_width == p_pmw
814+
&& col + cells > pum_col + pum_width;
744815

745816
// only draw the text that fits
746817
while (size > 0
@@ -756,6 +827,42 @@ pum_redraw(void)
756827
--cells;
757828
}
758829

830+
// Add '...' indicator if truncated due to p_pmw
831+
if (need_ellipsis)
832+
{
833+
st_end = st + size;
834+
while (st_end > st)
835+
{
836+
char_cells = has_mbyte ? (*mb_ptr2cells)(st_end) : 1;
837+
if (used_cells + char_cells > ellipsis_width)
838+
break;
839+
used_cells += char_cells;
840+
MB_PTR_BACK(st, st_end);
841+
last_char = st_end;
842+
}
843+
844+
if (last_char != NULL)
845+
{
846+
if (used_cells < ellipsis_width)
847+
{
848+
MB_PTR_BACK(st, st_end);
849+
last_char = st_end;
850+
over_cell = ellipsis_width - used_cells;
851+
}
852+
kept_len = last_char - st;
853+
new_str = alloc(ellipsis_width + over_cell + kept_len + 1);
854+
if (!new_str)
855+
return;
856+
memcpy(new_str, st, kept_len);
857+
if (over_cell > 0)
858+
vim_memset(new_str + kept_len, ' ', over_cell);
859+
vim_memset(new_str + kept_len + over_cell, '.', ellipsis_width);
860+
new_str[kept_len + ellipsis_width + over_cell] = NUL;
861+
vim_free(st);
862+
st = new_str;
863+
}
864+
}
865+
759866
if (attrs == NULL)
760867
screen_puts_len(st, size, row, col, attr);
761868
else
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
|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|_|a| @43
2+
|1|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|_|b| @43
3+
@12|1|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|_|a> @31
4+
|~+0#4040ff13&| @9| +0#0000001#e0e0e08|1|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|_|a| | +0#4040ff13#ffffff0@30
5+
|~| @9| +0#0000001#ffd7ff255|1|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|_|b| | +0#4040ff13#ffffff0@30
6+
|~| @73
7+
|~| @73
8+
|~| @73
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
|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|_|a| @43
2+
|1|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|_|b| @43
3+
@12|1|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|_|a> @31
4+
|~+0#4040ff13&| @9| +0#0000001#e0e0e08|1|2|3|4|5|6|7|.@2| +0#4040ff13#ffffff0@52
5+
|~| @9| +0#0000001#ffd7ff255|1|2|3|4|5|6|7|.@2| +0#4040ff13#ffffff0@52
6+
|~| @73
7+
|~| @73
8+
|~| @73

0 commit comments

Comments
 (0)