mirror of
https://github.com/neovim/neovim.git
synced 2025-10-12 12:56:04 +00:00
feat(ui): 'pumborder' (popup menu border) #25541
Problem: Popup menu cannot have a border. Solution: Support 'pumborder' option. Generalize `win_redr_border` to `grid_redr_border`, which redraws border for window grid and pum grid.
This commit is contained in:
@@ -4908,6 +4908,12 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
<
|
<
|
||||||
UI-dependent. Works best with RGB colors. 'termguicolors'
|
UI-dependent. Works best with RGB colors. 'termguicolors'
|
||||||
|
|
||||||
|
*'pumborder'*
|
||||||
|
'pumborder' string (default "")
|
||||||
|
global
|
||||||
|
Defines the default border style of popupmenu windows. Same as
|
||||||
|
'winborder'.
|
||||||
|
|
||||||
*'pumheight'* *'ph'*
|
*'pumheight'* *'ph'*
|
||||||
'pumheight' 'ph' number (default 0)
|
'pumheight' 'ph' number (default 0)
|
||||||
global
|
global
|
||||||
|
7
runtime/lua/vim/_meta/options.lua
generated
7
runtime/lua/vim/_meta/options.lua
generated
@@ -5129,6 +5129,13 @@ vim.o.pb = vim.o.pumblend
|
|||||||
vim.go.pumblend = vim.o.pumblend
|
vim.go.pumblend = vim.o.pumblend
|
||||||
vim.go.pb = vim.go.pumblend
|
vim.go.pb = vim.go.pumblend
|
||||||
|
|
||||||
|
--- Defines the default border style of popupmenu windows. Same as
|
||||||
|
--- 'winborder'.
|
||||||
|
---
|
||||||
|
--- @type string
|
||||||
|
vim.o.pumborder = ""
|
||||||
|
vim.go.pumborder = vim.o.pumborder
|
||||||
|
|
||||||
--- Maximum number of items to show in the popup menu
|
--- Maximum number of items to show in the popup menu
|
||||||
--- (`ins-completion-menu`). Zero means "use available screen space".
|
--- (`ins-completion-menu`). Zero means "use available screen space".
|
||||||
---
|
---
|
||||||
|
@@ -961,7 +961,7 @@ static bool parse_bordertext_pos(win_T *wp, String bordertext_pos, BorderTextTyp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_border_style(Object style, WinConfig *fconfig, Error *err)
|
void parse_border_style(Object style, WinConfig *fconfig, Error *err)
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -1079,14 +1079,14 @@ static void generate_api_error(win_T *wp, const char *attribute, Error *err)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a border style name or custom (comma-separated) style.
|
/// Parses a border style name or custom (comma-separated) style.
|
||||||
bool parse_winborder(WinConfig *fconfig, Error *err)
|
bool parse_winborder(WinConfig *fconfig, const char *border_opt, Error *err)
|
||||||
{
|
{
|
||||||
if (!fconfig) {
|
if (!fconfig) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Object style = OBJECT_INIT;
|
Object style = OBJECT_INIT;
|
||||||
|
|
||||||
if (strchr(p_winborder, ',')) {
|
if (strchr(border_opt, ',')) {
|
||||||
Array border_chars = ARRAY_DICT_INIT;
|
Array border_chars = ARRAY_DICT_INIT;
|
||||||
char *p = p_winborder;
|
char *p = p_winborder;
|
||||||
char part[MAX_SCHAR_SIZE] = { 0 };
|
char part[MAX_SCHAR_SIZE] = { 0 };
|
||||||
@@ -1364,7 +1364,7 @@ static bool parse_win_config(win_T *wp, Dict(win_config) *config, WinConfig *fco
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (*p_winborder != NUL && (wp == NULL || !wp->w_floating)
|
} else if (*p_winborder != NUL && (wp == NULL || !wp->w_floating)
|
||||||
&& !parse_winborder(fconfig, err)) {
|
&& !parse_winborder(fconfig, p_winborder, err)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -111,6 +111,7 @@
|
|||||||
#include "nvim/statusline.h"
|
#include "nvim/statusline.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/syntax.h"
|
#include "nvim/syntax.h"
|
||||||
|
#include "nvim/syntax_defs.h"
|
||||||
#include "nvim/terminal.h"
|
#include "nvim/terminal.h"
|
||||||
#include "nvim/types_defs.h"
|
#include "nvim/types_defs.h"
|
||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
@@ -657,7 +658,8 @@ int update_screen(void)
|
|||||||
win_grid_alloc(wp);
|
win_grid_alloc(wp);
|
||||||
|
|
||||||
if (wp->w_redr_border || wp->w_redr_type >= UPD_NOT_VALID) {
|
if (wp->w_redr_border || wp->w_redr_type >= UPD_NOT_VALID) {
|
||||||
win_redr_border(wp);
|
grid_draw_border(&wp->w_grid_alloc, wp->w_config, wp->w_border_adj, (int)wp->w_p_winbl,
|
||||||
|
wp->w_ns_hl_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wp->w_redr_type != 0) {
|
if (wp->w_redr_type != 0) {
|
||||||
@@ -743,112 +745,6 @@ void end_search_hl(void)
|
|||||||
screen_search_hl.rm.regprog = NULL;
|
screen_search_hl.rm.regprog = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_redr_bordertext(win_T *wp, VirtText vt, int col, BorderTextType bt)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < kv_size(vt);) {
|
|
||||||
int attr = -1;
|
|
||||||
char *text = next_virt_text_chunk(vt, &i, &attr);
|
|
||||||
if (text == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (attr == -1) { // No highlight specified.
|
|
||||||
attr = wp->w_ns_hl_attr[bt == kBorderTextTitle ? HLF_BTITLE : HLF_BFOOTER];
|
|
||||||
}
|
|
||||||
attr = hl_apply_winblend(wp, attr);
|
|
||||||
col += grid_line_puts(col, text, -1, attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int win_get_bordertext_col(int total_col, int text_width, AlignTextPos align)
|
|
||||||
{
|
|
||||||
switch (align) {
|
|
||||||
case kAlignLeft:
|
|
||||||
return 1;
|
|
||||||
case kAlignCenter:
|
|
||||||
return MAX((total_col - text_width) / 2 + 1, 1);
|
|
||||||
case kAlignRight:
|
|
||||||
return MAX(total_col - text_width + 1, 1);
|
|
||||||
}
|
|
||||||
UNREACHABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void win_redr_border(win_T *wp)
|
|
||||||
{
|
|
||||||
wp->w_redr_border = false;
|
|
||||||
if (!(wp->w_floating && wp->w_config.border)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScreenGrid *grid = &wp->w_grid_alloc;
|
|
||||||
|
|
||||||
schar_T chars[8];
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
chars[i] = schar_from_str(wp->w_config.border_chars[i]);
|
|
||||||
}
|
|
||||||
int *attrs = wp->w_config.border_attr;
|
|
||||||
|
|
||||||
int *adj = wp->w_border_adj;
|
|
||||||
int irow = wp->w_view_height + wp->w_winbar_height;
|
|
||||||
int icol = wp->w_view_width;
|
|
||||||
|
|
||||||
if (adj[0]) {
|
|
||||||
screengrid_line_start(grid, 0, 0);
|
|
||||||
if (adj[3]) {
|
|
||||||
grid_line_put_schar(0, chars[0], attrs[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < icol; i++) {
|
|
||||||
grid_line_put_schar(i + adj[3], chars[1], attrs[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wp->w_config.title) {
|
|
||||||
int title_col = win_get_bordertext_col(icol, wp->w_config.title_width,
|
|
||||||
wp->w_config.title_pos);
|
|
||||||
win_redr_bordertext(wp, wp->w_config.title_chunks, title_col, kBorderTextTitle);
|
|
||||||
}
|
|
||||||
if (adj[1]) {
|
|
||||||
grid_line_put_schar(icol + adj[3], chars[2], attrs[2]);
|
|
||||||
}
|
|
||||||
grid_line_flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < irow; i++) {
|
|
||||||
if (adj[3]) {
|
|
||||||
screengrid_line_start(grid, i + adj[0], 0);
|
|
||||||
grid_line_put_schar(0, chars[7], attrs[7]);
|
|
||||||
grid_line_flush();
|
|
||||||
}
|
|
||||||
if (adj[1]) {
|
|
||||||
int ic = (i == 0 && !adj[0] && chars[2]) ? 2 : 3;
|
|
||||||
screengrid_line_start(grid, i + adj[0], 0);
|
|
||||||
grid_line_put_schar(icol + adj[3], chars[ic], attrs[ic]);
|
|
||||||
grid_line_flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adj[2]) {
|
|
||||||
screengrid_line_start(grid, irow + adj[0], 0);
|
|
||||||
if (adj[3]) {
|
|
||||||
grid_line_put_schar(0, chars[6], attrs[6]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < icol; i++) {
|
|
||||||
int ic = (i == 0 && !adj[3] && chars[6]) ? 6 : 5;
|
|
||||||
grid_line_put_schar(i + adj[3], chars[ic], attrs[ic]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wp->w_config.footer) {
|
|
||||||
int footer_col = win_get_bordertext_col(icol, wp->w_config.footer_width,
|
|
||||||
wp->w_config.footer_pos);
|
|
||||||
win_redr_bordertext(wp, wp->w_config.footer_chunks, footer_col, kBorderTextFooter);
|
|
||||||
}
|
|
||||||
if (adj[1]) {
|
|
||||||
grid_line_put_schar(icol + adj[3], chars[4], attrs[4]);
|
|
||||||
}
|
|
||||||
grid_line_flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set cursor to its position in the current window.
|
/// Set cursor to its position in the current window.
|
||||||
void setcursor(void)
|
void setcursor(void)
|
||||||
{
|
{
|
||||||
|
106
src/nvim/grid.c
106
src/nvim/grid.c
@@ -1084,6 +1084,112 @@ void grid_del_lines(ScreenGrid *grid, int row, int line_count, int end, int col,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void grid_draw_bordertext(VirtText vt, int col, int winbl, const int *hl_attr,
|
||||||
|
BorderTextType bt)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < kv_size(vt);) {
|
||||||
|
int attr = -1;
|
||||||
|
char *text = next_virt_text_chunk(vt, &i, &attr);
|
||||||
|
if (text == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (attr == -1) { // No highlight specified.
|
||||||
|
attr = hl_attr[bt == kBorderTextTitle ? HLF_BTITLE : HLF_BFOOTER];
|
||||||
|
}
|
||||||
|
attr = hl_apply_winblend(winbl, attr);
|
||||||
|
col += grid_line_puts(col, text, -1, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_bordertext_col(int total_col, int text_width, AlignTextPos align)
|
||||||
|
{
|
||||||
|
switch (align) {
|
||||||
|
case kAlignLeft:
|
||||||
|
return 1;
|
||||||
|
case kAlignCenter:
|
||||||
|
return MAX((total_col - text_width) / 2 + 1, 1);
|
||||||
|
case kAlignRight:
|
||||||
|
return MAX(total_col - text_width + 1, 1);
|
||||||
|
}
|
||||||
|
UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// draw border on floating window grid
|
||||||
|
void grid_draw_border(ScreenGrid *grid, WinConfig config, int *adj, int winbl, int *hl_attr)
|
||||||
|
{
|
||||||
|
int *attrs = config.border_attr;
|
||||||
|
int default_adj[4] = { 1, 1, 1, 1 };
|
||||||
|
if (adj == NULL) {
|
||||||
|
adj = default_adj;
|
||||||
|
}
|
||||||
|
schar_T chars[8];
|
||||||
|
if (!hl_attr) {
|
||||||
|
hl_attr = hl_attr_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
chars[i] = schar_from_str(config.border_chars[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int irow = grid->rows - adj[0] - adj[2];
|
||||||
|
int icol = grid->cols - adj[1] - adj[3];
|
||||||
|
|
||||||
|
if (adj[0]) {
|
||||||
|
screengrid_line_start(grid, 0, 0);
|
||||||
|
if (adj[3]) {
|
||||||
|
grid_line_put_schar(0, chars[0], attrs[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < icol; i++) {
|
||||||
|
grid_line_put_schar(i + adj[3], chars[1], attrs[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.title) {
|
||||||
|
int title_col = get_bordertext_col(icol, config.title_width, config.title_pos);
|
||||||
|
grid_draw_bordertext(config.title_chunks, title_col, winbl, hl_attr, kBorderTextTitle);
|
||||||
|
}
|
||||||
|
if (adj[1]) {
|
||||||
|
grid_line_put_schar(icol + adj[3], chars[2], attrs[2]);
|
||||||
|
}
|
||||||
|
grid_line_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < irow; i++) {
|
||||||
|
if (adj[3]) {
|
||||||
|
screengrid_line_start(grid, i + adj[0], 0);
|
||||||
|
grid_line_put_schar(0, chars[7], attrs[7]);
|
||||||
|
grid_line_flush();
|
||||||
|
}
|
||||||
|
if (adj[1]) {
|
||||||
|
int ic = (i == 0 && !adj[0] && chars[2]) ? 2 : 3;
|
||||||
|
screengrid_line_start(grid, i + adj[0], 0);
|
||||||
|
grid_line_put_schar(icol + adj[3], chars[ic], attrs[ic]);
|
||||||
|
grid_line_flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adj[2]) {
|
||||||
|
screengrid_line_start(grid, irow + adj[0], 0);
|
||||||
|
if (adj[3]) {
|
||||||
|
grid_line_put_schar(0, chars[6], attrs[6]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < icol; i++) {
|
||||||
|
int ic = (i == 0 && !adj[3] && chars[6]) ? 6 : 5;
|
||||||
|
grid_line_put_schar(i + adj[3], chars[ic], attrs[ic]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.footer) {
|
||||||
|
int footer_col = get_bordertext_col(icol, config.footer_width, config.footer_pos);
|
||||||
|
grid_draw_bordertext(config.footer_chunks, footer_col, winbl, hl_attr, kBorderTextFooter);
|
||||||
|
}
|
||||||
|
if (adj[1]) {
|
||||||
|
grid_line_put_schar(icol + adj[3], chars[4], attrs[4]);
|
||||||
|
}
|
||||||
|
grid_line_flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void linecopy(ScreenGrid *grid, int to, int from, int col, int width)
|
static void linecopy(ScreenGrid *grid, int to, int from, int col, int width)
|
||||||
{
|
{
|
||||||
unsigned off_to = (unsigned)(grid->line_offset[to] + (size_t)col);
|
unsigned off_to = (unsigned)(grid->line_offset[to] + (size_t)col);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h> // IWYU pragma: keep
|
#include <stddef.h> // IWYU pragma: keep
|
||||||
|
|
||||||
|
#include "nvim/buffer_defs.h" // IWYU pragma: keep
|
||||||
#include "nvim/grid_defs.h" // IWYU pragma: keep
|
#include "nvim/grid_defs.h" // IWYU pragma: keep
|
||||||
#include "nvim/macros_defs.h"
|
#include "nvim/macros_defs.h"
|
||||||
#include "nvim/pos_defs.h"
|
#include "nvim/pos_defs.h"
|
||||||
|
@@ -325,16 +325,16 @@ int hl_get_ui_attr(int ns_id, int idx, int final_id, bool optional)
|
|||||||
|
|
||||||
/// Apply 'winblend' to highlight attributes.
|
/// Apply 'winblend' to highlight attributes.
|
||||||
///
|
///
|
||||||
/// @param wp The window to get 'winblend' value from.
|
/// @param winbl The 'winblend' value.
|
||||||
/// @param attr The original attribute code.
|
/// @param attr The original attribute code.
|
||||||
///
|
///
|
||||||
/// @return The attribute code with 'winblend' applied.
|
/// @return The attribute code with 'winblend' applied.
|
||||||
int hl_apply_winblend(win_T *wp, int attr)
|
int hl_apply_winblend(int winbl, int attr)
|
||||||
{
|
{
|
||||||
HlEntry entry = attr_entry(attr);
|
HlEntry entry = attr_entry(attr);
|
||||||
// if blend= attribute is not set, 'winblend' value overrides it.
|
// if blend= attribute is not set, 'winblend' value overrides it.
|
||||||
if (entry.attr.hl_blend == -1 && wp->w_p_winbl > 0) {
|
if (entry.attr.hl_blend == -1 && winbl > 0) {
|
||||||
entry.attr.hl_blend = (int)wp->w_p_winbl;
|
entry.attr.hl_blend = winbl;
|
||||||
attr = get_attr_entry(entry);
|
attr = get_attr_entry(entry);
|
||||||
}
|
}
|
||||||
return attr;
|
return attr;
|
||||||
@@ -379,7 +379,7 @@ void update_window_hl(win_T *wp, bool invalid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wp->w_floating) {
|
if (wp->w_floating) {
|
||||||
wp->w_hl_attr_normal = hl_apply_winblend(wp, wp->w_hl_attr_normal);
|
wp->w_hl_attr_normal = hl_apply_winblend((int)wp->w_p_winbl, wp->w_hl_attr_normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
wp->w_config.shadow = false;
|
wp->w_config.shadow = false;
|
||||||
@@ -390,7 +390,7 @@ void update_window_hl(win_T *wp, bool invalid)
|
|||||||
attr = hl_get_ui_attr(ns_id, HLF_BORDER,
|
attr = hl_get_ui_attr(ns_id, HLF_BORDER,
|
||||||
wp->w_config.border_hl_ids[i], false);
|
wp->w_config.border_hl_ids[i], false);
|
||||||
}
|
}
|
||||||
attr = hl_apply_winblend(wp, attr);
|
attr = hl_apply_winblend((int)wp->w_p_winbl, attr);
|
||||||
if (syn_attr2entry(attr).hl_blend > 0) {
|
if (syn_attr2entry(attr).hl_blend > 0) {
|
||||||
wp->w_config.shadow = true;
|
wp->w_config.shadow = true;
|
||||||
}
|
}
|
||||||
@@ -411,7 +411,7 @@ void update_window_hl(win_T *wp, bool invalid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (wp->w_floating) {
|
if (wp->w_floating) {
|
||||||
wp->w_hl_attr_normalnc = hl_apply_winblend(wp, wp->w_hl_attr_normalnc);
|
wp->w_hl_attr_normalnc = hl_apply_winblend((int)wp->w_p_winbl, wp->w_hl_attr_normalnc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -86,6 +86,7 @@ EXTERN const char *hlf_names[] INIT( = {
|
|||||||
[HLF_TS] = "StatusLineTerm",
|
[HLF_TS] = "StatusLineTerm",
|
||||||
[HLF_TSNC] = "StatusLineTermNC",
|
[HLF_TSNC] = "StatusLineTermNC",
|
||||||
[HLF_PRE] = "PreInsert",
|
[HLF_PRE] = "PreInsert",
|
||||||
|
[HLF_PBR] = "PmenuBorder",
|
||||||
});
|
});
|
||||||
|
|
||||||
EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context.
|
EXTERN int highlight_attr[HLF_COUNT]; // Highl. attr for each context.
|
||||||
|
@@ -110,6 +110,7 @@ typedef enum {
|
|||||||
HLF_PSX, ///< popup menu selected item "menu" (extra text)
|
HLF_PSX, ///< popup menu selected item "menu" (extra text)
|
||||||
HLF_PSB, ///< popup menu scrollbar
|
HLF_PSB, ///< popup menu scrollbar
|
||||||
HLF_PST, ///< popup menu scrollbar thumb
|
HLF_PST, ///< popup menu scrollbar thumb
|
||||||
|
HLF_PBR, ///< popup menu border
|
||||||
HLF_TP, ///< tabpage line
|
HLF_TP, ///< tabpage line
|
||||||
HLF_TPS, ///< tabpage line selected
|
HLF_TPS, ///< tabpage line selected
|
||||||
HLF_TPF, ///< tabpage line filler
|
HLF_TPF, ///< tabpage line filler
|
||||||
|
@@ -174,6 +174,9 @@ static const char *highlight_init_both[] = {
|
|||||||
"default link PmenuKind Pmenu",
|
"default link PmenuKind Pmenu",
|
||||||
"default link PmenuKindSel PmenuSel",
|
"default link PmenuKindSel PmenuSel",
|
||||||
"default link PmenuSbar Pmenu",
|
"default link PmenuSbar Pmenu",
|
||||||
|
"default link PmenuBorder Pmenu",
|
||||||
|
"default link PmenuShadow FloatShadow",
|
||||||
|
"default link PmenuShadowThrough FloatShadowThrough",
|
||||||
"default link PreInsert Added",
|
"default link PreInsert Added",
|
||||||
"default link ComplMatchIns NONE",
|
"default link ComplMatchIns NONE",
|
||||||
"default link ComplHint NonText",
|
"default link ComplHint NonText",
|
||||||
|
@@ -308,6 +308,7 @@ EXTERN OptInt p_acl; ///< 'autocompletedelay'
|
|||||||
#ifdef BACKSLASH_IN_FILENAME
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
EXTERN char *p_csl; ///< 'completeslash'
|
EXTERN char *p_csl; ///< 'completeslash'
|
||||||
#endif
|
#endif
|
||||||
|
EXTERN char *p_pumborder; ///< 'pumborder'
|
||||||
EXTERN OptInt p_pb; ///< 'pumblend'
|
EXTERN OptInt p_pb; ///< 'pumblend'
|
||||||
EXTERN OptInt p_ph; ///< 'pumheight'
|
EXTERN OptInt p_ph; ///< 'pumheight'
|
||||||
EXTERN OptInt p_pw; ///< 'pumwidth'
|
EXTERN OptInt p_pw; ///< 'pumwidth'
|
||||||
|
@@ -6719,6 +6719,21 @@ local options = {
|
|||||||
type = 'number',
|
type = 'number',
|
||||||
varname = 'p_pb',
|
varname = 'p_pb',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
full_name = 'pumborder',
|
||||||
|
scope = { 'global' },
|
||||||
|
cb = 'did_set_pumborder',
|
||||||
|
defaults = { if_true = '' },
|
||||||
|
values = { '', 'double', 'single', 'shadow', 'rounded', 'solid', 'bold', 'none' },
|
||||||
|
desc = [=[
|
||||||
|
Defines the default border style of popupmenu windows. Same as
|
||||||
|
'winborder'.
|
||||||
|
]=],
|
||||||
|
short_desc = N_('border of popupmenu'),
|
||||||
|
type = 'string',
|
||||||
|
list = 'onecomma',
|
||||||
|
varname = 'p_pumborder',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
abbreviation = 'ph',
|
abbreviation = 'ph',
|
||||||
defaults = 0,
|
defaults = 0,
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
#include "nvim/cmdexpand_defs.h"
|
#include "nvim/cmdexpand_defs.h"
|
||||||
#include "nvim/cursor.h"
|
#include "nvim/cursor.h"
|
||||||
#include "nvim/cursor_shape.h"
|
#include "nvim/cursor_shape.h"
|
||||||
|
#include "nvim/decoration.h"
|
||||||
#include "nvim/diff.h"
|
#include "nvim/diff.h"
|
||||||
#include "nvim/digraph.h"
|
#include "nvim/digraph.h"
|
||||||
#include "nvim/drawscreen.h"
|
#include "nvim/drawscreen.h"
|
||||||
@@ -2124,16 +2125,32 @@ const char *did_set_winbar(optset_T *args)
|
|||||||
return did_set_statustabline_rulerformat(args, false, false);
|
return did_set_statustabline_rulerformat(args, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The 'winborder' option is changed.
|
static bool parse_border_opt(const char *border_opt)
|
||||||
const char *did_set_winborder(optset_T *args)
|
|
||||||
{
|
{
|
||||||
WinConfig fconfig = WIN_CONFIG_INIT;
|
WinConfig fconfig = WIN_CONFIG_INIT;
|
||||||
Error err = ERROR_INIT;
|
Error err = ERROR_INIT;
|
||||||
if (!parse_winborder(&fconfig, &err)) {
|
bool result = true;
|
||||||
api_clear_error(&err);
|
if (!parse_winborder(&fconfig, border_opt, &err)) {
|
||||||
return e_invarg;
|
result = false;
|
||||||
}
|
}
|
||||||
api_clear_error(&err);
|
api_clear_error(&err);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The 'winborder' option is changed.
|
||||||
|
const char *did_set_winborder(optset_T *args)
|
||||||
|
{
|
||||||
|
if (!parse_border_opt(p_winborder)) {
|
||||||
|
return e_invarg;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *did_set_pumborder(optset_T *args)
|
||||||
|
{
|
||||||
|
if (!parse_border_opt(p_pumborder)) {
|
||||||
|
return e_invarg;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,12 +10,15 @@
|
|||||||
#include "nvim/api/buffer.h"
|
#include "nvim/api/buffer.h"
|
||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
|
#include "nvim/api/vim.h"
|
||||||
|
#include "nvim/api/win_config.h"
|
||||||
#include "nvim/ascii_defs.h"
|
#include "nvim/ascii_defs.h"
|
||||||
#include "nvim/autocmd.h"
|
#include "nvim/autocmd.h"
|
||||||
#include "nvim/buffer.h"
|
#include "nvim/buffer.h"
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/buffer_defs.h"
|
||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
#include "nvim/cmdexpand.h"
|
#include "nvim/cmdexpand.h"
|
||||||
|
#include "nvim/decoration.h"
|
||||||
#include "nvim/drawscreen.h"
|
#include "nvim/drawscreen.h"
|
||||||
#include "nvim/errors.h"
|
#include "nvim/errors.h"
|
||||||
#include "nvim/eval/typval.h"
|
#include "nvim/eval/typval.h"
|
||||||
@@ -28,8 +31,10 @@
|
|||||||
#include "nvim/gettext_defs.h"
|
#include "nvim/gettext_defs.h"
|
||||||
#include "nvim/globals.h"
|
#include "nvim/globals.h"
|
||||||
#include "nvim/grid.h"
|
#include "nvim/grid.h"
|
||||||
|
#include "nvim/grid_defs.h"
|
||||||
#include "nvim/highlight.h"
|
#include "nvim/highlight.h"
|
||||||
#include "nvim/highlight_defs.h"
|
#include "nvim/highlight_defs.h"
|
||||||
|
#include "nvim/highlight_group.h"
|
||||||
#include "nvim/insexpand.h"
|
#include "nvim/insexpand.h"
|
||||||
#include "nvim/keycodes.h"
|
#include "nvim/keycodes.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
@@ -47,6 +52,7 @@
|
|||||||
#include "nvim/pos_defs.h"
|
#include "nvim/pos_defs.h"
|
||||||
#include "nvim/state_defs.h"
|
#include "nvim/state_defs.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/types_defs.h"
|
#include "nvim/types_defs.h"
|
||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/ui_compositor.h"
|
#include "nvim/ui_compositor.h"
|
||||||
@@ -116,7 +122,7 @@ static void pum_compute_size(void)
|
|||||||
/// Calculate vertical placement for popup menu.
|
/// Calculate vertical placement for popup menu.
|
||||||
/// Sets pum_row and pum_height based on available space.
|
/// Sets pum_row and pum_height based on available space.
|
||||||
static void pum_compute_vertical_placement(int size, win_T *target_win, int pum_win_row,
|
static void pum_compute_vertical_placement(int size, win_T *target_win, int pum_win_row,
|
||||||
int above_row, int below_row)
|
int above_row, int below_row, int pum_border_size)
|
||||||
{
|
{
|
||||||
int context_lines;
|
int context_lines;
|
||||||
|
|
||||||
@@ -128,7 +134,7 @@ static void pum_compute_vertical_placement(int size, win_T *target_win, int pum_
|
|||||||
|
|
||||||
// Put the pum below "pum_win_row" if possible.
|
// Put the pum below "pum_win_row" if possible.
|
||||||
// If there are few lines decide on where there is more room.
|
// 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 + pum_border_size >= below_row - pum_height
|
||||||
&& pum_win_row - above_row > (below_row - above_row) / 2) {
|
&& pum_win_row - above_row > (below_row - above_row) / 2) {
|
||||||
// pum above "pum_win_row"
|
// pum above "pum_win_row"
|
||||||
pum_above = true;
|
pum_above = true;
|
||||||
@@ -152,6 +158,14 @@ static void pum_compute_vertical_placement(int size, win_T *target_win, int pum_
|
|||||||
pum_row += pum_height - (int)p_ph;
|
pum_row += pum_height - (int)p_ph;
|
||||||
pum_height = (int)p_ph;
|
pum_height = (int)p_ph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pum_border_size > 0 && pum_border_size + pum_row + pum_height >= pum_win_row) {
|
||||||
|
if (pum_row < 2) {
|
||||||
|
pum_height -= pum_border_size;
|
||||||
|
} else {
|
||||||
|
pum_row -= pum_border_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// pum below "pum_win_row"
|
// pum below "pum_win_row"
|
||||||
pum_above = false;
|
pum_above = false;
|
||||||
@@ -172,6 +186,10 @@ static void pum_compute_vertical_placement(int size, win_T *target_win, int pum_
|
|||||||
if (p_ph > 0 && pum_height > p_ph) {
|
if (p_ph > 0 && pum_height > p_ph) {
|
||||||
pum_height = (int)p_ph;
|
pum_height = (int)p_ph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pum_row + pum_height + pum_border_size >= cmdline_row) {
|
||||||
|
pum_height -= pum_border_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a preview window above avoid drawing over it.
|
// If there is a preview window above avoid drawing over it.
|
||||||
@@ -279,6 +297,8 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
|
|||||||
|
|
||||||
pum_rl = (State & MODE_CMDLINE) == 0 && curwin->w_p_rl;
|
pum_rl = (State & MODE_CMDLINE) == 0 && curwin->w_p_rl;
|
||||||
|
|
||||||
|
int pum_border_size = *p_pumborder != NUL ? 2 : 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Mark the pum as visible already here,
|
// Mark the pum as visible already here,
|
||||||
// to avoid that must_redraw is set when 'cursorcolumn' is on.
|
// to avoid that must_redraw is set when 'cursorcolumn' is on.
|
||||||
@@ -366,10 +386,11 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out the vertical size and position of the pum.
|
// Figure out the vertical size and position of the pum.
|
||||||
pum_compute_vertical_placement(size, target_win, pum_win_row, above_row, below_row);
|
pum_compute_vertical_placement(size, target_win, pum_win_row, above_row, below_row,
|
||||||
|
pum_border_size);
|
||||||
|
|
||||||
// don't display when we only have room for one line
|
// don't display when we only have room for one line
|
||||||
if (pum_height < 1 || (pum_height == 1 && size > 1)) {
|
if (pum_border_size == 0 && (pum_height < 1 || (pum_height == 1 && size > 1))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,6 +410,10 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
|
|||||||
// Figure out the horizontal size and position of the pum.
|
// Figure out the horizontal size and position of the pum.
|
||||||
pum_compute_horizontal_placement(target_win, cursor_col);
|
pum_compute_horizontal_placement(target_win, cursor_col);
|
||||||
|
|
||||||
|
if (pum_col + pum_border_size + pum_width > Columns) {
|
||||||
|
pum_col -= pum_border_size;
|
||||||
|
}
|
||||||
|
|
||||||
// Set selected item and redraw. If the window size changed need to redo
|
// 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
|
// the positioning. Limit this to two times, when there is not much
|
||||||
// room the window size will keep changing.
|
// room the window size will keep changing.
|
||||||
@@ -573,18 +598,43 @@ void pum_redraw(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WinConfig fconfig = WIN_CONFIG_INIT;
|
||||||
|
int pum_border_width = 0;
|
||||||
|
// setup popup menu border if 'pumborder' option is set
|
||||||
|
if (*p_pumborder != NUL) {
|
||||||
|
pum_border_width = 2;
|
||||||
|
fconfig.border = true;
|
||||||
|
Error err = ERROR_INIT;
|
||||||
|
parse_border_style(CSTR_AS_OBJ(p_pumborder), &fconfig, &err);
|
||||||
|
// shadow style uses different highlights for different positions
|
||||||
|
if (strcmp(p_pumborder, opt_winborder_values[3]) == 0) {
|
||||||
|
int blend = SYN_GROUP_STATIC("PmenuShadow");
|
||||||
|
int through = SYN_GROUP_STATIC("PmenuShadowThrough");
|
||||||
|
int attrs[] = { 0, 0, through, blend, blend, blend, through, 0 };
|
||||||
|
memcpy(fconfig.border_attr, attrs, sizeof(attrs));
|
||||||
|
} else {
|
||||||
|
// Non-shadow styles use PumBorder highlight for all border chars
|
||||||
|
int attr = hl_attr_active[HLF_PBR];
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
fconfig.border_attr[i] = attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
api_clear_error(&err);
|
||||||
|
}
|
||||||
grid_assign_handle(&pum_grid);
|
grid_assign_handle(&pum_grid);
|
||||||
|
|
||||||
pum_left_col = pum_col - col_off;
|
pum_left_col = pum_col - col_off;
|
||||||
pum_right_col = pum_left_col + grid_width;
|
pum_right_col = pum_left_col + grid_width;
|
||||||
bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_left_col,
|
bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_left_col,
|
||||||
pum_height, grid_width, false, true);
|
pum_height + pum_border_width, grid_width + pum_border_width, false,
|
||||||
|
true);
|
||||||
bool invalid_grid = moved || pum_invalid;
|
bool invalid_grid = moved || pum_invalid;
|
||||||
pum_invalid = false;
|
pum_invalid = false;
|
||||||
must_redraw_pum = false;
|
must_redraw_pum = false;
|
||||||
|
|
||||||
if (!pum_grid.chars || pum_grid.rows != pum_height || pum_grid.cols != grid_width) {
|
if (!pum_grid.chars || pum_grid.rows != pum_height || pum_grid.cols != grid_width) {
|
||||||
grid_alloc(&pum_grid, pum_height, grid_width, !invalid_grid, false);
|
grid_alloc(&pum_grid, pum_height + pum_border_width, grid_width + pum_border_width,
|
||||||
|
!invalid_grid, false);
|
||||||
ui_call_grid_resize(pum_grid.handle, pum_grid.cols, pum_grid.rows);
|
ui_call_grid_resize(pum_grid.handle, pum_grid.cols, pum_grid.rows);
|
||||||
} else if (invalid_grid) {
|
} else if (invalid_grid) {
|
||||||
grid_invalidate(&pum_grid);
|
grid_invalidate(&pum_grid);
|
||||||
@@ -599,6 +649,15 @@ void pum_redraw(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int scroll_range = pum_size - pum_height;
|
int scroll_range = pum_size - pum_height;
|
||||||
|
|
||||||
|
// avoid set border for mouse menu
|
||||||
|
int mouse_menu = State != MODE_CMDLINE && pum_grid.zindex == kZIndexCmdlinePopupMenu;
|
||||||
|
if (!mouse_menu && fconfig.border) {
|
||||||
|
grid_draw_border(&pum_grid, fconfig, NULL, 0, NULL);
|
||||||
|
row++;
|
||||||
|
col_off++;
|
||||||
|
}
|
||||||
|
|
||||||
// Never display more than we have
|
// Never display more than we have
|
||||||
pum_first = MIN(pum_first, scroll_range);
|
pum_first = MIN(pum_first, scroll_range);
|
||||||
|
|
||||||
@@ -871,7 +930,8 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma
|
|||||||
/// adjust floating info preview window position
|
/// adjust floating info preview window position
|
||||||
static void pum_adjust_info_position(win_T *wp, int width)
|
static void pum_adjust_info_position(win_T *wp, int width)
|
||||||
{
|
{
|
||||||
int col = pum_col + pum_width + pum_scrollbar + 1;
|
int extra_width = *p_pumborder != NUL ? 2 : 0;
|
||||||
|
int col = pum_col + pum_width + pum_scrollbar + 1 + extra_width;
|
||||||
// TODO(glepnir): support config align border by using completepopup
|
// TODO(glepnir): support config align border by using completepopup
|
||||||
// align menu
|
// align menu
|
||||||
int right_extra = Columns - col;
|
int right_extra = Columns - col;
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "nvim/buffer_defs.h"
|
||||||
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
|
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
|
||||||
#include "nvim/grid_defs.h"
|
#include "nvim/grid_defs.h"
|
||||||
#include "nvim/macros_defs.h"
|
#include "nvim/macros_defs.h"
|
||||||
|
@@ -258,11 +258,11 @@ describe('ui/cursor', function()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if m.hl_id then
|
if m.hl_id then
|
||||||
m.hl_id = 66
|
m.hl_id = 67
|
||||||
m.attr = { background = Screen.colors.DarkGray }
|
m.attr = { background = Screen.colors.DarkGray }
|
||||||
end
|
end
|
||||||
if m.id_lm then
|
if m.id_lm then
|
||||||
m.id_lm = 77
|
m.id_lm = 78
|
||||||
m.attr_lm = {}
|
m.attr_lm = {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@@ -2151,7 +2151,7 @@ describe('builtin popupmenu', function()
|
|||||||
feed('<C-E><ESC>')
|
feed('<C-E><ESC>')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('avoid modified original info text #test', function()
|
it('avoid modified original info text', function()
|
||||||
command('call Append_multipe()')
|
command('call Append_multipe()')
|
||||||
feed('S<C-x><C-o><C-P><C-P>')
|
feed('S<C-x><C-o><C-P><C-P>')
|
||||||
if multigrid then
|
if multigrid then
|
||||||
@@ -8730,6 +8730,407 @@ describe('builtin popupmenu', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe("'pumborder'", function()
|
||||||
|
before_each(function()
|
||||||
|
screen:try_resize(30, 11)
|
||||||
|
exec([[
|
||||||
|
funct Omni_test(findstart, base)
|
||||||
|
if a:findstart
|
||||||
|
return col(".") - 1
|
||||||
|
endif
|
||||||
|
return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}]
|
||||||
|
endfunc
|
||||||
|
hi link PmenuBorder FloatBorder
|
||||||
|
set omnifunc=Omni_test
|
||||||
|
set completeopt-=preview
|
||||||
|
set pumborder=rounded
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('can set border', function()
|
||||||
|
feed('Gi<C-x><C-o>')
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:------------------------------]|*10
|
||||||
|
[3:------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
one^ |
|
||||||
|
{1:~ }|*9
|
||||||
|
## grid 3
|
||||||
|
{5:-- }{6:match 1 of 3} |
|
||||||
|
## grid 4
|
||||||
|
{n:1info}|
|
||||||
|
## grid 5
|
||||||
|
╭───────────────╮|
|
||||||
|
│{12:one }│|
|
||||||
|
│{n:two }│|
|
||||||
|
│{n:three }│|
|
||||||
|
╰───────────────╯|
|
||||||
|
]],
|
||||||
|
win_pos = {
|
||||||
|
[2] = {
|
||||||
|
height = 10,
|
||||||
|
startcol = 0,
|
||||||
|
startrow = 0,
|
||||||
|
width = 30,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
float_pos = {
|
||||||
|
[5] = { -1, 'NW', 2, 1, 0, false, 100, 2, 1, 0 },
|
||||||
|
[4] = { 1001, 'NW', 1, 1, 17, false, 50, 1, 1, 17 },
|
||||||
|
},
|
||||||
|
win_viewport = {
|
||||||
|
[2] = {
|
||||||
|
win = 1000,
|
||||||
|
topline = 0,
|
||||||
|
botline = 2,
|
||||||
|
curline = 0,
|
||||||
|
curcol = 3,
|
||||||
|
linecount = 1,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
win = 1001,
|
||||||
|
topline = 0,
|
||||||
|
botline = 1,
|
||||||
|
curline = 0,
|
||||||
|
curcol = 0,
|
||||||
|
linecount = 1,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
win_viewport_margins = {
|
||||||
|
[2] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1001,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
one^ |
|
||||||
|
╭───────────────╮{n:1info}{1: }|
|
||||||
|
│{12:one }│{1: }|
|
||||||
|
│{n:two }│{1: }|
|
||||||
|
│{n:three }│{1: }|
|
||||||
|
╰───────────────╯{1: }|
|
||||||
|
{1:~ }|*4
|
||||||
|
{5:-- }{6:match 1 of 3} |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- avoid out of screen
|
||||||
|
feed(('a'):rep(25) .. '<C-x><C-o>')
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:------------------------------]|*10
|
||||||
|
[3:------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
oneaaaaaaaaaaaaaaaaaaaaaaaaaon|
|
||||||
|
e^ |
|
||||||
|
{1:~ }|*8
|
||||||
|
## grid 3
|
||||||
|
{5:-- }{6:match 1 of 3} |
|
||||||
|
## grid 4
|
||||||
|
{n:1info}|
|
||||||
|
## grid 5
|
||||||
|
╭─────────────────╮|
|
||||||
|
│{12: one }│|
|
||||||
|
│{n: two }│|
|
||||||
|
│{n: three }│|
|
||||||
|
╰─────────────────╯|
|
||||||
|
]],
|
||||||
|
win_pos = {
|
||||||
|
[2] = {
|
||||||
|
height = 10,
|
||||||
|
startcol = 0,
|
||||||
|
startrow = 0,
|
||||||
|
width = 30,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
float_pos = {
|
||||||
|
[5] = { -1, 'NW', 2, 2, 11, false, 100, 2, 2, 11 },
|
||||||
|
[4] = { 1001, 'NW', 1, 2, 6, false, 50, 1, 2, 6 },
|
||||||
|
},
|
||||||
|
win_viewport = {
|
||||||
|
[2] = {
|
||||||
|
win = 1000,
|
||||||
|
topline = 0,
|
||||||
|
botline = 2,
|
||||||
|
curline = 0,
|
||||||
|
curcol = 31,
|
||||||
|
linecount = 1,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
win = 1001,
|
||||||
|
topline = 0,
|
||||||
|
botline = 1,
|
||||||
|
curline = 0,
|
||||||
|
curcol = 0,
|
||||||
|
linecount = 1,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
win_viewport_margins = {
|
||||||
|
[2] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
[4] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1001,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
oneaaaaaaaaaaaaaaaaaaaaaaaaaon|
|
||||||
|
e^ |
|
||||||
|
{1:~ }{n:1info}╭─────────────────╮|
|
||||||
|
{1:~ }│{12: one }│|
|
||||||
|
{1:~ }│{n: two }│|
|
||||||
|
{1:~ }│{n: three }│|
|
||||||
|
{1:~ }╰─────────────────╯|
|
||||||
|
{1:~ }|*3
|
||||||
|
{5:-- }{6:match 1 of 3} |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('adjust to above when the below row + border out of win height', function()
|
||||||
|
command('set completeopt+=menuone,noselect')
|
||||||
|
feed('<ESC>Stwo' .. ('<CR>'):rep(6) .. 'tw<C-N>')
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:------------------------------]|*10
|
||||||
|
[3:------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
two |
|
||||||
|
|*5
|
||||||
|
tw^ |
|
||||||
|
{1:~ }|*3
|
||||||
|
## grid 3
|
||||||
|
{5:-- }{19:Back at original} |
|
||||||
|
## grid 4
|
||||||
|
╭───────────────╮|
|
||||||
|
│{n:two }│|
|
||||||
|
╰───────────────╯|
|
||||||
|
]],
|
||||||
|
win_pos = {
|
||||||
|
[2] = {
|
||||||
|
height = 10,
|
||||||
|
startcol = 0,
|
||||||
|
startrow = 0,
|
||||||
|
width = 30,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
float_pos = {
|
||||||
|
[4] = { -1, 'SW', 2, 4, 0, false, 100, 1, 3, 0 },
|
||||||
|
},
|
||||||
|
win_viewport = {
|
||||||
|
[2] = {
|
||||||
|
win = 1000,
|
||||||
|
topline = 0,
|
||||||
|
botline = 8,
|
||||||
|
curline = 6,
|
||||||
|
curcol = 2,
|
||||||
|
linecount = 7,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
win_viewport_margins = {
|
||||||
|
[2] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
two |
|
||||||
|
|*2
|
||||||
|
╭───────────────╮ |
|
||||||
|
│{n:two }│ |
|
||||||
|
╰───────────────╯ |
|
||||||
|
tw^ |
|
||||||
|
{1:~ }|*3
|
||||||
|
{5:-- }{19:Back at original} |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('pum border on cmdline', function()
|
||||||
|
command('set wildoptions=pum')
|
||||||
|
feed(':<TAB>')
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:------------------------------]|*10
|
||||||
|
[3:------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
|
|
||||||
|
{1:~ }|*9
|
||||||
|
## grid 3
|
||||||
|
:!^ |
|
||||||
|
## grid 4
|
||||||
|
╭─────────────────╮|
|
||||||
|
│{12: ! }{c: }│|
|
||||||
|
│{n: # }{12: }│|
|
||||||
|
│{n: & }{12: }│|
|
||||||
|
│{n: < }{12: }│|
|
||||||
|
│{n: = }{12: }│|
|
||||||
|
│{n: > }{12: }│|
|
||||||
|
│{n: @ }{12: }│|
|
||||||
|
│{n: Next }{12: }│|
|
||||||
|
╰─────────────────╯|
|
||||||
|
]],
|
||||||
|
win_pos = {
|
||||||
|
[2] = {
|
||||||
|
height = 10,
|
||||||
|
startcol = 0,
|
||||||
|
startrow = 0,
|
||||||
|
width = 30,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
float_pos = {
|
||||||
|
[4] = { -1, 'SW', 1, 8, 0, false, 250, 2, 0, 0 },
|
||||||
|
},
|
||||||
|
win_viewport = {
|
||||||
|
[2] = {
|
||||||
|
win = 1000,
|
||||||
|
topline = 0,
|
||||||
|
botline = 2,
|
||||||
|
curline = 0,
|
||||||
|
curcol = 0,
|
||||||
|
linecount = 1,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
win_viewport_margins = {
|
||||||
|
[2] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
╭─────────────────╮ |
|
||||||
|
│{12: ! }{c: }│{1: }|
|
||||||
|
│{n: # }{12: }│{1: }|
|
||||||
|
│{n: & }{12: }│{1: }|
|
||||||
|
│{n: < }{12: }│{1: }|
|
||||||
|
│{n: = }{12: }│{1: }|
|
||||||
|
│{n: > }{12: }│{1: }|
|
||||||
|
│{n: @ }{12: }│{1: }|
|
||||||
|
│{n: Next }{12: }│{1: }|
|
||||||
|
╰─────────────────╯{1: }|
|
||||||
|
:!^ |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('reduce pum height when height is not enough', function()
|
||||||
|
command('set lines=7 laststatus=2')
|
||||||
|
feed('S<C-x><C-o>')
|
||||||
|
if multigrid then
|
||||||
|
screen:expect({
|
||||||
|
grid = [[
|
||||||
|
## grid 1
|
||||||
|
[2:------------------------------]|*5
|
||||||
|
{3:[No Name] [+] }|
|
||||||
|
[3:------------------------------]|
|
||||||
|
## grid 2
|
||||||
|
one^ |
|
||||||
|
{1:~ }|*4
|
||||||
|
## grid 3
|
||||||
|
{5:-- }{6:match 1 of 3} |
|
||||||
|
## grid 4
|
||||||
|
╭────────────────╮|
|
||||||
|
│{12:one }{c: }│|
|
||||||
|
╰────────────────╯|
|
||||||
|
]],
|
||||||
|
win_pos = {
|
||||||
|
[2] = {
|
||||||
|
height = 5,
|
||||||
|
startcol = 0,
|
||||||
|
startrow = 0,
|
||||||
|
width = 30,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
float_pos = {
|
||||||
|
[4] = { -1, 'NW', 2, 1, 0, false, 100, 1, 1, 0 },
|
||||||
|
},
|
||||||
|
win_viewport = {
|
||||||
|
[2] = {
|
||||||
|
win = 1000,
|
||||||
|
topline = 0,
|
||||||
|
botline = 2,
|
||||||
|
curline = 0,
|
||||||
|
curcol = 3,
|
||||||
|
linecount = 1,
|
||||||
|
sum_scroll_delta = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
win_viewport_margins = {
|
||||||
|
[2] = {
|
||||||
|
bottom = 0,
|
||||||
|
left = 0,
|
||||||
|
right = 0,
|
||||||
|
top = 0,
|
||||||
|
win = 1000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
one^ |
|
||||||
|
╭────────────────╮{1: }|
|
||||||
|
│{12:one }{c: }│{1: }|
|
||||||
|
╰────────────────╯{1: }|
|
||||||
|
{1:~ }|
|
||||||
|
{3:[No Name] [+] }|
|
||||||
|
{5:-- }{6:match 1 of 3} |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe('with ext_multigrid and actual mouse grid', function()
|
describe('with ext_multigrid and actual mouse grid', function()
|
||||||
|
Reference in New Issue
Block a user