0
0
mirror of https://github.com/vim/vim.git synced 2025-07-04 23:07:33 -04:00

Merge bc8b161ddc8814beffd5edf38ebc6a06ba3e4f93 into a494ce1c64a2637719a5c1339abf19ec7c48089c

This commit is contained in:
glepnir 2025-07-04 10:24:00 +02:00 committed by GitHub
commit c905f41961
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 241 additions and 15 deletions

View File

@ -4583,7 +4583,8 @@ A jump table for the options with a short description can be found at |Q_op|.
A:DiffAdd,C:DiffChange,D:DiffDelete,
T:DiffText,E:DiffTextAdd,>:SignColumn,
-:Conceal,B:SpellBad,P:SpellCap,
R:SpellRare, L:SpellLocal,+:Pmenu,
R:SpellRare, L:SpellLocal,
+:Pmenu,I:PmenuBorder,
=:PmenuSel, k:PmenuMatch,<:PmenuMatchSel,
[:PmenuKind,]:PmenuKindSel,
{:PmenuExtra,}:PmenuExtraSel,
@ -6674,6 +6675,29 @@ A jump table for the options with a short description can be found at |Q_op|.
global
When on a ":" prompt is used in Ex mode.
*'pumborder'* *'pbr'*
'pumborder' 'pbr' string (default "")
global
When non-empty, specifies the border style used for the
|ins-completion-menu| during completion. This affects how the border
around the popup menu is drawn.
Possible values are:
"single" a single-line border
"double" a double-line border
"rounded" a rounded border using box-drawing characters
"solid" a solid block-style border
"shadow" a shadow-like border style
Alternatively, a custom border style can be defined by specifying
a comma-separated list of eight border characters. The expected
order is as follows:
Top-left corner, Top border, Top-right corner, Right border
Bot-right corner, Bot border, Bot-left corner, Left border
Example: >
:set pumborder=rounded
:set pumborder=+,-,+,\|,+,-,+,\|
<
*'pumheight'* *'ph'*
'pumheight' 'ph' number (default 0)
global

View File

@ -5915,6 +5915,8 @@ NonText '@' at the end of the window, "<<<" at the start of the window
Normal Normal text.
*hl-Pmenu*
Pmenu Popup menu: Normal item.
*hl-PmenuBorder*
PmenuBorder Popup menu: Border character.
*hl-PmenuSel*
PmenuSel Popup menu: Selected item.
*hl-PmenuKind*

View File

