diff options
author | zeertzjq <zeertzjq@outlook.com> | 2025-03-28 15:37:49 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2025-03-29 21:12:32 +0800 |
commit | 62da4e2949cc906102bd768cdd40b274623822b6 (patch) | |
tree | f81120d9e4b80abd16b3ceb6c46149b550b5be18 /src | |
parent | 89bc9455543abbd98bba752367ab5f2b83943931 (diff) | |
download | rneovim-62da4e2949cc906102bd768cdd40b274623822b6.tar.gz rneovim-62da4e2949cc906102bd768cdd40b274623822b6.tar.bz2 rneovim-62da4e2949cc906102bd768cdd40b274623822b6.zip |
vim-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: vim/vim#10901
closes: vim/vim#16943
https://github.com/vim/vim/commit/88d75934c3d5bc4c406343f106e1a61638abd3a7
Co-authored-by: glepnir <glephunter@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/option_vars.h | 1 | ||||
-rw-r--r-- | src/nvim/options.lua | 15 | ||||
-rw-r--r-- | src/nvim/popupmenu.c | 109 |
3 files changed, 124 insertions, 1 deletions
diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h index 0b5d0a45b4..e624ab80ef 100644 --- a/src/nvim/option_vars.h +++ b/src/nvim/option_vars.h @@ -306,6 +306,7 @@ EXTERN char *p_csl; ///< 'completeslash' EXTERN OptInt p_pb; ///< 'pumblend' EXTERN OptInt p_ph; ///< 'pumheight' EXTERN OptInt p_pw; ///< 'pumwidth' +EXTERN OptInt p_pmw; ///< 'pummaxwidth' EXTERN char *p_com; ///< 'comments' EXTERN char *p_cpo; ///< 'cpoptions' EXTERN char *p_debug; ///< 'debug' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 2f77d0ebb7..f261abf30e 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -6426,6 +6426,21 @@ local options = { varname = 'p_ph', }, { + abbreviation = 'pmw', + defaults = 0, + desc = [=[ + Maximum width for the popup menu (|ins-completion-menu|). When zero, + there is no maximum width limit, otherwise the popup menu will never be + wider than this value. Truncated text will be indicated by "..." at the + end. Takes precedence over 'pumwidth'. + ]=], + full_name = 'pummaxwidth', + scope = { 'global' }, + short_desc = N_('maximum width of the popup menu'), + type = 'number', + varname = 'p_pmw', + }, + { abbreviation = 'pw', defaults = 15, desc = [=[ diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index d26651fb84..75f1c93ed7 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -199,6 +199,9 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i } int def_width = (int)p_pw; + if (p_pmw > 0 && def_width > p_pmw) { + def_width = (int)p_pmw; + } win_T *pvwin = NULL; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { @@ -307,6 +310,9 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i pum_compute_size(); int max_width = pum_base_width; + if (p_pmw > 0 && max_width > p_pmw) { + max_width = (int)p_pmw; + } // if there are more items than room we need a scrollbar if (pum_height < size) { @@ -339,6 +345,9 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i if (pum_width > content_width && pum_width > p_pw) { // Reduce width to fit item pum_width = MAX(content_width, (int)p_pw); + if (p_pmw > 0 && pum_width > p_pmw) { + pum_width = (int)p_pmw; + } } else if (((cursor_col - min_col > p_pw || cursor_col - min_col > max_width) && !pum_rl) || (pum_rl && (cursor_col < max_col - p_pw @@ -365,6 +374,9 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i if (pum_width < p_pw) { pum_width = (int)p_pw; + if (p_pmw > 0 && pum_width > p_pmw) { + pum_width = (int)p_pmw; + } if (pum_rl) { if (pum_width > pum_col - min_col) { pum_width = pum_col - min_col; @@ -376,6 +388,9 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i } } else if (pum_width > content_width && pum_width > p_pw) { pum_width = MAX(content_width, (int)p_pw); + if (p_pmw > 0 && pum_width > p_pmw) { + pum_width = (int)p_pmw; + } } } } else if (max_col - min_col < def_width) { @@ -386,11 +401,17 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i pum_col = min_col; } pum_width = max_col - min_col - 1; + if (p_pmw > 0 && pum_width > p_pmw) { + pum_width = (int)p_pmw; + } } else { if (max_width > p_pw) { // truncate max_width = (int)p_pw; } + if (p_pmw > 0 && max_width > p_pmw) { + max_width = (int)p_pmw; + } if (pum_rl) { pum_col = min_col + max_width - 1; } else { @@ -611,6 +632,8 @@ void pum_redraw(void) thumb_pos = (pum_first * (pum_height - thumb_height) + scroll_range / 2) / scroll_range; } + const int ellipsis_width = 3; + for (int i = 0; i < pum_height; i++) { int idx = i + pum_first; const hlf_T *const hlfs = (idx == pum_selected) ? hlfsSel : hlfsNorm; @@ -685,6 +708,9 @@ void pum_redraw(void) char *rt = reverse_text(st); char *rt_start = rt; int cells = vim_strsize(rt); + bool need_ellipsis = p_pmw > ellipsis_width + && pum_width == p_pmw + && grid_col - cells < col_off - pum_width; if (grid_col - cells < col_off - pum_width) { do { @@ -692,7 +718,41 @@ void pum_redraw(void) MB_PTR_ADV(rt); } while (grid_col - cells < col_off - pum_width); - if (grid_col - cells > col_off - pum_width) { + if (need_ellipsis) { + char *orig_rt = rt; + int used_cells = 0; + char *last_char = NULL; + while (*orig_rt != NUL) { + int char_cells = utf_ptr2cells(orig_rt); + 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) { + int over_cell = 0; + if (used_cells < ellipsis_width) { + over_cell = ellipsis_width - used_cells; + MB_PTR_ADV(orig_rt); + last_char = orig_rt; + } + size_t kept_len = strlen(last_char); + char *new_str = xmalloc((size_t)ellipsis_width + (size_t)over_cell + + kept_len + 1); + memset(new_str, '.', (size_t)ellipsis_width); + if (over_cell > 0) { + memset(new_str + ellipsis_width, ' ', (size_t)over_cell); + } + memcpy(new_str + ellipsis_width + over_cell, last_char, kept_len); + new_str[(size_t)ellipsis_width + kept_len + (size_t)over_cell] = NUL; + char *old_rt = rt_start; + rt = rt_start = new_str; + xfree(old_rt); + } + } else if (grid_col - cells > col_off - pum_width) { // Most left character requires 2-cells but only 1 cell is available on // screen. Put a '<' on the left of the pum item. *(--rt) = '<'; @@ -710,6 +770,53 @@ void pum_redraw(void) xfree(st); grid_col -= width; } else { + size_t size = strlen(st); + int cells = (int)mb_string2cells_len(st, size); + bool need_ellipsis = p_pmw > ellipsis_width + && pum_width == p_pmw + && grid_col + cells > col_off + pum_width; + + // Add '...' indicator if truncated due to p_pmw + if (need_ellipsis) { + while (size > 0 && grid_col + cells > col_off + pum_width) { + size--; + size -= (size_t)utf_head_off(st, st + size); + cells -= utf_ptr2cells(st + size); + } + char *st_end = st + size; + int used_cells = 0; + char *last_char = NULL; + while (st_end > st) { + int char_cells = utf_ptr2cells(st_end); + 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) { + int over_cell = 0; + if (used_cells < ellipsis_width) { + MB_PTR_BACK(st, st_end); + last_char = st_end; + over_cell = ellipsis_width - used_cells; + } + size_t kept_len = (size_t)(last_char - st); + char *new_str = xmalloc((size_t)ellipsis_width + (size_t)over_cell + + kept_len + 1); + memcpy(new_str, st, kept_len); + if (over_cell > 0) { + memset(new_str + kept_len, ' ', (size_t)over_cell); + } + memset(new_str + kept_len + over_cell, '.', (size_t)ellipsis_width); + new_str[kept_len + (size_t)ellipsis_width + (size_t)over_cell] = NUL; + xfree(st); + st = new_str; + } + } + if (attrs == NULL) { grid_line_puts(grid_col, st, -1, attr); } else { |