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 <glephunter@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/option.h b/src/option.h
index 5714e0c..0b568f1 100644
--- a/src/option.h
+++ b/src/option.h
@@ -545,6 +545,7 @@
#endif
EXTERN long p_ph; // 'pumheight'
EXTERN long p_pw; // 'pumwidth'
+EXTERN long p_pmw; // 'pummaxwidth'
EXTERN char_u *p_com; // 'comments'
EXTERN char_u *p_cpo; // 'cpoptions'
#ifdef FEAT_CSCOPE
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 3621635..b6b5d49 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -2021,6 +2021,9 @@
{"pumheight", "ph", P_NUM|P_VI_DEF,
(char_u *)&p_ph, PV_NONE, NULL, NULL,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},
+ {"pummaxwidth", "pmw", P_NUM|P_VI_DEF,
+ (char_u *)&p_pmw, PV_NONE, NULL, NULL,
+ {(char_u *)0L, (char_u *)0L} SCTX_INIT},
{"pumwidth", "pw", P_NUM|P_VI_DEF,
(char_u *)&p_pw, PV_NONE, NULL, NULL,
{(char_u *)15L, (char_u *)15L} SCTX_INIT},
diff --git a/src/popupmenu.c b/src/popupmenu.c
index 443223d..d69c7bd 100644
--- a/src/popupmenu.c
+++ b/src/popupmenu.c
@@ -115,6 +115,8 @@
do
{
def_width = p_pw;
+ if (p_pmw > 0 && def_width > p_pmw)
+ def_width = p_pmw;
above_row = 0;
below_row = cmdline_row;
@@ -226,6 +228,8 @@
pum_size = size;
pum_compute_size();
max_width = pum_base_width;
+ if (p_pmw > 0 && max_width > p_pmw)
+ max_width = p_pmw;
// Calculate column
if (State == MODE_CMDLINE)
@@ -275,8 +279,12 @@
content_width = max_width + pum_kind_width + pum_extra_width + 1;
if (pum_width > content_width && pum_width > p_pw)
+ {
// Reduce width to fit item
- pum_width = MAX(content_width , p_pw);
+ pum_width = MAX(content_width, p_pw);
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
+ }
else if (((cursor_col > p_pw || cursor_col > max_width)
#ifdef FEAT_RIGHTLEFT
&& !pum_rl)
@@ -313,6 +321,8 @@
if (pum_width < p_pw)
{
pum_width = p_pw;
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
{
@@ -327,7 +337,11 @@
}
}
else if (pum_width > content_width && pum_width > p_pw)
+ {
pum_width = MAX(content_width, p_pw);
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
+ }
}
}
@@ -341,11 +355,15 @@
#endif
pum_col = 0;
pum_width = Columns - 1;
+ if (p_pmw > 0 && pum_width > p_pmw)
+ pum_width = p_pmw;
}
else
{
if (max_width > p_pw)
max_width = p_pw; // truncate
+ if (p_pmw > 0 && max_width > p_pmw)
+ max_width = p_pmw;
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
pum_col = max_width - 1;
@@ -582,6 +600,13 @@
int last_isabbr = FALSE;
int orig_attr = -1;
int scroll_range = pum_size - pum_height;
+ int need_ellipsis = FALSE;
+ int char_cells = 0;
+ int ellipsis_width = 3;
+ int over_cell = 0;
+ char_u *new_str = NULL;
+ int kept_len = 0;
+ char_u *last_char = NULL;
hlf_T hlfsNorm[3];
hlf_T hlfsSel[3];
@@ -698,8 +723,14 @@
{
char_u *rt_start = rt;
int cells;
+ int used_cells = 0;
+ char_u *old_rt = NULL;
+ char_u *orig_rt = NULL;
cells = vim_strsize(rt);
+ need_ellipsis = p_pmw > ellipsis_width
+ && pum_width == p_pmw
+ && cells > pum_width;
if (cells > pum_width)
{
do
@@ -709,7 +740,42 @@
MB_PTR_ADV(rt);
} while (cells > pum_width);
- if (cells < pum_width)
+ if (need_ellipsis)
+ {
+ orig_rt = rt;
+ while (*orig_rt != NUL)
+ {
+ char_cells = has_mbyte ? (*mb_ptr2cells)(orig_rt) : 1;
+ if (used_cells + char_cells > ellipsis_width)
+ break;
+ used_cells += char_cells;
+ MB_PTR_ADV(orig_rt);
+ last_char = orig_rt;
+ }
+
+ if (last_char != NULL)
+ {
+ if (used_cells < ellipsis_width)
+ {
+ over_cell = ellipsis_width - used_cells;
+ MB_PTR_ADV(orig_rt);
+ last_char = orig_rt;
+ }
+ kept_len = STRLEN(last_char);
+ new_str = alloc(ellipsis_width + over_cell + kept_len + 1);
+ if (!new_str)
+ return;
+ vim_memset(new_str, '.', ellipsis_width);
+ if (over_cell > 0)
+ vim_memset(new_str + ellipsis_width, ' ', over_cell);
+ memcpy(new_str + ellipsis_width + over_cell, last_char, kept_len);
+ new_str[ellipsis_width + kept_len + over_cell] = NUL;
+ old_rt = rt_start;
+ rt = rt_start = new_str;
+ vim_free(old_rt);
+ }
+ }
+ else if (cells < pum_width)
{
// Most left character requires 2-cells
// but only 1 cell is available on
@@ -739,8 +805,13 @@
{
if (st != NULL)
{
- int size = (int)STRLEN(st);
- int cells = (*mb_string2cells)(st, size);
+ int size = (int)STRLEN(st);
+ int cells = (*mb_string2cells)(st, size);
+ int used_cells = 0;
+ char_u *st_end = NULL;
+ need_ellipsis = p_pmw > ellipsis_width
+ && pum_width == p_pmw
+ && col + cells > pum_col + pum_width;
// only draw the text that fits
while (size > 0
@@ -756,6 +827,42 @@
--cells;
}
+ // Add '...' indicator if truncated due to p_pmw
+ if (need_ellipsis)
+ {
+ st_end = st + size;
+ while (st_end > st)
+ {
+ char_cells = has_mbyte ? (*mb_ptr2cells)(st_end) : 1;
+ if (used_cells + char_cells > ellipsis_width)
+ break;
+ used_cells += char_cells;
+ MB_PTR_BACK(st, st_end);
+ last_char = st_end;
+ }
+
+ if (last_char != NULL)
+ {
+ if (used_cells < ellipsis_width)
+ {
+ MB_PTR_BACK(st, st_end);
+ last_char = st_end;
+ over_cell = ellipsis_width - used_cells;
+ }
+ kept_len = last_char - st;
+ new_str = alloc(ellipsis_width + over_cell + kept_len + 1);
+ if (!new_str)
+ return;
+ memcpy(new_str, st, kept_len);
+ if (over_cell > 0)
+ vim_memset(new_str + kept_len, ' ', over_cell);
+ vim_memset(new_str + kept_len + over_cell, '.', ellipsis_width);
+ new_str[kept_len + ellipsis_width + over_cell] = NUL;
+ vim_free(st);
+ st = new_str;
+ }
+ }
+
if (attrs == NULL)
screen_puts_len(st, size, row, col, attr);
else
diff --git a/src/testdir/dumps/Test_pum_maxwidth_01.dump b/src/testdir/dumps/Test_pum_maxwidth_01.dump
new file mode 100644
index 0000000..a836ab0
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_01.dump
@@ -0,0 +1,8 @@
+|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
+|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
+@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
+|~+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
+|~| @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
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/dumps/Test_pum_maxwidth_02.dump b/src/testdir/dumps/Test_pum_maxwidth_02.dump
new file mode 100644
index 0000000..427ea9f
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_02.dump
@@ -0,0 +1,8 @@
+|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
+|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
+@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
+|~+0#4040ff13&| @9| +0#0000001#e0e0e08|1|2|3|4|5|6|7|.@2| +0#4040ff13#ffffff0@52
+|~| @9| +0#0000001#ffd7ff255|1|2|3|4|5|6|7|.@2| +0#4040ff13#ffffff0@52
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/dumps/Test_pum_maxwidth_03.dump b/src/testdir/dumps/Test_pum_maxwidth_03.dump
new file mode 100644
index 0000000..e303108
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_03.dump
@@ -0,0 +1,8 @@
+|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
+|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
+@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
+|~+0#4040ff13&| @9| +0#0000001#e0e0e08|1|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|.@2| +0#4040ff13#ffffff0@42
+|~| @9| +0#0000001#ffd7ff255|1|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|.@2| +0#4040ff13#ffffff0@42
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/dumps/Test_pum_maxwidth_04.dump b/src/testdir/dumps/Test_pum_maxwidth_04.dump
new file mode 100644
index 0000000..a6d257e
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_04.dump
@@ -0,0 +1,8 @@
+|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
+|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
+@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
+|~+0#4040ff13&| @9| +0#0000001#e0e0e08|1|2|3|4|5|.@2| +0#4040ff13#ffffff0@54
+|~| @9| +0#0000001#ffd7ff255|1|2|3|4|5|.@2| +0#4040ff13#ffffff0@54
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/dumps/Test_pum_maxwidth_05.dump b/src/testdir/dumps/Test_pum_maxwidth_05.dump
new file mode 100644
index 0000000..0dd6a39
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_05.dump
@@ -0,0 +1,8 @@
+|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|_|1|2|3|4|5|6|7|8|9|_|1|2|3|4|5|6|7|8|9|_| | +0#4040ff13#ffffff0@43
+|一*0#0000001#ffd7ff255|二|三|四|五|六|七|八|九|十| +&@10| +0#4040ff13#ffffff0@43
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/dumps/Test_pum_maxwidth_06.dump b/src/testdir/dumps/Test_pum_maxwidth_06.dump
new file mode 100644
index 0000000..7321870
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_06.dump
@@ -0,0 +1,8 @@
+|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|.@2| +0#4040ff13#ffffff0@64
+|一*0#0000001#ffd7ff255|二|三| +&|.@2| +0#4040ff13#ffffff0@64
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/dumps/Test_pum_maxwidth_07.dump b/src/testdir/dumps/Test_pum_maxwidth_07.dump
new file mode 100644
index 0000000..8e81d31
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_07.dump
@@ -0,0 +1,8 @@
+| +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@2|7|6|5|4|3|2|1
+| +0#4040ff13#ffffff0@64|.+0#0000001#ffd7ff255@2| |三*&|二|一
+| +0#4040ff13#ffffff0@73|~
+| @73|~
+| @73|~
+| @73|~
+| @73|~
diff --git a/src/testdir/dumps/Test_pum_maxwidth_08.dump b/src/testdir/dumps/Test_pum_maxwidth_08.dump
new file mode 100644
index 0000000..8681e5f
--- /dev/null
+++ b/src/testdir/dumps/Test_pum_maxwidth_08.dump
@@ -0,0 +1,8 @@
+|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| +0#4040ff13#ffffff0@72
+|一*0#0000001#ffd7ff255| +0#4040ff13#ffffff0@72
+|~| @73
+|~| @73
+|~| @73
+|~| @73
+|~| @73
diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim
index e599a8d..94839b5 100644
--- a/src/testdir/test_popup.vim
+++ b/src/testdir/test_popup.vim
@@ -1986,4 +1986,81 @@
call StopVimInTerminal(buf)
endfunc
+func Test_pum_maxwidth()
+ CheckScreendump
+
+ let lines =<< trim END
+ 123456789_123456789_123456789_a
+ 123456789_123456789_123456789_b
+ 123
+ END
+ call writefile(lines, 'Xtest', 'D')
+ let buf = RunVimInTerminal('Xtest', {})
+
+ call term_sendkeys(buf, "G\"zyy")
+ call term_sendkeys(buf, "A\<C-N>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_01', {'rows': 8})
+ call term_sendkeys(buf, "\<Esc>3Gdd\"zp")
+
+ call term_sendkeys(buf, ":set pummaxwidth=10\<CR>")
+ call term_sendkeys(buf, "GA\<C-N>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_02', {'rows': 8})
+ call term_sendkeys(buf, "\<Esc>3Gdd\"zp")
+
+ call term_sendkeys(buf, ":set pummaxwidth=20\<CR>")
+ call term_sendkeys(buf, "GA\<C-N>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_03', {'rows': 8})
+ call term_sendkeys(buf, "\<Esc>3Gdd\"zp")
+
+ call term_sendkeys(buf, ":set pumwidth=20 pummaxwidth=8\<CR>")
+ call term_sendkeys(buf, "GA\<C-N>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_04', {'rows': 8})
+ call term_sendkeys(buf, "\<Esc>3Gdd\"zp")
+
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_pum_maxwidth_multibyte()
+ CheckScreendump
+
+ let lines =<< trim END
+ func Omni_test(findstart, base)
+ if a:findstart
+ return col(".")
+ endif
+ return [
+ \ #{word: "123456789_123456789_123456789_"},
+ \ #{word: "一二三四五六七八九十"},
+ \ ]
+ endfunc
+ set omnifunc=Omni_test
+ END
+ call writefile(lines, 'Xtest', 'D')
+ let buf = RunVimInTerminal('-S Xtest', {})
+ call TermWait(buf)
+
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_05', {'rows': 8})
+ call term_sendkeys(buf, "\<ESC>")
+
+ call term_sendkeys(buf, ":set pummaxwidth=10\<CR>")
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_06', {'rows': 8})
+ call term_sendkeys(buf, "\<ESC>")
+
+ if has('rightleft')
+ call term_sendkeys(buf, ":set rightleft\<CR>")
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_07', {'rows': 8})
+ call term_sendkeys(buf, "\<Esc>:set norightleft\<CR>")
+ endif
+
+ call term_sendkeys(buf, ":set pummaxwidth=2\<CR>")
+ call term_sendkeys(buf, "S\<C-X>\<C-O>")
+ call VerifyScreenDump(buf, 'Test_pum_maxwidth_08', {'rows': 8})
+ call term_sendkeys(buf, "\<ESC>")
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 7339d58..cb559cf 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1250,
+/**/
1249,
/**/
1248,