@ -841,6 +841,7 @@ $quote eval.txt /*$quote*
'patchexpr' options.txt /*'patchexpr'*
'patchmode' options.txt /*'patchmode'*
'path' options.txt /*'path'*
'pbr' options.txt /*'pbr'*
'pdev' options.txt /*'pdev'*
'penc' options.txt /*'penc'*
'perldll' options.txt /*'perldll'*
@ -870,6 +871,7 @@ $quote eval.txt /*$quote*
'printoptions' options.txt /*'printoptions'*
'prompt' options.txt /*'prompt'*
'pt' options.txt /*'pt'*
'pumborder' options.txt /*'pumborder'*
'pumheight' options.txt /*'pumheight'*
'pummaxwidth' options.txt /*'pummaxwidth'*
'pumwidth' options.txt /*'pumwidth'*
@ -8280,6 +8282,7 @@ hl-MsgArea syntax.txt /*hl-MsgArea*
hl-NonText syntax.txt /*hl-NonText*
hl-Normal syntax.txt /*hl-Normal*
hl-Pmenu syntax.txt /*hl-Pmenu*
hl-PmenuBorder syntax.txt /*hl-PmenuBorder*
hl-PmenuExtra syntax.txt /*hl-PmenuExtra*
hl-PmenuExtraSel syntax.txt /*hl-PmenuExtraSel*
hl-PmenuKind syntax.txt /*hl-PmenuKind*

View File

@ -260,6 +260,7 @@ static char *(highlight_init_both[]) = {
"default link CursorLineSign SignColumn",
"default link CursorLineFold FoldColumn",
"default link CurSearch Search",
"default link PmenuBorder Pmenu",
"default link PmenuKind Pmenu",
"default link PmenuKindSel PmenuSel",
"default link PmenuMatch Pmenu",

View File

@ -521,6 +521,7 @@ EXTERN unsigned cfc_flags; // flags from "completefuzzycollect"
EXTERN char_u *p_cia; // 'completeitemalign'
EXTERN unsigned cia_flags; // order flags of 'completeitemalign'
EXTERN char_u *p_cot; // 'completeopt'
EXTERN char_u *p_pbr; // 'pumborder'
EXTERN unsigned cot_flags; // flags from 'completeopt'
// Keep in sync with p_cot_values in optionstr.c
#define COT_MENU 0x001

View File

@ -2058,6 +2058,9 @@ static struct vimoption options[] =
{"prompt", NULL, P_BOOL|P_VI_DEF,
(char_u *)&p_prompt, PV_NONE, NULL, NULL,
{(char_u *)TRUE, (char_u *)0L} SCTX_INIT},
{"pumborder", "pbr", P_STRING|P_VI_DEF,
(char_u *)&p_pbr, PV_NONE, did_set_pumborder, NULL,
{(char_u *)"", (char_u *)0L} SCTX_INIT},
{"pumheight", "ph", P_NUM|P_VI_DEF,
(char_u *)&p_ph, PV_NONE, NULL, NULL,
{(char_u *)0L, (char_u *)0L} SCTX_INIT},

View File

@ -3338,6 +3338,17 @@ did_set_optexpr(optset_T *args)
}
#endif
/*
* The 'pumborder' option is changed
*/
char *
did_set_pumborder(optset_T *args UNUSED)
{
if (!pum_parse_border())
return e_invalid_argument;
return NULL;
}
/*
* The 'pastetoggle' option is changed.
*/

View File

