mirror of
https://github.com/neovim/neovim.git
synced 2026-08-29 18:41:48 +00:00
fix(pum): hide info floating window when insufficient space (#37107)
fix(pum): hide info window when insufficient space Problem: 1. Info window was displayed even with insufficient space. 2. Tab characters counted as single cells. Solution: 1. Hide window when space < 10 columns. Will be configurable via completepopup width option in the future. 2. Use win_linetabsize over mb_string2cells.
This commit is contained in:
@@ -910,15 +910,16 @@ void pum_redraw(void)
|
|||||||
/// Set the informational text in the preview buffer when the completion
|
/// Set the informational text in the preview buffer when the completion
|
||||||
/// item does not include a dedicated preview or popup window.
|
/// item does not include a dedicated preview or popup window.
|
||||||
///
|
///
|
||||||
/// @param[in] buf Buffer where the text will be set.
|
/// @param[in] win Window containing buffer where the text will be set.
|
||||||
/// @param[in] info Informational text to display in the preview buffer.
|
/// @param[in] info Informational text to display in the preview buffer.
|
||||||
/// @param[in] lnum Where to start the text. Incremented for each added line.
|
/// @param[in] lnum Where to start the text. Incremented for each added line.
|
||||||
/// @param[out] max_width Maximum width of the displayed text.
|
/// @param[out] max_width Maximum width of the displayed text.
|
||||||
static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *max_width)
|
static void pum_preview_set_text(win_T *win, char *info, linenr_T *lnum, int *max_width)
|
||||||
{
|
{
|
||||||
Error err = ERROR_INIT;
|
Error err = ERROR_INIT;
|
||||||
Arena arena = ARENA_EMPTY;
|
Arena arena = ARENA_EMPTY;
|
||||||
Array replacement = ARRAY_DICT_INIT;
|
Array replacement = ARRAY_DICT_INIT;
|
||||||
|
buf_T *buf = win->w_buffer;
|
||||||
buf->b_p_ma = true;
|
buf->b_p_ma = true;
|
||||||
|
|
||||||
// Iterate through the string line by line by temporarily replacing newlines with NUL
|
// Iterate through the string line by line by temporarily replacing newlines with NUL
|
||||||
@@ -931,7 +932,7 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*max_width = MAX(*max_width, (int)mb_string2cells(curr));
|
*max_width = MAX(*max_width, win_linetabsize(win, 0, curr, MAXCOL));
|
||||||
ADD(replacement, STRING_OBJ(cstr_to_string(curr)));
|
ADD(replacement, STRING_OBJ(cstr_to_string(curr)));
|
||||||
(*lnum)++;
|
(*lnum)++;
|
||||||
|
|
||||||
@@ -941,9 +942,7 @@ static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
int original_textlock = textlock;
|
int original_textlock = textlock;
|
||||||
if (textlock > 0) {
|
textlock = 0;
|
||||||
textlock = 0;
|
|
||||||
}
|
|
||||||
nvim_buf_set_lines(0, buf->handle, 0, -1, false, replacement, &arena, &err);
|
nvim_buf_set_lines(0, buf->handle, 0, -1, false, replacement, &arena, &err);
|
||||||
textlock = original_textlock;
|
textlock = original_textlock;
|
||||||
if (ERROR_SET(&err)) {
|
if (ERROR_SET(&err)) {
|
||||||
@@ -956,7 +955,7 @@ 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 bool pum_adjust_info_position(win_T *wp, int width)
|
||||||
{
|
{
|
||||||
int border_width = pum_border_width();
|
int border_width = pum_border_width();
|
||||||
int col = pum_col + pum_width + 1 + MAX(border_width, pum_scrollbar);
|
int col = pum_col + pum_width + 1 + MAX(border_width, pum_scrollbar);
|
||||||
@@ -965,6 +964,14 @@ static void pum_adjust_info_position(win_T *wp, int width)
|
|||||||
int right_extra = Columns - col;
|
int right_extra = Columns - col;
|
||||||
int left_extra = pum_col - 2;
|
int left_extra = pum_col - 2;
|
||||||
|
|
||||||
|
int max_extra = MAX(right_extra, left_extra);
|
||||||
|
// Close info window if there's insufficient space
|
||||||
|
// TODO(glepnir): Replace the hardcoded value (10) with values from the 'completepopup' width/height options.
|
||||||
|
if (max_extra < 10) {
|
||||||
|
wp->w_config.hide = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (right_extra > width) { // place in right
|
if (right_extra > width) { // place in right
|
||||||
wp->w_config.width = width;
|
wp->w_config.width = width;
|
||||||
wp->w_config.col = col - 1;
|
wp->w_config.col = col - 1;
|
||||||
@@ -973,7 +980,7 @@ static void pum_adjust_info_position(win_T *wp, int width)
|
|||||||
wp->w_config.col = pum_col - wp->w_config.width - 1;
|
wp->w_config.col = pum_col - wp->w_config.width - 1;
|
||||||
} else { // either width is enough just use the biggest one.
|
} else { // either width is enough just use the biggest one.
|
||||||
const bool place_in_right = right_extra > left_extra;
|
const bool place_in_right = right_extra > left_extra;
|
||||||
wp->w_config.width = place_in_right ? right_extra : left_extra;
|
wp->w_config.width = max_extra;
|
||||||
wp->w_config.col = place_in_right ? col - 1 : pum_col - wp->w_config.width - 1;
|
wp->w_config.col = place_in_right ? col - 1 : pum_col - wp->w_config.width - 1;
|
||||||
}
|
}
|
||||||
// when pum_above is SW otherwise is NW
|
// when pum_above is SW otherwise is NW
|
||||||
@@ -984,6 +991,7 @@ static void pum_adjust_info_position(win_T *wp, int width)
|
|||||||
wp->w_config.row = pum_above ? pum_row + wp->w_config.height : pum_row;
|
wp->w_config.row = pum_above ? pum_row + wp->w_config.height : pum_row;
|
||||||
wp->w_config.hide = false;
|
wp->w_config.hide = false;
|
||||||
win_config_float(wp, wp->w_config);
|
win_config_float(wp, wp->w_config);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used for nvim__complete_set
|
/// Used for nvim__complete_set
|
||||||
@@ -1010,12 +1018,14 @@ win_T *pum_set_info(int selected, char *info)
|
|||||||
}
|
}
|
||||||
linenr_T lnum = 0;
|
linenr_T lnum = 0;
|
||||||
int max_info_width = 0;
|
int max_info_width = 0;
|
||||||
pum_preview_set_text(wp->w_buffer, info, &lnum, &max_info_width);
|
pum_preview_set_text(wp, info, &lnum, &max_info_width);
|
||||||
no_u_sync--;
|
no_u_sync--;
|
||||||
RedrawingDisabled--;
|
RedrawingDisabled--;
|
||||||
redraw_later(wp, UPD_NOT_VALID);
|
redraw_later(wp, UPD_NOT_VALID);
|
||||||
|
|
||||||
pum_adjust_info_position(wp, max_info_width);
|
if (!pum_adjust_info_position(wp, max_info_width)) {
|
||||||
|
wp = NULL;
|
||||||
|
}
|
||||||
unblock_autocmds();
|
unblock_autocmds();
|
||||||
return wp;
|
return wp;
|
||||||
}
|
}
|
||||||
@@ -1167,7 +1177,7 @@ static bool pum_set_selected(int n, int repeat)
|
|||||||
if (res == OK) {
|
if (res == OK) {
|
||||||
linenr_T lnum = 0;
|
linenr_T lnum = 0;
|
||||||
int max_info_width = 0;
|
int max_info_width = 0;
|
||||||
pum_preview_set_text(curbuf, pum_array[pum_selected].pum_info, &lnum, &max_info_width);
|
pum_preview_set_text(curwin, pum_array[pum_selected].pum_info, &lnum, &max_info_width);
|
||||||
// Increase the height of the preview window to show the
|
// Increase the height of the preview window to show the
|
||||||
// text, but no more than 'previewheight' lines.
|
// text, but no more than 'previewheight' lines.
|
||||||
if (repeat == 0 && !use_float) {
|
if (repeat == 0 && !use_float) {
|
||||||
@@ -1191,7 +1201,9 @@ static bool pum_set_selected(int n, int repeat)
|
|||||||
|
|
||||||
if (use_float) {
|
if (use_float) {
|
||||||
// adjust floating window by actually height and max info text width
|
// adjust floating window by actually height and max info text width
|
||||||
pum_adjust_info_position(curwin, max_info_width);
|
if (!pum_adjust_info_position(curwin, max_info_width) && win_valid(curwin_save)) {
|
||||||
|
win_enter(curwin_save, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((curwin != curwin_save && win_valid(curwin_save))
|
if ((curwin != curwin_save && win_valid(curwin_save))
|
||||||
|
|||||||
@@ -2238,6 +2238,41 @@ describe('builtin popupmenu', function()
|
|||||||
feed('S<C-x><C-o><C-N>')
|
feed('S<C-x><C-o><C-N>')
|
||||||
eq(1, n.eval([[len(uniq(copy(g:bufnrs))) == 1]]))
|
eq(1, n.eval([[len(uniq(copy(g:bufnrs))) == 1]]))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('handles tabs in info width calculation', function()
|
||||||
|
screen:try_resize(50, 11)
|
||||||
|
command([[
|
||||||
|
set cot+=menuone
|
||||||
|
let g:list = [#{word: 'class', info: "\tClassName() = default;"}]
|
||||||
|
]])
|
||||||
|
feed('S<C-x><C-o>')
|
||||||
|
local info = fn.complete_info()
|
||||||
|
eq(30, api.nvim_win_get_width(info.preview_winid))
|
||||||
|
feed('<ESC>')
|
||||||
|
exec([[
|
||||||
|
setlocal tabstop=1
|
||||||
|
autocmd ModeChanged *:i ++once call complete(1, [#{word: 'a'}])
|
||||||
|
\| call nvim__complete_set(0, #{info: "\tfloob\tfloob"})
|
||||||
|
]])
|
||||||
|
feed('i')
|
||||||
|
info = fn.complete_info()
|
||||||
|
eq(21, api.nvim_win_get_width(info.preview_winid))
|
||||||
|
if not multigrid then
|
||||||
|
screen:expect([[
|
||||||
|
a^s |
|
||||||
|
{12:a }{n: floob floob}{1: }|
|
||||||
|
{1:~ }|*8
|
||||||
|
{5:-- INSERT --} |
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('hide info window when insufficient space', function()
|
||||||
|
screen:try_resize(12, 11)
|
||||||
|
feed('S<C-x><C-o>')
|
||||||
|
local info = fn.complete_info()
|
||||||
|
eq(true, api.nvim_win_get_config(info.preview_winid).hide)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('with vsplits', function()
|
it('with vsplits', function()
|
||||||
|
|||||||
Reference in New Issue
Block a user