@ -39,6 +39,8 @@ static int pum_win_height;
static int pum_win_col;
static int pum_win_wcol;
static int pum_win_width;
static int pum_border_chars[8];
static int pum_has_border = FALSE;
// Some parts are not updated when a popup menu is visible. Setting this flag
// makes pum_visible() return FALSE even when there is a popup menu.
@ -104,6 +106,7 @@ pum_display(
int content_width;
int right_edge_col;
int redo_count = 0;
int border_cells = pum_has_border ? 2 : 0;
#if defined(FEAT_QUICKFIX)
win_T *pvwin;
#endif
@ -161,7 +164,7 @@ pum_display(
// Put the pum below "pum_win_row" if possible. If there are few lines
// decide on where there is more room.
if (pum_win_row + 2 >= below_row - pum_height
if (pum_win_row + 2 + border_cells >= below_row - pum_height
&& pum_win_row - above_row > (below_row - above_row) / 2)
{
// pum above "pum_win_row"
@ -187,6 +190,14 @@ pum_display(
pum_row += pum_height - p_ph;
pum_height = p_ph;
}
if (pum_has_border && border_cells + pum_row + pum_height > pum_win_row)
{
if (pum_row < 2)
pum_height -= border_cells;
else
pum_row -= border_cells;
}
}
else
{
@ -207,6 +218,10 @@ pum_display(
pum_height = MIN(below_row - pum_row, size);
if (p_ph > 0 && pum_height > p_ph)
pum_height = p_ph;
if ((State == MODE_CMDLINE)
&& pum_row + pum_height + border_cells >= cmdline_row)
pum_height -= border_cells;
}
// don't display when we only have room for one line
@ -375,6 +390,9 @@ pum_display(
pum_width = max_width - pum_scrollbar;
}
if (pum_col + border_cells + pum_width > Columns)
pum_col -= border_cells;
// Set selected item and redraw. If the window size changed need to
// redo the positioning. Limit this to two times, when there is not
// much room the window size will keep changing.
@ -872,6 +890,148 @@ pum_draw_scrollbar(
screen_putchar(' ', row, pum_col + pum_width, attr);
}
int
pum_parse_border(void)
{
int i;
char_u *p = p_pbr;
char_u *next = NULL;
int this_char;
int comb[MAX_MCO];
char_u buf[10];
int len;
int tmp[8];
struct {
char_u *name;
int c[8];
} defaults[] = {
{ (char_u *)"double", { 0x2554, 0x2550, 0x2557, 0x2551,
0x255D, 0x2550, 0x255A, 0x2551 } },
{ (char_u *)"single", { 0x250C, 0x2500, 0x2510, 0x2502,
0x2518, 0x2500, 0x2514, 0x2502 } },
{ (char_u *)"rounded", { 0x256D, 0x2500, 0x256E, 0x2502,
0x256F, 0x2500, 0x2570, 0x2502 } },
{ (char_u *)"bold", { 0x250F, 0x2501, 0x2513, 0x2503,
0x251B, 0x2501, 0x2517, 0x2503 } },
{ (char_u *)"solid", { 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20 } },
};
if (*p_pbr == NUL)
{
pum_has_border = FALSE;
return TRUE;
}
for (i = 0; i < 5; i++)
{
if (STRCMP(p_pbr, defaults[i].name) == 0)
{
memcpy(pum_border_chars, defaults[i].c, 8 * sizeof(int));
pum_has_border = TRUE;
return TRUE;
}
}
for (i = 0; i < 8; i++)
{
next = vim_strchr(p, ',');
if (next)
{
len = (int)(next - p);
if (len > 9)
len = 9;
vim_strncpy(buf, p, len);
buf[len] = NUL;
p = next + 1;
}
else
{
vim_strncpy(buf, p, 9);
buf[9] = NUL;
p += STRLEN(buf);
}
this_char = utfc_ptr2char(buf, comb);
if (!vim_isprintc(this_char))
{
pum_has_border = FALSE;
return FALSE;
}
tmp[i] = this_char;
}
if (*p != NUL)
{
pum_has_border = FALSE;
return FALSE;
}
memcpy(pum_border_chars, tmp, 8 * sizeof(int));
pum_has_border = TRUE;
return TRUE;
}
static void
pum_draw_border(int *border_char, int thumb_pos, int thumb_height)
{
int i;
int row = pum_row;
int col = pum_col;
int attr = syn_name2attr((char_u *)"PmenuBorder");
int width = pum_width - (State & MODE_CMDLINE ? 1 : 0);
int height = pum_height;
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
{
// topright leftright botright botleft
screen_putchar(border_char[2], row, col + 1, attr);
screen_putchar(border_char[0], row, col - width, attr);
screen_putchar(border_char[4], row + height + 1, col + 1, attr);
screen_putchar(border_char[6], row + height + 1, col - width, attr);
// top bot
for (i = 0; i < width; i++)
{
screen_putchar(border_char[1], row, col - i, attr);
screen_putchar(border_char[5], row + height + 1, col - i, attr);
}
// left right
for (i = 1; i < height + 1; i++)
{
screen_putchar(border_char[3], row + i, col + 1, attr);
if (!pum_scrollbar || i < thumb_pos || i >= thumb_pos + thumb_height)
screen_putchar(border_char[7], row + i, col - width, attr);
}
}
else
#endif
{
// topleft topright botleft botright
screen_putchar(border_char[0], row, col, attr);
screen_putchar(border_char[2], row, col + width, attr);
screen_putchar(border_char[6], row + height + 1, col, attr);
screen_putchar(border_char[4], row + height + 1, col + width, attr);
// top bot
for (i = 1; i < width; i++)
{
screen_putchar(border_char[1], row, col + i, attr);
screen_putchar(border_char[5], row + height + 1, col + i, attr);
}
// left right
for (i = 1; i < height + 1; i++)
{
screen_putchar(border_char[7], row + i, col, attr);
if (!pum_scrollbar || i - 1 < thumb_pos || i - 1 >= thumb_pos + thumb_height)
screen_putchar(border_char[3], row + i, col + width, attr);
}
}
}
/*
* Redraw the popup menu, using "pum_first" and "pum_selected".
*/
@ -898,7 +1058,9 @@ pum_redraw(void)
int basic_width; // first item width
int last_isabbr = FALSE;
int orig_attr = -1;
int scroll_range = pum_size - pum_height;
int border_cells = pum_has_border ? 2 : 0;
int scroll_range = pum_size - pum_height + border_cells;
int col_off = pum_has_border > 0 ? 1 : 0;
hlf_T hlfsNorm[3];
hlf_T hlfsSel[3];
@ -940,6 +1102,9 @@ pum_redraw(void)
screen_zindex = POPUPMENU_ZINDEX;
#endif
if (pum_has_border > 0)
++row;
for (i = 0; i < pum_height; ++i)
{
idx = i + pum_first;
@ -947,21 +1112,31 @@ pum_redraw(void)
hlf = hlfs[0]; // start with "word" highlight
attr = highlight_attr[hlf];
// prepend a space if there is room
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
if (!pum_has_border)
{
if (pum_col < curwin->w_wincol + curwin->w_width - 1)
screen_putchar(' ', row, pum_col + 1, attr);
}
else
// prepend a space if there is room
#ifdef FEAT_RIGHTLEFT
if (pum_rl)
{
if (pum_col < curwin->w_wincol + curwin->w_width - 1)
screen_putchar(' ', row, pum_col + 1, attr);
}
else
#endif
if (pum_col > 0)
screen_putchar(' ', row, pum_col - 1, attr);
if (pum_col > 0)
screen_putchar(' ', row, pum_col - 1, attr);
}
// Display each entry, use two spaces for a Tab.
// Do this 3 times and order from p_cia
col = pum_col;
if (pum_has_border > 0)
{
#ifdef FEAT_RIGHTLEFT
if (!pum_rl)
#endif
++col;
}
totwidth = 0;
pum_align_order(order);
basic_width = items_width_array[order[0]];
@ -1005,9 +1180,9 @@ pum_redraw(void)
else
#endif
{
screen_fill(row, row + 1, col, pum_col + basic_width + n,
screen_fill(row, row + 1, col, pum_col + basic_width + n + col_off,
' ', ' ', orig_attr);
col = pum_col + basic_width + n;
col = pum_col + basic_width + n + col_off;
}
totwidth = basic_width + n;
}
@ -1021,10 +1196,12 @@ pum_redraw(void)
screen_fill(row, row + 1, col, pum_col + pum_width, ' ', ' ',
orig_attr);
pum_draw_scrollbar(row, i, thumb_pos, thumb_height);
++row;
}
if (pum_has_border && pum_window != NULL)
pum_draw_border(pum_border_chars, thumb_pos, thumb_height);
#ifdef FEAT_PROP_POPUP
screen_zindex = 0;
#endif

View File

@ -208,4 +208,5 @@ int check_ff_value(char_u *p);
void save_clear_shm_value(void);
void restore_shm_value(void);
void export_myvimdir(void);
char *did_set_pumborder(optset_T *args);
/* vim: set ft=c : */

View File

@ -17,4 +17,5 @@ void ui_post_balloon(char_u *mesg, list_T *list);
void ui_may_remove_balloon(void);
void pum_show_popupmenu(vimmenu_T *menu);
void pum_make_popup(char_u *path_name, int use_mouse_pos);
int pum_parse_border(void);
/* vim: set ft=c : */

View File

@ -275,6 +275,8 @@ let test_values = {
\ ['xxx', 'xxx,c:yes', 'xxx:', 'xxx:,c:yes']],
\ 'printoptions': [['', 'header:0', 'left:10pc,top:5pc'],
\ ['xxx', 'header:-1']],
\ 'pumborder': [['', 'single', 'rounded', '+,-,+,\|,+,-,+,\|'],
\ ['xxx', '+,-,+,\|,+,-,+,']],
\ 'scrollopt': [['', 'ver', 'hor', 'jump', 'ver,hor'], ['xxx']],
\ 'renderoptions': [[''], ['xxx']],
\ 'rightleftcmd': [['search'], ['xxx']],