commit 8ae9a44d3841e3ae39f3976a711b29bb50b8f515
parent c1648cf820ed379f6abb7cb802680a02a1def755
Author: fredizzimo <fsundvik@gmail.com>
Date: Sun, 14 Sep 2025 00:57:04 +0300
feat(ui): support grid=0 in nvim_input_mouse #32535
Problem:
Multigrid UIs have to find out which window to send the input by using
the Nvim focus rules, which are not fully documented.
Furthermore,`getmousepos()` has several problems when multigrid is
enabled, with the main one being that screenrow and screencol are window
relative instead of screen relative, due to the fact that the UI don't
send any absolute coordinates.
Solution:
Allow passing 0 as grid to `nvim_input_mouse`, with absolute
coordinates, which lets nvim determine the actual window to send the
mouse input to. This works as long as nvim is in charge of the window
positioning. If the UI repositions or resizes the windows, it can still
pass the grid it determines like before.
Diffstat:
15 files changed, 2170 insertions(+), 1944 deletions(-)
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
@@ -1147,8 +1147,9 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
press, except that the "-" separator is optional, so
"C-A-", "c-a" and "CA" can all be used to specify
Ctrl+Alt+click.
- • {grid} (`integer`) Grid number if the client uses |ui-multigrid|,
- else 0.
+ • {grid} (`integer`) Grid number (used by |ui-multigrid| client),
+ or 0 to let Nvim decide positioning of windows. For more
+ information, see |dev-ui-multigrid|
• {row} (`integer`) Mouse row-position (zero-based, like redraw
events)
• {col} (`integer`) Mouse column-position (zero-based, like redraw
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
@@ -685,5 +685,23 @@ External UIs are expected to implement these common features:
- Handle the "restart" UI event so that |:restart| works.
- Detect capslock and show an indicator if capslock is active.
+Multigrid UI ~
+ *dev-ui-multigrid*
+- A multigrid UI should display floating windows using one of the following
+ methods, using the `win_float_pos` |ui-multigrid| event. Different methods
+ can be selected for each window as needed.
+
+ 1. Let Nvim determine the position and z-order of the windows. This can be
+ achieved by using the `compindex`, `screen_row`, and `screen_col` information from
+ the `win_float_pos` UI event. To allow Nvim to automatically determine the grid,
+ the UI should call `nvim_input_mouse` with 0 as the `grid` parameter.
+ 2. Use the `anchor`, `anchor_grid`, `anchor_row`, `anchor_col`, and `zindex` as
+ references for positioning the windows. If windows are outside the screen,
+ it is the UI's responsibility to reposition and/or resize them. Since Nvim
+ lacks information about actual window placement in this case, the UI must
+ call `nvim_input_mouse` with the actual grid id, factoring in `mouse_enabled`.
+ Note: Some API functions may return unexpected results for these windows due
+ to the missing information.
+- For external windows, the grid id should also be passed to `nvim_input_mouse`.
vim:tw=78:ts=8:sw=4:et:ft=help:norl:
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -339,6 +339,7 @@ UI
• "Error executing Lua:" changed to "Lua:".
• 'busy' status is shown in default statusline with symbol ◐
• Improved LSP signature help rendering.
+• Multigrid UIs can call nvim_input_mouse with grid 0 to let Nvim decide the grid.
VIMSCRIPT
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
@@ -1606,7 +1606,8 @@ function vim.api.nvim_input(keys) end
--- The same specifiers are used as for a key press, except
--- that the "-" separator is optional, so "C-A-", "c-a"
--- and "CA" can all be used to specify Ctrl+Alt+click.
---- @param grid integer Grid number if the client uses `ui-multigrid`, else 0.
+--- @param grid integer Grid number (used by `ui-multigrid` client), or 0 to let Nvim decide positioning of
+--- windows. For more information, see [dev-ui-multigrid]
--- @param row integer Mouse row-position (zero-based, like redraw events)
--- @param col integer Mouse column-position (zero-based, like redraw events)
function vim.api.nvim_input_mouse(button, action, modifier, grid, row, col) end
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
@@ -382,7 +382,8 @@ Integer nvim_input(uint64_t channel_id, String keys)
/// The same specifiers are used as for a key press, except
/// that the "-" separator is optional, so "C-A-", "c-a"
/// and "CA" can all be used to specify Ctrl+Alt+click.
-/// @param grid Grid number if the client uses |ui-multigrid|, else 0.
+/// @param grid Grid number (used by |ui-multigrid| client), or 0 to let Nvim decide positioning of
+/// windows. For more information, see [dev-ui-multigrid]
/// @param row Mouse row-position (zero-based, like redraw events)
/// @param col Mouse column-position (zero-based, like redraw events)
/// @param[out] err Error details, if any
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
@@ -2013,7 +2013,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv, bool allow_number
int winnr = 1;
// Find the window at the mouse coordinates and compute the
// text position.
- win_T *const win = mouse_find_win(&grid, &row, &col);
+ win_T *const win = mouse_find_win_inner(&grid, &row, &col);
if (win == NULL) {
return;
}
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
@@ -235,7 +235,7 @@ static int get_fpos_of_mouse(pos_T *mpos)
}
// find the window where the row is in
- win_T *wp = mouse_find_win(&grid, &row, &col);
+ win_T *wp = mouse_find_win_inner(&grid, &row, &col);
if (wp == NULL) {
return IN_UNKNOWN;
}
@@ -663,7 +663,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
int click_grid = mouse_grid;
int click_row = mouse_row;
int click_col = mouse_col;
- win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
+ win_T *wp = mouse_find_win_inner(&click_grid, &click_row, &click_col);
if (wp == NULL) {
return false;
}
@@ -1093,7 +1093,7 @@ void ins_mousescroll(int dir)
int grid = mouse_grid;
int row = mouse_row;
int col = mouse_col;
- curwin = mouse_find_win(&grid, &row, &col);
+ curwin = mouse_find_win_inner(&grid, &row, &col);
if (curwin == NULL) {
curwin = old_curwin;
return;
@@ -1263,8 +1263,8 @@ retnomove:
}
// find the window where the row is in and adjust "row" and "col" to be
- // relative to top-left of the window
- win_T *wp = mouse_find_win(&grid, &row, &col);
+ // relative to top-left of the window inner area
+ win_T *wp = mouse_find_win_inner(&grid, &row, &col);
if (wp == NULL) {
return IN_UNKNOWN;
}
@@ -1581,7 +1581,7 @@ void nv_mousescroll(cmdarg_T *cap)
int grid = mouse_grid;
int row = mouse_row;
int col = mouse_col;
- curwin = mouse_find_win(&grid, &row, &col);
+ curwin = mouse_find_win_inner(&grid, &row, &col);
if (curwin == NULL) {
curwin = old_curwin;
return;
@@ -1695,10 +1695,10 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
}
/// Find the window at "grid" position "*rowp" and "*colp". The positions are
-/// updated to become relative to the top-left of the window.
+/// updated to become relative to the top-left of the window inner area.
///
/// @return NULL when something is wrong.
-win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
+win_T *mouse_find_win_inner(int *gridp, int *rowp, int *colp)
{
win_T *wp_grid = mouse_find_grid_win(gridp, rowp, colp);
if (wp_grid) {
@@ -1740,6 +1740,20 @@ win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
return NULL;
}
+/// Find the window at "grid" position "*rowp" and "*colp". The positions are
+/// updated to become relative to the top-left of the window.
+///
+/// @return NULL when something is wrong.
+win_T *mouse_find_win_outer(int *gridp, int *rowp, int *colp)
+{
+ win_T *wp = mouse_find_win_inner(gridp, rowp, colp);
+ if (wp) {
+ *rowp += wp->w_winrow_off;
+ *colp += wp->w_wincol_off;
+ }
+ return wp;
+}
+
static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
{
if (*gridp == msg_grid.handle) {
@@ -1755,18 +1769,26 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
}
} else if (*gridp == 0) {
ScreenGrid *grid = ui_comp_mouse_focus(*rowp, *colp);
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (&wp->w_grid_alloc != grid) {
- continue;
- }
+ if (grid == &pum_grid) {
*gridp = grid->handle;
- *rowp -= grid->comp_row + wp->w_grid.row_offset;
- *colp -= grid->comp_col + wp->w_grid.col_offset;
- return wp;
+ *rowp -= grid->comp_row;
+ *colp -= grid->comp_col;
+ // The popup menu doesn't have a window, so return NULL
+ return NULL;
+ } else {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (&wp->w_grid_alloc != grid) {
+ continue;
+ }
+ *gridp = grid->handle;
+ *rowp -= wp->w_winrow + wp->w_grid.row_offset;
+ *colp -= wp->w_wincol + wp->w_grid.col_offset;
+ return wp;
+ }
}
- // no float found, click on the default grid
- // TODO(bfredl): grid can be &pum_grid, allow select pum items by mouse?
+ // No grid found, return the default grid. With multigrid this happens for split separators for
+ // example.
*gridp = DEFAULT_GRID_HANDLE;
}
return NULL;
@@ -1877,7 +1899,7 @@ static void mouse_check_grid(colnr_T *vcolp, int *flagsp)
int click_col = mouse_col;
// XXX: this doesn't change click_grid if it is 1, even with multigrid
- if (mouse_find_win(&click_grid, &click_row, &click_col) != curwin
+ if (mouse_find_win_inner(&click_grid, &click_row, &click_col) != curwin
// Only use vcols[] after the window was redrawn. Mainly matters
// for tests, a user would not click before redrawing.
|| curwin->w_redr_type != 0) {
@@ -1931,7 +1953,7 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tv_dict_add_nr(d, S_LEN("screenrow"), (varnumber_T)mouse_row + 1);
tv_dict_add_nr(d, S_LEN("screencol"), (varnumber_T)mouse_col + 1);
- win_T *wp = mouse_find_win(&grid, &row, &col);
+ win_T *wp = mouse_find_win_inner(&grid, &row, &col);
if (wp != NULL) {
int height = wp->w_height + wp->w_hsep_height + wp->w_status_height;
// The height is adjusted by 1 when there is a bottom border. This is not
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
@@ -37,6 +37,7 @@
#include "nvim/memory_defs.h"
#include "nvim/menu.h"
#include "nvim/message.h"
+#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/option_defs.h"
@@ -1325,6 +1326,10 @@ static void pum_position_at_mouse(int min_width)
int col = mouse_col;
pum_win_row_offset = 0;
pum_win_col_offset = 0;
+
+ if (ui_has(kUIMultigrid) && grid == 0) {
+ mouse_find_win_outer(&grid, &row, &col);
+ }
if (grid > 1) {
win_T *wp = get_win_by_grid_handle(grid);
if (wp != NULL) {
@@ -1395,17 +1400,27 @@ static void pum_position_at_mouse(int min_width)
/// Select the pum entry at the mouse position.
static void pum_select_mouse_pos(void)
{
- if (mouse_grid == pum_grid.handle) {
- pum_selected = mouse_row;
+ int grid = mouse_grid;
+ int row = mouse_row;
+ int col = mouse_col;
+
+ if (grid == 0) {
+ mouse_find_win_outer(&grid, &row, &col);
+ }
+
+ if (grid == pum_grid.handle) {
+ pum_selected = row;
return;
- } else if (mouse_grid != pum_anchor_grid
- || mouse_col < pum_left_col - pum_win_col_offset
- || mouse_col >= pum_right_col - pum_win_col_offset) {
+ }
+
+ if (grid != pum_anchor_grid
+ || col < pum_left_col - pum_win_col_offset
+ || col >= pum_right_col - pum_win_col_offset) {
pum_selected = -1;
return;
}
- int idx = mouse_row - (pum_row - pum_win_row_offset);
+ int idx = row - (pum_row - pum_win_row_offset);
if (idx < 0 || idx >= pum_height) {
pum_selected = -1;
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
@@ -1907,7 +1907,7 @@ static bool send_mouse_event(Terminal *term, int c)
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
- win_T *mouse_win = mouse_find_win(&grid, &row, &col);
+ win_T *mouse_win = mouse_find_win_inner(&grid, &row, &col);
if (mouse_win == NULL) {
goto end;
}
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
@@ -318,6 +318,15 @@ ScreenGrid *ui_comp_mouse_focus(int row, int col)
return grid;
}
}
+ if (ui_has(kUIMultigrid)) {
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ ScreenGrid *grid = &wp->w_grid_alloc;
+ if (grid->mouse_enabled && row >= wp->w_winrow && row < wp->w_winrow + grid->rows
+ && col >= wp->w_wincol && col < wp->w_wincol + grid->cols) {
+ return grid;
+ }
+ }
+ }
return NULL;
}
diff --git a/src/nvim/window.c b/src/nvim/window.c
@@ -5187,6 +5187,8 @@ win_T *win_alloc(win_T *after, bool hidden)
new_wp->handle = ++last_win_id;
pmap_put(int)(&window_handles, new_wp->handle, new_wp);
+ new_wp->w_grid_alloc.mouse_enabled = true;
+
grid_assign_handle(&new_wp->w_grid_alloc);
// Init w: variables.
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
@@ -192,7 +192,7 @@ void win_config_float(win_T *wp, WinConfig fconfig)
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
- win_T *mouse_win = mouse_find_win(&grid, &row, &col);
+ win_T *mouse_win = mouse_find_win_inner(&grid, &row, &col);
if (mouse_win != NULL) {
fconfig.relative = kFloatRelativeWindow;
fconfig.row += row;
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
@@ -971,7 +971,7 @@ describe('float window', function()
api.nvim_win_set_config(win, api.nvim_win_get_config(win))
end)
- local function with_ext_multigrid(multigrid)
+ local function with_ext_multigrid(multigrid, send_mouse_grid)
local screen, attrs
before_each(function()
screen = Screen.new(40, 7, { ext_multigrid = multigrid })
@@ -6164,8 +6164,12 @@ describe('float window', function()
end)
local function test_float_mouse_focus()
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
+ end
+ if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -6183,7 +6187,6 @@ describe('float window', function()
float_pos = expected_pos,
}
else
- api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
screen:expect([[
x |
{0:~ }|
@@ -6194,8 +6197,12 @@ describe('float window', function()
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ end
+ if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -6213,7 +6220,6 @@ describe('float window', function()
float_pos = expected_pos,
}
else
- api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
^x |
{0:~ }|
@@ -6237,27 +6243,53 @@ describe('float window', function()
local function test_float_mouse_no_focus()
api.nvim_buf_set_lines(0, -1, -1, true, { 'a' })
expected_pos[4][6] = false
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
- screen:expect {
- grid = [[
- ## grid 1
- [2:----------------------------------------]|*6
- [3:----------------------------------------]|
- ## grid 2
- ^x |
- a |
- {0:~ }|*4
- ## grid 3
- |
- ## grid 4
- {1:y }|
- {2:~ }|
- ]],
- float_pos = expected_pos,
- }
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
+ end
+ if multigrid then
+ if send_mouse_grid then
+ -- Sending input to grid 4 is a user error, you are not supposed to pass a grid
+ -- that isn't focusable. In this case, nothing happens and the input is not passed
+ -- through to grid 4, like normally happens when you pass grid 0.
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:----------------------------------------]|*6
+ [3:----------------------------------------]|
+ ## grid 2
+ ^x |
+ a |
+ {0:~ }|*4
+ ## grid 3
+ |
+ ## grid 4
+ {1:y }|
+ {2:~ }|
+ ]],
+ float_pos = expected_pos,
+ }
+ else
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:----------------------------------------]|*6
+ [3:----------------------------------------]|
+ ## grid 2
+ x |
+ ^a |
+ {0:~ }|*4
+ ## grid 3
+ |
+ ## grid 4
+ {1:y }|
+ {2:~ }|
+ ]],
+ float_pos = expected_pos,
+ }
+ end
+ else
screen:expect([[
x |
^a |
@@ -6268,8 +6300,12 @@ describe('float window', function()
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ end
+ if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -6289,7 +6325,6 @@ describe('float window', function()
unchanged = true,
}
else
- api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
^x |
a |
@@ -7959,7 +7994,11 @@ describe('float window', function()
},
}
- api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
+ end
screen:expect {
grid = [[
## grid 1
@@ -7982,7 +8021,11 @@ describe('float window', function()
},
}
- api.nvim_input_mouse('left', 'drag', '', 4, 1, 2)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'drag', '', 4, 1, 2)
+ else
+ api.nvim_input_mouse('left', 'drag', '', 0, 3, 7)
+ end
screen:expect {
grid = [[
## grid 1
@@ -8074,7 +8117,11 @@ describe('float window', function()
},
}
- api.nvim_input_mouse('left', 'press', '', 4, 1, 1)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 1)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 6)
+ end
screen:expect {
grid = [[
## grid 1
@@ -8099,7 +8146,11 @@ describe('float window', function()
},
}
- api.nvim_input_mouse('left', 'drag', '', 4, 2, 3)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'drag', '', 4, 2, 3)
+ else
+ api.nvim_input_mouse('left', 'drag', '', 0, 2, 8)
+ end
screen:expect {
grid = [[
## grid 1
@@ -8193,7 +8244,11 @@ describe('float window', function()
},
}
- api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
+ end
screen:expect {
grid = [[
## grid 1
@@ -8217,7 +8272,11 @@ describe('float window', function()
},
}
- api.nvim_input_mouse('left', 'drag', '', 4, 2, 2)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'drag', '', 4, 2, 2)
+ else
+ api.nvim_input_mouse('left', 'drag', '', 0, 3, 7)
+ end
screen:expect {
grid = [[
## grid 1
@@ -8304,7 +8363,11 @@ describe('float window', function()
{0:~ }|*2
]])
- api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 22)
+ end
screen:expect([[
## grid 1
[2:-------------------]{5:│}[4:--------------------]|*5
@@ -8322,7 +8385,11 @@ describe('float window', function()
{0:~ }|*2
]])
- api.nvim_input_mouse('left', 'drag', '', 4, 1, 1)
+ if send_mouse_grid then
+ api.nvim_input_mouse('left', 'drag', '', 4, 1, 1)
+ else
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 21)
+ end
screen:expect([[
## grid 1
[2:-------------------]{5:│}[4:--------------------]|*5
@@ -8409,21 +8476,21 @@ describe('float window', function()
}
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 3, 1)
else
api.nvim_input_mouse('left', 'press', '', 0, 3, 6)
end
eq({ 0, 3, 1, 0, 1 }, fn.getcurpos())
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 3, 2)
else
api.nvim_input_mouse('left', 'press', '', 0, 3, 7)
end
eq({ 0, 3, 1, 0, 2 }, fn.getcurpos())
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 3, 10)
else
api.nvim_input_mouse('left', 'press', '', 0, 3, 15)
@@ -8470,8 +8537,12 @@ describe('float window', function()
}
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 1)
+ else
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
+ end
+ if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -8496,7 +8567,6 @@ describe('float window', function()
},
}
else
- api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
screen:expect {
grid = [[
{5:┌────────────────────┐} |
@@ -8510,21 +8580,21 @@ describe('float window', function()
}
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 7)
end
eq({ 0, 2, 1, 0, 1 }, fn.getcurpos())
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 3)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 8)
end
eq({ 0, 2, 1, 0, 2 }, fn.getcurpos())
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 11)
else
api.nvim_input_mouse('left', 'press', '', 0, 2, 16)
@@ -8840,8 +8910,12 @@ describe('float window', function()
end
-- Test scrolling by mouse
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 4, 2, 2)
+ else
+ api.nvim_input_mouse('wheel', 'down', '', 0, 4, 7)
+ end
+ if multigrid then
screen:expect {
grid = [[
## grid 1
@@ -8865,7 +8939,6 @@ describe('float window', function()
float_pos = { [4] = { 1001, 'NW', 1, 2, 5, true, 50, 1, 2, 5 } },
}
else
- api.nvim_input_mouse('wheel', 'down', '', 0, 4, 7)
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
@@ -11047,10 +11120,15 @@ describe('float window', function()
end)
end
- describe('with ext_multigrid', function()
- with_ext_multigrid(true)
+ describe('with ext_multigrid and actual mouse grid', function()
+ with_ext_multigrid(true, true)
end)
+
+ describe('with ext_multigrid and mouse grid 0', function()
+ with_ext_multigrid(true, false)
+ end)
+
describe('without ext_multigrid', function()
- with_ext_multigrid(false)
+ with_ext_multigrid(false, false)
end)
end)
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
@@ -10,1882 +10,1869 @@ local command = n.command
local exec = n.exec
describe('ui/mouse/input', function()
- local screen
-
- before_each(function()
- clear()
- api.nvim_set_option_value('mouse', 'a', {})
- api.nvim_set_option_value('list', true, {})
- -- NB: this is weird, but mostly irrelevant to the test
- -- So I didn't bother to change it
- command('set listchars=eol:$')
- command('setl listchars=nbsp:x')
- screen = Screen.new(25, 5)
- screen:add_extra_attr_ids {
- [100] = {
- bold = true,
- background = Screen.colors.LightGrey,
- foreground = Screen.colors.Blue1,
- },
- }
- command('set mousemodel=extend')
- feed('itesting<cr>mouse<cr>support and selection<esc>')
- screen:expect({
- any = {
- 'testing ',
- 'mouse ',
- 'support and selectio%^n ',
- },
- })
- end)
-
- it('single left click moves cursor', function()
- feed('<LeftMouse><2,1>')
- screen:expect({
- any = 'mo%^use',
- mouse_enabled = true,
- })
- feed('<LeftMouse><0,0>')
- screen:expect({
- any = '%^testing',
- })
- end)
+ local function with_ext_multigrid(multigrid)
+ local screen
- it("in external ui works with unset 'mouse'", function()
- api.nvim_set_option_value('mouse', '', {})
- feed('<LeftMouse><2,1>')
- screen:expect({
- any = 'mo%^use',
- mouse_enabled = false,
- })
- feed('<LeftMouse><0,0>')
- screen:expect({
- any = '%^testing',
- })
- end)
+ before_each(function()
+ clear()
+ api.nvim_set_option_value('mouse', 'a', {})
+ api.nvim_set_option_value('list', true, {})
+ -- NB: this is weird, but mostly irrelevant to the test
+ -- So I didn't bother to change it
+ command('set listchars=eol:$')
+ command('setl listchars=nbsp:x')
- it('double left click enters visual mode', function()
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- screen:expect({
- any = {
- '{17:testin}%^g',
- 'VISUAL',
- },
- })
- end)
+ screen = Screen.new(25, 5, { ext_multigrid = multigrid })
+ screen:add_extra_attr_ids {
+ [100] = {
+ bold = true,
+ background = Screen.colors.LightGrey,
+ foreground = Screen.colors.Blue1,
+ },
+ }
+ command('set mousemodel=extend')
+ feed('itesting<cr>mouse<cr>support and selection<esc>')
+ screen:expect({
+ any = {
+ 'testing ',
+ 'mouse ',
+ 'support and selectio%^n ',
+ },
+ })
+ end)
- it('triple left click enters visual line mode', function()
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- screen:expect({
- any = {
- '%^t{17:esting}',
- 'VISUAL LINE',
- },
- })
- end)
+ it('single left click moves cursor', function()
+ feed('<LeftMouse><2,1>')
+ screen:expect({
+ any = 'mo%^use',
+ mouse_enabled = true,
+ })
+ feed('<LeftMouse><0,0>')
+ screen:expect({
+ any = '%^testing',
+ })
+ end)
- it('quadruple left click enters visual block mode', function()
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- feed('<LeftMouse><0,0>')
- feed('<LeftRelease><0,0>')
- screen:expect({
- any = {
- '%^testing',
- 'VISUAL BLOCK',
- },
- })
- end)
+ it("in external ui works with unset 'mouse'", function()
+ api.nvim_set_option_value('mouse', '', {})
+ feed('<LeftMouse><2,1>')
+ screen:expect({
+ any = 'mo%^use',
+ mouse_enabled = false,
+ })
+ feed('<LeftMouse><0,0>')
+ screen:expect({
+ any = '%^testing',
+ })
+ end)
- describe('tab drag', function()
- it('in tabline on filler space moves tab to the end', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ it('double left click enters visual mode', function()
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ '{17:testin}%^g',
+ 'VISUAL',
},
})
- feed('<LeftMouse><4,0>')
+ end)
+
+ it('triple left click enters visual line mode', function()
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ '%^t{17:esting}',
+ 'VISUAL LINE',
},
})
- feed('<LeftDrag><14,0>')
+ end)
+
+ it('quadruple left click enters visual block mode', function()
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
+ feed('<LeftMouse><0,0>')
+ feed('<LeftRelease><0,0>')
screen:expect({
any = {
- '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
- 'this is fo%^o',
+ '%^testing',
+ 'VISUAL BLOCK',
},
})
end)
- it('in tabline to the left moves tab left', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ describe('tab drag', function()
+ it('in tabline on filler space moves tab to the end', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><4,0>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ feed('<LeftDrag><14,0>')
+ screen:expect({
+ any = {
+ '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ end)
+
+ it('in tabline to the left moves tab left', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><11,0>')
+ -- Prevent the case where screen:expect() with "unchanged" returns too early,
+ -- causing the click position to be overwritten by the next drag.
+ poke_eventloop()
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ unchanged = true,
+ })
+ feed('<LeftDrag><6,0>')
+ screen:expect({
+ any = {
+ '{5: %+ bar }{24: %+ foo }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ end)
+
+ it('in tabline to the right moves tab right', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><4,0>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ feed('<LeftDrag><7,0>')
+ screen:expect({
+ any = {
+ '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ end)
+
+ it('out of tabline under filler space moves tab to the end', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><4,0>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ feed('<LeftDrag><4,1>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ unchanged = true,
+ })
+ feed('<LeftDrag><14,1>')
+ screen:expect({
+ any = {
+ '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ end)
+
+ it('out of tabline to the left moves tab left', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><11,0>')
+ -- Prevent the case where screen:expect() with "unchanged" returns too early,
+ -- causing the click position to be overwritten by the next drag.
+ poke_eventloop()
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ unchanged = true,
+ })
+ feed('<LeftDrag><11,1>')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ unchanged = true,
+ })
+ feed('<LeftDrag><6,1>')
+ screen:expect({
+ any = {
+ '{5: %+ bar }{24: %+ foo }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ end)
+
+ it('out of tabline to the right moves tab right', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><4,0>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ feed('<LeftDrag><4,1>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ unchanged = true,
+ })
+ feed('<LeftDrag><7,1>')
+ screen:expect({
+ any = {
+ '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ end)
+ end)
+
+ describe('tabline', function()
+ it('left click in default tabline (tabpage label) switches to tab', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><4,0>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ feed('<LeftMouse><6,0>')
+ screen:expect_unchanged()
+ feed('<LeftMouse><10,0>')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><12,0>')
+ screen:expect_unchanged()
+ end)
+
+ it('left click in default tabline (blank space) switches tab', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><20,0>')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
+ 'this is fo%^o',
+ },
+ })
+ feed('<LeftMouse><22,0>')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ end)
+
+ it('left click in default tabline (close label) closes tab', function()
+ api.nvim_set_option_value('hidden', true, {})
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<LeftMouse><24,0>')
+ screen:expect({
+ any = {
+ 'this is fo%^o',
+ },
+ none = {
+ '{24:X}',
+ '%+ foo',
+ '%+ bar',
+ },
+ })
+ end)
+
+ it('double click in default tabline opens new tab before', function()
+ feed_command('%delete')
+ insert('this is foo')
+ feed_command('silent file foo | tabnew | file bar')
+ insert('this is bar')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:%$}',
+ },
+ })
+ feed('<2-LeftMouse><4,0>')
+ screen:expect({
+ any = {
+ '{5: Name] }{24: %+ foo %+ bar }{2: }{24:X}|',
+ '{1:%^$}',
+ },
+ })
+ command('tabclose')
+ screen:expect({
+ any = {
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}|',
+ 'this is fo%^o',
+ },
+ })
+ feed('<2-LeftMouse><20,0>')
+ screen:expect({
+ any = {
+ '{24: %+ foo %+ bar }{5: Name] }{2: }{24:X}',
+ '{1:%^$}',
+ },
+ })
+ command('tabclose')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ 'this is ba%^r{1:$}',
+ },
+ })
+ feed('<2-LeftMouse><10,0>')
+ screen:expect({
+ any = {
+ '{24: %+ foo }{5: Name] }{24: %+ bar }{2: }{24:X}',
+ '{1:%^$}',
+ },
+ })
+ end)
+
+ describe('%@ label', function()
+ before_each(function()
+ feed_command([[
+ function Test(...)
+ let g:reply = a:000
+ return copy(a:000) " Check for memory leaks: return should be freed
+ endfunction
+ ]])
+ feed_command([[
+ function Test2(...)
+ return call('Test', a:000 + [2])
+ endfunction
+ ]])
+ api.nvim_set_option_value('tabline', '%@Test@test%X-%5@Test2@test2', {})
+ api.nvim_set_option_value('showtabline', 2, {})
+ screen:expect({
+ any = {
+ '{2:test%-test2 }',
+ 'testing',
+ 'mouse',
+ 'support and selectio%^n',
+ },
+ })
+ api.nvim_set_var('reply', {})
+ end)
+
+ local check_reply = function(expected)
+ eq(expected, api.nvim_get_var('reply'))
+ api.nvim_set_var('reply', {})
+ end
+
+ local test_click = function(name, click_str, click_num, mouse_button, modifiers)
+ local function doit(do_click)
+ eq(1, fn.has('tablineat'))
+ do_click(0, 3)
+ check_reply({ 0, click_num, mouse_button, modifiers })
+ do_click(0, 4)
+ check_reply({})
+ do_click(0, 6)
+ check_reply({ 5, click_num, mouse_button, modifiers, 2 })
+ do_click(0, 13)
+ check_reply({ 5, click_num, mouse_button, modifiers, 2 })
+ end
+
+ it(name .. ' works (pseudokey)', function()
+ doit(function(row, col)
+ feed(click_str .. '<' .. col .. ',' .. row .. '>')
+ end)
+ end)
+
+ it(name .. ' works (nvim_input_mouse)', function()
+ doit(function(row, col)
+ local buttons = { l = 'left', m = 'middle', r = 'right' }
+ local modstr = (click_num > 1) and tostring(click_num) or ''
+ for char in string.gmatch(modifiers, '%w') do
+ modstr = modstr .. char .. '-' -- - not needed but should be accepted
+ end
+ api.nvim_input_mouse(buttons[mouse_button], 'press', modstr, 0, row, col)
+ end)
+ end)
+ end
+
+ test_click('single left click', '<LeftMouse>', 1, 'l', ' ')
+ test_click('shifted single left click', '<S-LeftMouse>', 1, 'l', 's ')
+ test_click('shifted single left click with alt modifier', '<S-A-LeftMouse>', 1, 'l', 's a ')
+ test_click(
+ 'shifted single left click with alt and ctrl modifiers',
+ '<S-C-A-LeftMouse>',
+ 1,
+ 'l',
+ 'sca '
+ )
+ -- <C-RightMouse> does not work
+ test_click(
+ 'shifted single right click with alt modifier',
+ '<S-A-RightMouse>',
+ 1,
+ 'r',
+ 's a '
+ )
+ -- Modifiers do not work with MiddleMouse
+ test_click(
+ 'shifted single middle click with alt and ctrl modifiers',
+ '<MiddleMouse>',
+ 1,
+ 'm',
+ ' '
+ )
+ -- Modifiers do not work with N-*Mouse
+ test_click('double left click', '<2-LeftMouse>', 2, 'l', ' ')
+ test_click('triple left click', '<3-LeftMouse>', 3, 'l', ' ')
+ test_click('quadruple left click', '<4-LeftMouse>', 4, 'l', ' ')
+ test_click('double right click', '<2-RightMouse>', 2, 'r', ' ')
+ test_click('triple right click', '<3-RightMouse>', 3, 'r', ' ')
+ test_click('quadruple right click', '<4-RightMouse>', 4, 'r', ' ')
+ test_click('double middle click', '<2-MiddleMouse>', 2, 'm', ' ')
+ test_click('triple middle click', '<3-MiddleMouse>', 3, 'm', ' ')
+ test_click('quadruple middle click', '<4-MiddleMouse>', 4, 'm', ' ')
+ end)
+ end)
+
+ it('left drag changes visual selection', function()
+ -- drag events must be preceded by a click
+ feed('<LeftMouse><2,1>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mo%^use',
+ 'support and selection',
},
})
- feed('<LeftMouse><11,0>')
- -- Prevent the case where screen:expect() with "unchanged" returns too early,
- -- causing the click position to be overwritten by the next drag.
- poke_eventloop()
+ feed('<LeftDrag><4,1>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mo{17:us}%^e',
+ 'support and selection',
+ 'VISUAL',
+ },
+ })
+ feed('<LeftDrag><2,2>')
+ screen:expect({
+ any = {
+ 'testing',
+ 'mo{17:use}',
+ '{17:su}%^pport and selection',
+ 'VISUAL',
},
- unchanged = true,
})
- feed('<LeftDrag><6,0>')
+ feed('<LeftDrag><0,0>')
screen:expect({
any = {
- '{5: %+ bar }{24: %+ foo }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ '%^t{17:esting}',
+ '{17:mou}se ',
+ 'support and selection',
+ 'VISUAL',
},
})
end)
- it('in tabline to the right moves tab right', function()
- feed_command('%delete')
- insert('this is foo')
+ it('left drag changes visual selection after tab click', function()
feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
+ feed_command('tabprevious') -- go to first tab
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ '{5: %+ foo }{24: %+ bar }{2: }{24:X}|',
+ 'testing',
+ 'mouse',
+ 'support and selectio%^n',
+ ':tabprevious',
},
})
- feed('<LeftMouse><4,0>')
+ feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab
+ n.poke_eventloop()
+ feed('<LeftMouse><0,1>')
+ -- This text is hidden when using multigrid
+ local none = {
+ 'mouse',
+ 'support and selection',
+ }
+ if multigrid then
+ none = nil
+ end
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ '%^this is bar{1:%$}',
+ ':tabprevious',
},
+ none = none,
})
- feed('<LeftDrag><7,0>')
+ feed('<LeftDrag><4,1>')
screen:expect({
any = {
- '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
- 'this is fo%^o',
+ '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
+ '{17:this}%^ is bar{1:%$}',
+ 'VISUAL',
},
})
end)
- it('out of tabline under filler space moves tab to the end', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
- screen:expect({
- any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
- },
- })
- feed('<LeftMouse><4,0>')
+ it('left drag changes visual selection in split layout', function()
+ screen:try_resize(53, 14)
+ command('set mouse=a')
+ command('vsplit')
+ command('wincmd l')
+ command('below split')
+ command('enew')
+ feed('ifoo\nbar<esc>')
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ 'foo{1:%$}',
+ 'ba%^r{1:%$}',
},
})
- feed('<LeftDrag><4,1>')
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 27)
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ '%^foo{1:%$}',
+ 'bar{1:%$}',
},
- unchanged = true,
})
- feed('<LeftDrag><14,1>')
+ api.nvim_input_mouse('left', 'drag', '', 0, 7, 30)
screen:expect({
any = {
- '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
- 'this is fo%^o',
+ '{17:foo}{100:%$}',
+ '{17:bar}{1:%^%$}',
+ 'VISUAL',
},
})
end)
- it('out of tabline to the left moves tab left', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ it('two clicks will enter VISUAL and dragging selects words', function()
+ feed('<LeftMouse><2,2>')
+ feed('<LeftRelease><2,2>')
+ feed('<LeftMouse><2,2>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mouse',
+ '{17:suppor}%^t and selection',
+ 'VISUAL',
},
})
- feed('<LeftMouse><11,0>')
- -- Prevent the case where screen:expect() with "unchanged" returns too early,
- -- causing the click position to be overwritten by the next drag.
- poke_eventloop()
+ feed('<LeftDrag><0,1>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ '%^m{17:ouse}',
+ '{17:support} and selection',
+ 'VISUAL',
},
- unchanged = true,
})
- feed('<LeftDrag><11,1>')
+ feed('<LeftDrag><4,0>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ '%^t{17:esting}',
+ '{17:mouse}',
+ '{17:support} and selection',
+ 'VISUAL',
},
- unchanged = true,
})
- feed('<LeftDrag><6,1>')
+ feed('<LeftDrag><14,2>')
screen:expect({
any = {
- '{5: %+ bar }{24: %+ foo }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mouse',
+ '{17:support and selectio}%^n',
+ 'VISUAL',
},
})
end)
- it('out of tabline to the right moves tab right', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ it('three clicks will enter VISUAL LINE and dragging selects lines', function()
+ feed('<LeftMouse><2,2>')
+ feed('<LeftRelease><2,2>')
+ feed('<LeftMouse><2,2>')
+ feed('<LeftRelease><2,2>')
+ feed('<LeftMouse><2,2>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mouse',
+ '{17:su}%^p{17:port and selection}',
+ 'VISUAL LINE',
},
})
- feed('<LeftMouse><4,0>')
+ feed('<LeftDrag><0,1>')
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ 'testing',
+ '%^m{17:ouse}',
+ '{17:support and selection}',
+ 'VISUAL LINE',
},
})
- feed('<LeftDrag><4,1>')
+ feed('<LeftDrag><4,0>')
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ '{17:test}%^i{17:ng}',
+ '{17:mouse}',
+ '{17:support and selection}',
+ 'VISUAL LINE',
},
- unchanged = true,
})
- feed('<LeftDrag><7,1>')
+ feed('<LeftDrag><14,2>')
screen:expect({
any = {
- '{24: %+ bar }{5: %+ foo }{2: }{24:X}',
- 'this is fo%^o',
+ 'testing',
+ 'mouse',
+ '{17:support and se}%^l{17:ection}',
+ 'VISUAL LINE',
},
})
end)
- end)
- describe('tabline', function()
- it('left click in default tabline (tabpage label) switches to tab', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ it('four clicks will enter VISUAL BLOCK and dragging selects blockwise', function()
+ feed('<LeftMouse><2,2>')
+ feed('<LeftRelease><2,2>')
+ feed('<LeftMouse><2,2>')
+ feed('<LeftRelease><2,2>')
+ feed('<LeftMouse><2,2>')
+ feed('<LeftRelease><2,2>')
+ feed('<LeftMouse><2,2>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mouse',
+ 'su%^pport and selection',
+ 'VISUAL BLOCK',
},
})
- feed('<LeftMouse><4,0>')
+ feed('<LeftDrag><0,1>')
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ 'testing',
+ '%^m{17:ou}se',
+ '{17:sup}port and selection',
+ 'VISUAL BLOCK',
},
})
- feed('<LeftMouse><6,0>')
- screen:expect_unchanged()
- feed('<LeftMouse><10,0>')
+ feed('<LeftDrag><4,0>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'te{17:st}%^ing',
+ 'mo{17:use}',
+ 'su{17:ppo}rt and selection',
+ 'VISUAL BLOCK',
},
})
- feed('<LeftMouse><12,0>')
- screen:expect_unchanged()
- end)
-
- it('left click in default tabline (blank space) switches tab', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ feed('<LeftDrag><14,2>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing',
+ 'mouse',
+ 'su{17:pport and se}%^lection',
+ 'VISUAL BLOCK',
},
})
- feed('<LeftMouse><20,0>')
+ end)
+
+ it('right click extends visual selection to the clicked location', function()
+ feed('<LeftMouse><0,0>')
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}',
- 'this is fo%^o',
+ '%^testing',
+ 'mouse',
+ 'support and selection',
},
})
- feed('<LeftMouse><22,0>')
+ feed('<RightMouse><2,2>')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ '{17:testing}',
+ '{17:mouse}',
+ '{17:su}^pport and selection',
+ 'VISUAL',
},
})
end)
- it('left click in default tabline (close label) closes tab', function()
- api.nvim_set_option_value('hidden', true, {})
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
- screen:expect({
- any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
- },
- })
- feed('<LeftMouse><24,0>')
+ it('ctrl + left click will search for a tag', function()
+ api.nvim_set_option_value('tags', './non-existent-tags-file', {})
+ feed('<C-LeftMouse><0,0>')
screen:expect({
any = {
- 'this is fo%^o',
- },
- none = {
- '{24:X}',
- '%+ foo',
- '%+ bar',
+ '{9:E433: No tags file}',
+ '{9:E426: Tag not found: test}',
+ '{9:ing}',
+ '{6:Press ENTER or type comma}',
+ '{6:nd to continue}%^',
},
})
+ feed('<cr>')
end)
- it('double click in default tabline opens new tab before', function()
- feed_command('%delete')
- insert('this is foo')
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
+ it('x1 and x2 can be triggered by api', function()
+ api.nvim_set_var('x1_pressed', 0)
+ api.nvim_set_var('x1_released', 0)
+ api.nvim_set_var('x2_pressed', 0)
+ api.nvim_set_var('x2_released', 0)
+ command('nnoremap <X1Mouse> <Cmd>let g:x1_pressed += 1<CR>')
+ command('nnoremap <X1Release> <Cmd>let g:x1_released += 1<CR>')
+ command('nnoremap <X2Mouse> <Cmd>let g:x2_pressed += 1<CR>')
+ command('nnoremap <X2Release> <Cmd>let g:x2_released += 1<CR>')
+ api.nvim_input_mouse('x1', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('x1', 'release', '', 0, 0, 0)
+ api.nvim_input_mouse('x2', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('x2', 'release', '', 0, 0, 0)
+ eq(1, api.nvim_get_var('x1_pressed'), 'x1 pressed once')
+ eq(1, api.nvim_get_var('x1_released'), 'x1 released once')
+ eq(1, api.nvim_get_var('x2_pressed'), 'x2 pressed once')
+ eq(1, api.nvim_get_var('x2_released'), 'x2 released once')
+ end)
+
+ it('dragging vertical separator', function()
+ screen:try_resize(45, 5)
+ command('setlocal nowrap')
+ local oldwin = api.nvim_get_current_win()
+ command('rightbelow vnew')
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:%$}',
+ 'testing ',
+ 'mouse ',
+ 'support and selection ',
+ '{1:%^%$} ',
+ '{2:%[No Name%] %[%+%] }{3:%[No Name%] }',
},
})
- feed('<2-LeftMouse><4,0>')
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
+ poke_eventloop()
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
screen:expect({
any = {
- '{5: Name] }{24: %+ foo %+ bar }{2: }{24:X}|',
- '{1:%^$}',
+ 'testing ',
+ 'mouse ',
+ 'support and ',
+ '{1:%^$} ',
+ '{2:< Name%] %[%+%] }{3:%[No Name%] }',
},
})
- command('tabclose')
+ api.nvim_input_mouse('left', 'drag', '', 0, 2, 2)
screen:expect({
any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}|',
- 'this is fo%^o',
+ 'te',
+ 'mo',
+ 'su',
+ '{1:%^%$} ',
+ '{2:< }{3:%[No Name%] }',
},
})
- feed('<2-LeftMouse><20,0>')
+ api.nvim_input_mouse('left', 'release', '', 0, 2, 2)
+ api.nvim_set_option_value('statuscolumn', 'foobar', { win = oldwin })
screen:expect({
any = {
- '{24: %+ foo %+ bar }{5: Name] }{2: }{24:X}',
- '{1:%^$}',
+ '{8:fo}',
+ '{1:%^%$} ',
+ '{2:< }{3:%[No Name%] }',
},
})
- command('tabclose')
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 2)
+ poke_eventloop()
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
screen:expect({
any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- 'this is ba%^r{1:$}',
+ '{8:foobar}testin',
+ '{8:foobar}mouse ',
+ '{8:foobar}suppor',
+ '{1:%^%$} ',
+ '{2:< Name%] %[%+%] }{3:%[No Name%] }',
},
})
- feed('<2-LeftMouse><10,0>')
+ api.nvim_input_mouse('left', 'drag', '', 0, 2, 22)
screen:expect({
any = {
- '{24: %+ foo }{5: Name] }{24: %+ bar }{2: }{24:X}',
- '{1:%^$}',
+ '{8:foobar}testing ',
+ '{8:foobar}mouse ',
+ '{8:foobar}support and sele',
+ '{1:%^%$} ',
+ '{2:%[No Name%] %[%+%] }{3:%[No Name%] }',
},
})
+ api.nvim_input_mouse('left', 'release', '', 0, 2, 22)
end)
- describe('%@ label', function()
- before_each(function()
- feed_command([[
- function Test(...)
- let g:reply = a:000
- return copy(a:000) " Check for memory leaks: return should be freed
- endfunction
- ]])
- feed_command([[
- function Test2(...)
- return call('Test', a:000 + [2])
- endfunction
- ]])
- api.nvim_set_option_value('tabline', '%@Test@test%X-%5@Test2@test2', {})
- api.nvim_set_option_value('showtabline', 2, {})
- screen:expect({
- any = {
- '{2:test%-test2 }',
- 'testing',
- 'mouse',
- 'support and selectio%^n',
- },
- })
- api.nvim_set_var('reply', {})
- end)
-
- local check_reply = function(expected)
- eq(expected, api.nvim_get_var('reply'))
- api.nvim_set_var('reply', {})
- end
-
- local test_click = function(name, click_str, click_num, mouse_button, modifiers)
- local function doit(do_click)
- eq(1, fn.has('tablineat'))
- do_click(0, 3)
- check_reply({ 0, click_num, mouse_button, modifiers })
- do_click(0, 4)
- check_reply({})
- do_click(0, 6)
- check_reply({ 5, click_num, mouse_button, modifiers, 2 })
- do_click(0, 13)
- check_reply({ 5, click_num, mouse_button, modifiers, 2 })
- end
-
- it(name .. ' works (pseudokey)', function()
- doit(function(row, col)
- feed(click_str .. '<' .. col .. ',' .. row .. '>')
- end)
- end)
-
- it(name .. ' works (nvim_input_mouse)', function()
- doit(function(row, col)
- local buttons = { l = 'left', m = 'middle', r = 'right' }
- local modstr = (click_num > 1) and tostring(click_num) or ''
- for char in string.gmatch(modifiers, '%w') do
- modstr = modstr .. char .. '-' -- - not needed but should be accepted
- end
- api.nvim_input_mouse(buttons[mouse_button], 'press', modstr, 0, row, col)
- end)
- end)
+ local function wheel(use_api)
+ feed('ggdG')
+ insert([[
+ Inserting
+ text
+ with
+ many
+ lines
+ to
+ test
+ mouse scrolling
+ ]])
+ screen:try_resize(53, 14)
+ feed('k')
+ api.nvim_set_option_value('statuscolumn', 'C', { win = api.nvim_get_current_win() })
+ feed_command('sp')
+ api.nvim_set_option_value('statuscolumn', 'B', { win = api.nvim_get_current_win() })
+ feed_command('vsp')
+ api.nvim_set_option_value('statuscolumn', 'A', { win = api.nvim_get_current_win() })
+ screen:expect({
+ any = {
+ '{8:A}lines ',
+ '{8:A}to ',
+ '{8:A}test ',
+ '{8:A}^mouse scrolling ',
+ '{8:B}lines ',
+ '{8:B}to ',
+ '{8:B}test ',
+ '{8:B}mouse scrolling ',
+ '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
+ '{8:C}to ',
+ '{8:C}test ',
+ '{8:C}mouse scrolling ',
+ '{2:%[No Name%] %[%+%] }',
+ },
+ none = {
+ '{8:A}Inserting',
+ '{8:A}text',
+ '{8:A}with',
+ '{8:A}many',
+ '{8:B}Inserting',
+ '{8:B}text',
+ '{8:B}with',
+ '{8:B}many',
+ '{8:C}Inserting',
+ '{8:C}text',
+ '{8:C}with',
+ '{8:C}many',
+ '{8:C}lines',
+ },
+ })
+ if use_api then
+ api.nvim_input_mouse('wheel', 'down', '', 0, 0, 0)
+ else
+ feed('<ScrollWheelDown><0,0>')
end
-
- test_click('single left click', '<LeftMouse>', 1, 'l', ' ')
- test_click('shifted single left click', '<S-LeftMouse>', 1, 'l', 's ')
- test_click('shifted single left click with alt modifier', '<S-A-LeftMouse>', 1, 'l', 's a ')
- test_click(
- 'shifted single left click with alt and ctrl modifiers',
- '<S-C-A-LeftMouse>',
- 1,
- 'l',
- 'sca '
- )
- -- <C-RightMouse> does not work
- test_click('shifted single right click with alt modifier', '<S-A-RightMouse>', 1, 'r', 's a ')
- -- Modifiers do not work with MiddleMouse
- test_click(
- 'shifted single middle click with alt and ctrl modifiers',
- '<MiddleMouse>',
- 1,
- 'm',
- ' '
- )
- -- Modifiers do not work with N-*Mouse
- test_click('double left click', '<2-LeftMouse>', 2, 'l', ' ')
- test_click('triple left click', '<3-LeftMouse>', 3, 'l', ' ')
- test_click('quadruple left click', '<4-LeftMouse>', 4, 'l', ' ')
- test_click('double right click', '<2-RightMouse>', 2, 'r', ' ')
- test_click('triple right click', '<3-RightMouse>', 3, 'r', ' ')
- test_click('quadruple right click', '<4-RightMouse>', 4, 'r', ' ')
- test_click('double middle click', '<2-MiddleMouse>', 2, 'm', ' ')
- test_click('triple middle click', '<3-MiddleMouse>', 3, 'm', ' ')
- test_click('quadruple middle click', '<4-MiddleMouse>', 4, 'm', ' ')
- end)
- end)
-
- it('left drag changes visual selection', function()
- -- drag events must be preceded by a click
- feed('<LeftMouse><2,1>')
- screen:expect({
- any = {
- 'testing',
- 'mo%^use',
- 'support and selection',
- },
- })
- feed('<LeftDrag><4,1>')
- screen:expect({
- any = {
- 'testing',
- 'mo{17:us}%^e',
- 'support and selection',
- 'VISUAL',
- },
- })
- feed('<LeftDrag><2,2>')
- screen:expect({
- any = {
- 'testing',
- 'mo{17:use}',
- '{17:su}%^pport and selection',
- 'VISUAL',
- },
- })
- feed('<LeftDrag><0,0>')
- screen:expect({
- any = {
- '%^t{17:esting}',
- '{17:mou}se ',
- 'support and selection',
- 'VISUAL',
- },
- })
- end)
-
- it('left drag changes visual selection after tab click', function()
- feed_command('silent file foo | tabnew | file bar')
- insert('this is bar')
- feed_command('tabprevious') -- go to first tab
- screen:expect({
- any = {
- '{5: %+ foo }{24: %+ bar }{2: }{24:X}|',
- 'testing',
- 'mouse',
- 'support and selectio%^n',
- ':tabprevious',
- },
- })
- feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab
- n.poke_eventloop()
- feed('<LeftMouse><0,1>')
- screen:expect({
- any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- '%^this is bar{1:%$}',
- ':tabprevious',
- },
- none = {
- 'mouse',
- 'support and selection',
- },
- })
- feed('<LeftDrag><4,1>')
- screen:expect({
- any = {
- '{24: %+ foo }{5: %+ bar }{2: }{24:X}',
- '{17:this}%^ is bar{1:%$}',
- 'VISUAL',
- },
- })
- end)
-
- it('left drag changes visual selection in split layout', function()
- screen:try_resize(53, 14)
- command('set mouse=a')
- command('vsplit')
- command('wincmd l')
- command('below split')
- command('enew')
- feed('ifoo\nbar<esc>')
- screen:expect({
- any = {
- 'foo{1:%$}',
- 'ba%^r{1:%$}',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 6, 27)
- screen:expect({
- any = {
- '%^foo{1:%$}',
- 'bar{1:%$}',
- },
- })
- api.nvim_input_mouse('left', 'drag', '', 0, 7, 30)
- screen:expect({
- any = {
- '{17:foo}{100:%$}',
- '{17:bar}{1:%^%$}',
- 'VISUAL',
- },
- })
- end)
-
- it('two clicks will enter VISUAL and dragging selects words', function()
- feed('<LeftMouse><2,2>')
- feed('<LeftRelease><2,2>')
- feed('<LeftMouse><2,2>')
- screen:expect({
- any = {
- 'testing',
- 'mouse',
- '{17:suppor}%^t and selection',
- 'VISUAL',
- },
- })
- feed('<LeftDrag><0,1>')
- screen:expect({
- any = {
- 'testing',
- '%^m{17:ouse}',
- '{17:support} and selection',
- 'VISUAL',
- },
- })
- feed('<LeftDrag><4,0>')
- screen:expect({
- any = {
- '%^t{17:esting}',
- '{17:mouse}',
- '{17:support} and selection',
- 'VISUAL',
- },
- })
- feed('<LeftDrag><14,2>')
- screen:expect({
- any = {
- 'testing',
- 'mouse',
- '{17:support and selectio}%^n',
- 'VISUAL',
- },
- })
- end)
-
- it('three clicks will enter VISUAL LINE and dragging selects lines', function()
- feed('<LeftMouse><2,2>')
- feed('<LeftRelease><2,2>')
- feed('<LeftMouse><2,2>')
- feed('<LeftRelease><2,2>')
- feed('<LeftMouse><2,2>')
- screen:expect({
- any = {
- 'testing',
- 'mouse',
- '{17:su}%^p{17:port and selection}',
- 'VISUAL LINE',
- },
- })
- feed('<LeftDrag><0,1>')
- screen:expect({
- any = {
- 'testing',
- '%^m{17:ouse}',
- '{17:support and selection}',
- 'VISUAL LINE',
- },
- })
- feed('<LeftDrag><4,0>')
- screen:expect({
- any = {
- '{17:test}%^i{17:ng}',
- '{17:mouse}',
- '{17:support and selection}',
- 'VISUAL LINE',
- },
- })
- feed('<LeftDrag><14,2>')
- screen:expect({
- any = {
- 'testing',
- 'mouse',
- '{17:support and se}%^l{17:ection}',
- 'VISUAL LINE',
- },
- })
- end)
-
- it('four clicks will enter VISUAL BLOCK and dragging selects blockwise', function()
- feed('<LeftMouse><2,2>')
- feed('<LeftRelease><2,2>')
- feed('<LeftMouse><2,2>')
- feed('<LeftRelease><2,2>')
- feed('<LeftMouse><2,2>')
- feed('<LeftRelease><2,2>')
- feed('<LeftMouse><2,2>')
- screen:expect({
- any = {
- 'testing',
- 'mouse',
- 'su%^pport and selection',
- 'VISUAL BLOCK',
- },
- })
- feed('<LeftDrag><0,1>')
- screen:expect({
- any = {
- 'testing',
- '%^m{17:ou}se',
- '{17:sup}port and selection',
- 'VISUAL BLOCK',
- },
- })
- feed('<LeftDrag><4,0>')
- screen:expect({
- any = {
- 'te{17:st}%^ing',
- 'mo{17:use}',
- 'su{17:ppo}rt and selection',
- 'VISUAL BLOCK',
- },
- })
- feed('<LeftDrag><14,2>')
- screen:expect({
- any = {
- 'testing',
- 'mouse',
- 'su{17:pport and se}%^lection',
- 'VISUAL BLOCK',
- },
- })
- end)
-
- it('right click extends visual selection to the clicked location', function()
- feed('<LeftMouse><0,0>')
- screen:expect({
- any = {
- '%^testing',
- 'mouse',
- 'support and selection',
- },
- })
- feed('<RightMouse><2,2>')
- screen:expect({
- any = {
- '{17:testing}',
- '{17:mouse}',
- '{17:su}^pport and selection',
- 'VISUAL',
- },
- })
- end)
-
- it('ctrl + left click will search for a tag', function()
- api.nvim_set_option_value('tags', './non-existent-tags-file', {})
- feed('<C-LeftMouse><0,0>')
- screen:expect({
- any = {
- '{9:E433: No tags file}',
- '{9:E426: Tag not found: test}',
- '{9:ing}',
- '{6:Press ENTER or type comma}',
- '{6:nd to continue}%^',
- },
- })
- feed('<cr>')
- end)
-
- it('x1 and x2 can be triggered by api', function()
- api.nvim_set_var('x1_pressed', 0)
- api.nvim_set_var('x1_released', 0)
- api.nvim_set_var('x2_pressed', 0)
- api.nvim_set_var('x2_released', 0)
- command('nnoremap <X1Mouse> <Cmd>let g:x1_pressed += 1<CR>')
- command('nnoremap <X1Release> <Cmd>let g:x1_released += 1<CR>')
- command('nnoremap <X2Mouse> <Cmd>let g:x2_pressed += 1<CR>')
- command('nnoremap <X2Release> <Cmd>let g:x2_released += 1<CR>')
- api.nvim_input_mouse('x1', 'press', '', 0, 0, 0)
- api.nvim_input_mouse('x1', 'release', '', 0, 0, 0)
- api.nvim_input_mouse('x2', 'press', '', 0, 0, 0)
- api.nvim_input_mouse('x2', 'release', '', 0, 0, 0)
- eq(1, api.nvim_get_var('x1_pressed'), 'x1 pressed once')
- eq(1, api.nvim_get_var('x1_released'), 'x1 released once')
- eq(1, api.nvim_get_var('x2_pressed'), 'x2 pressed once')
- eq(1, api.nvim_get_var('x2_released'), 'x2 released once')
- end)
-
- it('dragging vertical separator', function()
- screen:try_resize(45, 5)
- command('setlocal nowrap')
- local oldwin = api.nvim_get_current_win()
- command('rightbelow vnew')
- screen:expect({
- any = {
- 'testing ',
- 'mouse ',
- 'support and selection ',
- '{1:%^%$} ',
- '{2:%[No Name%] %[%+%] }{3:%[No Name%] }',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
- poke_eventloop()
- api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
- screen:expect({
- any = {
- 'testing ',
- 'mouse ',
- 'support and ',
- '{1:%^$} ',
- '{2:< Name%] %[%+%] }{3:%[No Name%] }',
- },
- })
- api.nvim_input_mouse('left', 'drag', '', 0, 2, 2)
- screen:expect({
- any = {
- 'te',
- 'mo',
- 'su',
- '{1:%^%$} ',
- '{2:< }{3:%[No Name%] }',
- },
- })
- api.nvim_input_mouse('left', 'release', '', 0, 2, 2)
- api.nvim_set_option_value('statuscolumn', 'foobar', { win = oldwin })
- screen:expect({
- any = {
- '{8:fo}',
- '{1:%^%$} ',
- '{2:< }{3:%[No Name%] }',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 0, 2)
- poke_eventloop()
- api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
- screen:expect({
- any = {
- '{8:foobar}testin',
- '{8:foobar}mouse ',
- '{8:foobar}suppor',
- '{1:%^%$} ',
- '{2:< Name%] %[%+%] }{3:%[No Name%] }',
- },
- })
- api.nvim_input_mouse('left', 'drag', '', 0, 2, 22)
- screen:expect({
- any = {
- '{8:foobar}testing ',
- '{8:foobar}mouse ',
- '{8:foobar}support and sele',
- '{1:%^%$} ',
- '{2:%[No Name%] %[%+%] }{3:%[No Name%] }',
- },
- })
- api.nvim_input_mouse('left', 'release', '', 0, 2, 22)
- end)
-
- local function wheel(use_api)
- feed('ggdG')
- insert([[
- Inserting
- text
- with
- many
- lines
- to
- test
- mouse scrolling
- ]])
- screen:try_resize(53, 14)
- feed('k')
- api.nvim_set_option_value('statuscolumn', 'C', { win = api.nvim_get_current_win() })
- feed_command('sp')
- api.nvim_set_option_value('statuscolumn', 'B', { win = api.nvim_get_current_win() })
- feed_command('vsp')
- api.nvim_set_option_value('statuscolumn', 'A', { win = api.nvim_get_current_win() })
- screen:expect({
- any = {
- '{8:A}lines ',
- '{8:A}to ',
- '{8:A}test ',
- '{8:A}^mouse scrolling ',
- '{8:B}lines ',
- '{8:B}to ',
- '{8:B}test ',
- '{8:B}mouse scrolling ',
- '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
- '{8:C}to ',
- '{8:C}test ',
- '{8:C}mouse scrolling ',
- '{2:%[No Name%] %[%+%] }',
- },
- none = {
- '{8:A}Inserting',
- '{8:A}text',
- '{8:A}with',
- '{8:A}many',
- '{8:B}Inserting',
- '{8:B}text',
- '{8:B}with',
- '{8:B}many',
- '{8:C}Inserting',
- '{8:C}text',
- '{8:C}with',
- '{8:C}many',
- '{8:C}lines',
- },
- })
- if use_api then
- api.nvim_input_mouse('wheel', 'down', '', 0, 0, 0)
- else
- feed('<ScrollWheelDown><0,0>')
- end
- screen:expect({
- any = {
- '{8:A}^mouse scrolling ',
- '{8:B}lines ',
- '{8:B}to ',
- '{8:B}test ',
- '{8:B}mouse scrolling ',
- '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
- '{8:C}to ',
- '{8:C}test ',
- '{8:C}mouse scrolling ',
- '{2:%[No Name%] %[%+%] }',
- },
- none = {
- '{8:A}lines',
- '{8:A}to',
- '{8:A}test',
- '{8:B}Inserting',
- '{8:B}text',
- '{8:B}with',
- '{8:B}many',
- '{8:C}Inserting',
- '{8:C}text',
- '{8:C}with',
- '{8:C}many',
- '{8:C}lines',
- },
- })
- if use_api then
- api.nvim_input_mouse('wheel', 'up', '', 0, 0, 27)
- else
- feed('<ScrollWheelUp><27,0>')
- end
- screen:expect({
- any = {
- '{8:A}^mouse scrolling ',
- '{8:B}lines ',
- '{8:B}to ',
- '{8:B}test ',
- '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
- '{8:C}to ',
- '{8:C}test ',
- '{8:C}mouse scrolling ',
- '{2:%[No Name%] %[%+%] }',
- },
- none = {
- '{8:A}Inserting',
- '{8:A}text',
- '{8:A}with',
- '{8:A}many',
- '{8:A}lines',
- '{8:A}to',
- '{8:A}test',
- '{8:B}Inserting',
- '{8:B}mouse scrolling',
- '{8:C}Inserting',
- '{8:C}text',
- '{8:C}with',
- '{8:C}many',
- '{8:C}lines',
- },
- })
- if use_api then
- api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
- api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
- else
- feed('<ScrollWheelUp><27,7><ScrollWheelUp>')
- end
- screen:expect({
- any = {
- '{8:A}^mouse scrolling ',
- '{8:B}lines ',
- '{8:B}to ',
- '{8:B}test ',
- '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
- '{8:C}Inserting ',
- '{8:C}text ',
- '{8:C}with ',
- '{8:C}many ',
- '{8:C}lines ',
- '{2:%[No Name%] %[%+%] }',
- },
- none = {
- '{8:A}Inserting',
- '{8:A}text',
- '{8:A}with',
- '{8:A}many',
- '{8:A}lines',
- '{8:A}to',
- '{8:A}test',
- '{8:B}Inserting',
- '{8:B}mouse scrolling',
- '{8:C}to',
- '{8:C}test',
- '{8:C}mouse scrolling',
- },
- })
- end
-
- it('mouse wheel will target the hovered window (pseudokey)', function()
- wheel(false)
- end)
-
- it('mouse wheel will target the hovered window (nvim_input_mouse)', function()
- wheel(true)
- end)
-
- it('horizontal scrolling (pseudokey)', function()
- command('set sidescroll=0')
- feed('<esc>:set nowrap<cr>')
-
- feed('a <esc>17Ab<esc>3Ab<esc>')
- screen:expect({
- any = {
- 'bbbbbbbbbbbbbbb%^b ',
- },
- })
-
- feed('<ScrollWheelLeft><0,0>')
- screen:expect({
- any = {
- 'n bbbbbbbbbbbbbbbbbbb%^b ',
- },
- })
-
- feed('^<ScrollWheelRight><0,0>')
- screen:expect({
- any = {
- 'g ',
- '%^t and selection bbbbbbbbb',
- },
- })
- end)
-
- it('horizontal scrolling (nvim_input_mouse)', function()
- command('set sidescroll=0')
- feed('<esc>:set nowrap<cr>')
-
- feed('a <esc>17Ab<esc>3Ab<esc>')
- screen:expect({
- any = {
- 'bbbbbbbbbbbbbbb%^b ',
- },
- })
-
- api.nvim_input_mouse('wheel', 'left', '', 0, 0, 27)
- screen:expect({
- any = {
- 'n bbbbbbbbbbbbbbbbbbb%^b ',
- },
- })
-
- feed('^')
- api.nvim_input_mouse('wheel', 'right', '', 0, 0, 0)
- screen:expect({
- any = {
- 'g ',
- '%^t and selection bbbbbbbbb',
- },
- })
- end)
-
- it("'sidescrolloff' applies to horizontal scrolling", function()
- command('set nowrap')
- command('set sidescrolloff=4')
-
- feed('I <esc>020ib<esc>0')
- screen:expect({
- any = {
- 'testing ',
- 'mouse ',
- '%^bbbbbbbbbbbbbbbbbbbb supp',
- },
- })
-
- api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
- screen:expect({
- any = {
- 'g ',
- ' ',
- 'bbbb%^bbbbbbbbbb support an',
- },
- })
-
- -- window-local 'sidescrolloff' should override global value. #21162
- command('setlocal sidescrolloff=2')
- feed('0')
- screen:expect({
- any = {
- 'testing ',
- 'mouse ',
- '%^bbbbbbbbbbbbbbbbbbbb supp',
- },
- })
-
- api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
- screen:expect({
- any = {
- 'g ',
- ' ',
- 'bb%^bbbbbbbbbbbb support an',
- },
- })
- end)
-
- local function test_mouse_click_conceal()
- it('(level 1) click on non-wrapped lines', function()
- feed_command('let &conceallevel=1', 'echo')
-
- feed('<esc><LeftMouse><0,0>')
screen:expect({
any = {
- '%^Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ '{8:A}^mouse scrolling ',
+ '{8:B}lines ',
+ '{8:B}to ',
+ '{8:B}test ',
+ '{8:B}mouse scrolling ',
+ '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
+ '{8:C}to ',
+ '{8:C}test ',
+ '{8:C}mouse scrolling ',
+ '{2:%[No Name%] %[%+%] }',
},
- })
-
- feed('<esc><LeftMouse><1,0>')
+ none = {
+ '{8:A}lines',
+ '{8:A}to',
+ '{8:A}test',
+ '{8:B}Inserting',
+ '{8:B}text',
+ '{8:B}with',
+ '{8:B}many',
+ '{8:C}Inserting',
+ '{8:C}text',
+ '{8:C}with',
+ '{8:C}many',
+ '{8:C}lines',
+ },
+ })
+ if use_api then
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 27)
+ else
+ feed('<ScrollWheelUp><27,0>')
+ end
screen:expect({
any = {
- 'S%^ection{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ '{8:A}^mouse scrolling ',
+ '{8:B}lines ',
+ '{8:B}to ',
+ '{8:B}test ',
+ '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
+ '{8:C}to ',
+ '{8:C}test ',
+ '{8:C}mouse scrolling ',
+ '{2:%[No Name%] %[%+%] }',
},
- })
-
- feed('<esc><LeftMouse><21,0>')
+ none = {
+ '{8:A}Inserting',
+ '{8:A}text',
+ '{8:A}with',
+ '{8:A}many',
+ '{8:A}lines',
+ '{8:A}to',
+ '{8:A}test',
+ '{8:B}Inserting',
+ '{8:B}mouse scrolling',
+ '{8:C}Inserting',
+ '{8:C}text',
+ '{8:C}with',
+ '{8:C}many',
+ '{8:C}lines',
+ },
+ })
+ if use_api then
+ api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
+ else
+ feed('<ScrollWheelUp><27,7><ScrollWheelUp>')
+ end
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }%^t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ '{8:A}^mouse scrolling ',
+ '{8:B}lines ',
+ '{8:B}to ',
+ '{8:B}test ',
+ '{3:%[No Name%] %[%+%] }{2:%[No Name%] %[%+%] }',
+ '{8:C}Inserting ',
+ '{8:C}text ',
+ '{8:C}with ',
+ '{8:C}many ',
+ '{8:C}lines ',
+ '{2:%[No Name%] %[%+%] }',
},
- })
-
- feed('<esc><LeftMouse><21,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t%^3{14: } {14: }',
- '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ none = {
+ '{8:A}Inserting',
+ '{8:A}text',
+ '{8:A}with',
+ '{8:A}many',
+ '{8:A}lines',
+ '{8:A}to',
+ '{8:A}test',
+ '{8:B}Inserting',
+ '{8:B}mouse scrolling',
+ '{8:C}to',
+ '{8:C}test',
+ '{8:C}mouse scrolling',
},
})
+ end
- feed('<esc><LeftMouse><0,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '{14:%^>} 私は猫が大好き{1:>---}{14: X } {1:>}',
- },
- })
+ it('mouse wheel will target the hovered window (pseudokey)', function()
+ wheel(false)
+ end)
- feed('<esc><LeftMouse><7,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '{14:>} 私は%^猫が大好き{1:>---}{14: X } {1:>}',
- },
- })
+ it('mouse wheel will target the hovered window (nvim_input_mouse)', function()
+ wheel(true)
+ end)
- feed('<esc><LeftMouse><21,2>')
+ it('horizontal scrolling (pseudokey)', function()
+ command('set sidescroll=0')
+ feed('<esc>:set nowrap<cr>')
+
+ feed('a <esc>17Ab<esc>3Ab<esc>')
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '{14:>} 私は猫が大好き{1:>---}{14: %^X } {1:>}',
+ 'bbbbbbbbbbbbbbb%^b ',
},
})
- end) -- level 1 - non wrapped
-
- it('(level 1) click on wrapped lines', function()
- feed_command('let &conceallevel=1', 'let &wrap=1', 'echo')
- feed('<esc><LeftMouse><24,1>')
+ feed('<ScrollWheelLeft><0,0>')
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14:%^ }',
- 't4{14: } ',
- '{14:>} 私は猫が大好き{1:>---}{14: X} ',
- '{14: } ✨🐈✨ ',
+ 'n bbbbbbbbbbbbbbbbbbb%^b ',
},
})
- feed('<esc><LeftMouse><0,2>')
+ feed('^<ScrollWheelRight><0,0>')
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- '%^t4{14: } ',
- '{14:>} 私は猫が大好き{1:>---}{14: X} ',
- '{14: } ✨🐈✨ ',
+ 'g ',
+ '%^t and selection bbbbbbbbb',
},
})
+ end)
+
+ it('horizontal scrolling (nvim_input_mouse)', function()
+ command('set sidescroll=0')
+ feed('<esc>:set nowrap<cr>')
- feed('<esc><LeftMouse><8,3>')
+ feed('a <esc>17Ab<esc>3Ab<esc>')
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- 't4{14: } ',
- '{14:>} 私は猫%^が大好き{1:>---}{14: X} ',
- '{14: } ✨🐈✨ ',
+ 'bbbbbbbbbbbbbbb%^b ',
},
})
- feed('<esc><LeftMouse><21,3>')
+ api.nvim_input_mouse('wheel', 'left', '', 0, 0, 27)
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- 't4{14: } ',
- '{14:>} 私は猫が大好き{1:>---}{14: %^X} ',
- '{14: } ✨🐈✨ ',
+ 'n bbbbbbbbbbbbbbbbbbb%^b ',
},
})
- feed('<esc><LeftMouse><4,4>')
+ feed('^')
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 0)
screen:expect({
any = {
- 'Section{1:>>--->--->---}{14: }t1{14: } ',
- '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
- 't4{14: } ',
- '{14:>} 私は猫が大好き{1:>---}{14: X} ',
- '{14: } ✨%^🐈✨ ',
+ 'g ',
+ '%^t and selection bbbbbbbbb',
},
})
- end) -- level 1 - wrapped
+ end)
- it('(level 2) click on non-wrapped lines', function()
- feed_command('let &conceallevel=2', 'echo')
+ it("'sidescrolloff' applies to horizontal scrolling", function()
+ command('set nowrap')
+ command('set sidescrolloff=4')
- feed('<esc><LeftMouse><20,0>')
+ feed('I <esc>020ib<esc>0')
screen:expect({
any = {
- 'Section{1:>>--->--->---}%^t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ 'testing ',
+ 'mouse ',
+ '%^bbbbbbbbbbbbbbbbbbbb supp',
},
})
- feed('<esc><LeftMouse><14,1>')
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} %^t2 t3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ 'g ',
+ ' ',
+ 'bbbb%^bbbbbbbbbb support an',
},
})
- feed('<esc><LeftMouse><18,1>')
+ -- window-local 'sidescrolloff' should override global value. #21162
+ command('setlocal sidescrolloff=2')
+ feed('0')
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t%^3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ 'testing ',
+ 'mouse ',
+ '%^bbbbbbbbbbbbbbbbbbbb supp',
},
})
- feed('<esc><LeftMouse><0,2>') -- Weirdness
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:%^>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ 'g ',
+ ' ',
+ 'bb%^bbbbbbbbbbbb support an',
},
})
+ end)
- feed('<esc><LeftMouse><8,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:>} 私は猫%^が大好き{1:>---}{14:X} ✨{1:>}',
- },
- })
+ local function test_mouse_click_conceal()
+ it('(level 1) click on non-wrapped lines', function()
+ feed_command('let &conceallevel=1', 'echo')
- feed('<esc><LeftMouse><20,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:%^X} ✨{1:>}',
- },
- })
- end) -- level 2 - non wrapped
+ feed('<esc><LeftMouse><0,0>')
+ screen:expect({
+ any = {
+ '%^Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ },
+ })
- it('(level 2) click on non-wrapped lines (insert mode)', function()
- feed_command('let &conceallevel=2', 'echo')
+ feed('<esc><LeftMouse><1,0>')
+ screen:expect({
+ any = {
+ 'S%^ection{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ },
+ })
- feed('<esc>i<LeftMouse><20,0>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}%^t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
- },
- })
+ feed('<esc><LeftMouse><21,0>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }%^t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ },
+ })
- feed('<LeftMouse><14,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} %^t2 t3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
- },
- })
+ feed('<esc><LeftMouse><21,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t%^3{14: } {14: }',
+ '{14:>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ },
+ })
- feed('<LeftMouse><18,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t%^3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
- },
- })
+ feed('<esc><LeftMouse><0,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '{14:%^>} 私は猫が大好き{1:>---}{14: X } {1:>}',
+ },
+ })
- feed('<LeftMouse><0,2>') -- Weirdness
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:%^>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
- },
- })
+ feed('<esc><LeftMouse><7,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '{14:>} 私は%^猫が大好き{1:>---}{14: X } {1:>}',
+ },
+ })
- feed('<LeftMouse><8,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:>} 私は猫%^が大好き{1:>---}{14:X} ✨{1:>}',
- },
- })
+ feed('<esc><LeftMouse><21,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '{14:>} 私は猫が大好き{1:>---}{14: %^X } {1:>}',
+ },
+ })
+ end) -- level 1 - non wrapped
- feed('<LeftMouse><20,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:%^X} ✨{1:>}',
- },
- })
- end) -- level 2 - non wrapped (insert mode)
+ it('(level 1) click on wrapped lines', function()
+ feed_command('let &conceallevel=1', 'let &wrap=1', 'echo')
- it('(level 2) click on wrapped lines', function()
- feed_command('let &conceallevel=2', 'let &wrap=1', 'echo')
+ feed('<esc><LeftMouse><24,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14:%^ }',
+ 't4{14: } ',
+ '{14:>} 私は猫が大好き{1:>---}{14: X} ',
+ '{14: } ✨🐈✨ ',
+ },
+ })
- feed('<esc><LeftMouse><20,0>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}%^t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><0,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ '%^t4{14: } ',
+ '{14:>} 私は猫が大好き{1:>---}{14: X} ',
+ '{14: } ✨🐈✨ ',
+ },
+ })
- feed('<esc><LeftMouse><14,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} %^t2 t3 ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><8,3>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ 't4{14: } ',
+ '{14:>} 私は猫%^が大好き{1:>---}{14: X} ',
+ '{14: } ✨🐈✨ ',
+ },
+ })
- feed('<esc><LeftMouse><18,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t%^3 ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><21,3>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ 't4{14: } ',
+ '{14:>} 私は猫が大好き{1:>---}{14: %^X} ',
+ '{14: } ✨🐈✨ ',
+ },
+ })
- -- NOTE: The click would ideally be on the 't' in 't4', but wrapping
- -- caused the invisible '*' right before 't4' to remain on the previous
- -- screen line. This is being treated as expected because fixing this is
- -- out of scope for mouse clicks. Should the wrapping behavior of
- -- concealed characters change in the future, this case should be
- -- reevaluated.
- feed('<esc><LeftMouse><0,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 %^ ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><4,4>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}{14: }t1{14: } ',
+ '{1:>--->--->---} {14: }t2{14: } {14: }t3{14: } {14: }',
+ 't4{14: } ',
+ '{14:>} 私は猫が大好き{1:>---}{14: X} ',
+ '{14: } ✨%^🐈✨ ',
+ },
+ })
+ end) -- level 1 - wrapped
- feed('<esc><LeftMouse><1,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't%^4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- ' ✨🐈✨ ',
- },
- })
+ it('(level 2) click on non-wrapped lines', function()
+ feed_command('let &conceallevel=2', 'echo')
- feed('<esc><LeftMouse><0,3>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- '{14:%^>} 私は猫が大好き{1:>---}{14:X} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><20,0>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}%^t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><20,3>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:%^X} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><14,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} %^t2 t3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><1,4>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- '%^✨🐈✨ ',
- },
- })
+ feed('<esc><LeftMouse><18,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t%^3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><5,4>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- '{14:>} 私は猫が大好き{1:>---}{14:X} ',
- '✨🐈%^✨ ',
- },
- })
- end) -- level 2 - wrapped
+ feed('<esc><LeftMouse><0,2>') -- Weirdness
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:%^>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- it('(level 3) click on non-wrapped lines', function()
- feed_command('let &conceallevel=3', 'echo')
+ feed('<esc><LeftMouse><8,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:>} 私は猫%^が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><0,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- '%^ 私は猫が大好き{1:>----} ✨🐈',
- },
- })
+ feed('<esc><LeftMouse><20,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:%^X} ✨{1:>}',
+ },
+ })
+ end) -- level 2 - non wrapped
- feed('<esc><LeftMouse><1,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- ' %^私は猫が大好き{1:>----} ✨🐈',
- },
- })
+ it('(level 2) click on non-wrapped lines (insert mode)', function()
+ feed_command('let &conceallevel=2', 'echo')
- feed('<esc><LeftMouse><13,2>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- ' 私は猫が大好%^き{1:>----} ✨🐈',
- },
- })
+ feed('<esc>i<LeftMouse><20,0>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}%^t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><20,2>')
- feed('zH') -- FIXME: unnecessary horizontal scrolling
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 t4 ',
- ' 私は猫が大好き{1:>----}%^ ✨🐈',
- },
- })
- end) -- level 3 - non wrapped
+ feed('<LeftMouse><14,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} %^t2 t3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- it('(level 3) click on wrapped lines', function()
- feed_command('let &conceallevel=3', 'let &wrap=1', 'echo')
+ feed('<LeftMouse><18,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t%^3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><14,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} %^t2 t3 ',
- 't4 ',
- ' 私は猫が大好き{1:>----} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<LeftMouse><0,2>') -- Weirdness
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:%^>} 私は猫が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
- feed('<esc><LeftMouse><18,1>')
- screen:expect({
- any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t%^3 ',
- 't4 ',
- ' 私は猫が大好き{1:>----} ',
- ' ✨🐈✨ ',
- },
- })
+ feed('<LeftMouse><8,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:>} 私は猫%^が大好き{1:>---}{14:X} ✨{1:>}',
+ },
+ })
+
+ feed('<LeftMouse><20,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:%^X} ✨{1:>}',
+ },
+ })
+ end) -- level 2 - non wrapped (insert mode)
+
+ it('(level 2) click on wrapped lines', function()
+ feed_command('let &conceallevel=2', 'let &wrap=1', 'echo')
+
+ feed('<esc><LeftMouse><20,0>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}%^t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><14,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} %^t2 t3 ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><18,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t%^3 ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ -- NOTE: The click would ideally be on the 't' in 't4', but wrapping
+ -- caused the invisible '*' right before 't4' to remain on the previous
+ -- screen line. This is being treated as expected because fixing this is
+ -- out of scope for mouse clicks. Should the wrapping behavior of
+ -- concealed characters change in the future, this case should be
+ -- reevaluated.
+ feed('<esc><LeftMouse><0,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 %^ ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><1,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't%^4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><0,3>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ '{14:%^>} 私は猫が大好き{1:>---}{14:X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><20,3>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:%^X} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><1,4>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ '%^✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><5,4>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ '{14:>} 私は猫が大好き{1:>---}{14:X} ',
+ '✨🐈%^✨ ',
+ },
+ })
+ end) -- level 2 - wrapped
+
+ it('(level 3) click on non-wrapped lines', function()
+ feed_command('let &conceallevel=3', 'echo')
+
+ feed('<esc><LeftMouse><0,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ '%^ 私は猫が大好き{1:>----} ✨🐈',
+ },
+ })
+
+ feed('<esc><LeftMouse><1,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ ' %^私は猫が大好き{1:>----} ✨🐈',
+ },
+ })
+
+ feed('<esc><LeftMouse><13,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ ' 私は猫が大好%^き{1:>----} ✨🐈',
+ },
+ })
+
+ feed('<esc><LeftMouse><20,2>')
+ feed('zH') -- FIXME: unnecessary horizontal scrolling
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 t4 ',
+ ' 私は猫が大好き{1:>----}%^ ✨🐈',
+ },
+ })
+ end) -- level 3 - non wrapped
+
+ it('(level 3) click on wrapped lines', function()
+ feed_command('let &conceallevel=3', 'let &wrap=1', 'echo')
- feed('<esc><LeftMouse><1,2>')
+ feed('<esc><LeftMouse><14,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} %^t2 t3 ',
+ 't4 ',
+ ' 私は猫が大好き{1:>----} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><18,1>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t%^3 ',
+ 't4 ',
+ ' 私は猫が大好き{1:>----} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><1,2>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't%^4 ',
+ ' 私は猫が大好き{1:>----} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><0,3>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ '%^ 私は猫が大好き{1:>----} ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><20,3>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ ' 私は猫が大好き{1:>----}%^ ',
+ ' ✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><1,4>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ ' 私は猫が大好き{1:>----} ',
+ ' %^✨🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><3,4>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ ' 私は猫が大好き{1:>----} ',
+ ' ✨%^🐈✨ ',
+ },
+ })
+
+ feed('<esc><LeftMouse><5,4>')
+ screen:expect({
+ any = {
+ 'Section{1:>>--->--->---}t1 ',
+ '{1:>--->--->---} t2 t3 ',
+ 't4 ',
+ ' 私は猫が大好き{1:>----} ',
+ ' ✨🐈%^✨ ',
+ },
+ })
+ end) -- level 3 - wrapped
+ end
+
+ describe('on concealed text', function()
+ -- Helpful for reading the test expectations:
+ -- :match Error /\^/
+
+ before_each(function()
+ screen:try_resize(25, 7)
+ feed('ggdG')
+
+ command([[setlocal concealcursor=ni nowrap shiftwidth=2 tabstop=4 list listchars=tab:>-]])
+ command([[highlight link X0 Normal]])
+ command([[highlight link X1 NonText]])
+ command([[highlight link X2 NonText]])
+ command([[highlight link X3 NonText]])
+
+ -- First column is there to retain the tabs.
+ insert([[
+ |Section *t1*
+ | *t2* *t3* *t4*
+ |x 私は猫が大好き *cats* ✨🐈✨
+ ]])
+
+ feed('gg<c-v>Gxgg')
+ end)
+
+ describe('(syntax)', function()
+ before_each(function()
+ command([[syntax region X0 matchgroup=X1 start=/\*/ end=/\*/ concealends contains=X2]])
+ command([[syntax match X2 /cats/ conceal cchar=X contained]])
+ command([[syntax match X3 /\n\@<=x/ conceal cchar=>]])
+ end)
+ test_mouse_click_conceal()
+ end)
+
+ describe('(matchadd())', function()
+ before_each(function()
+ fn.matchadd('Conceal', [[\*]])
+ fn.matchadd('Conceal', [[cats]], 10, -1, { conceal = 'X' })
+ fn.matchadd('Conceal', [[\n\@<=x]], 10, -1, { conceal = '>' })
+ end)
+ test_mouse_click_conceal()
+ end)
+
+ describe('(extmarks)', function()
+ before_each(function()
+ local ns = api.nvim_create_namespace('conceal')
+ api.nvim_buf_set_extmark(0, ns, 0, 11, { end_col = 12, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 0, 14, { end_col = 15, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 5, { end_col = 6, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { end_col = 9, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 10, { end_col = 11, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 13, { end_col = 14, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 15, { end_col = 16, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 18, { end_col = 19, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 2, 24, { end_col = 25, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 2, 29, { end_col = 30, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 2, 25, { end_col = 29, conceal = 'X' })
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { end_col = 1, conceal = '>' })
+ end)
+ test_mouse_click_conceal()
+ end)
+ end)
+
+ it('virtual text does not change cursor placement on concealed line', function()
+ command('%delete')
+ insert('aaaaaaaaaa|hidden|bbbbbbbbbb|hidden|cccccccccc')
+ command('syntax match test /|hidden|/ conceal cchar=X')
+ command('set conceallevel=2 concealcursor=n virtualedit=all')
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't%^4 ',
- ' 私は猫が大好き{1:>----} ',
- ' ✨🐈✨ ',
+ 'aaaaaaaaaa{14:X}bbbbbbb ',
+ 'bbb{14:X}ccccccccc%^c ',
},
})
-
- feed('<esc><LeftMouse><0,3>')
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- '%^ 私は猫が大好き{1:>----} ',
- ' ✨🐈✨ ',
+ 'aaaaaaaaaa{14:X}bbbbbb%^b ',
+ 'bbb{14:X}cccccccccc ',
},
})
-
- feed('<esc><LeftMouse><20,3>')
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 16)
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- ' 私は猫が大好き{1:>----}%^ ',
- ' ✨🐈✨ ',
+ 'aaaaaaaaaa{14:X}bbbbbbb ',
+ 'bbb{14:X}cccccccccc %^ ',
},
})
- feed('<esc><LeftMouse><1,4>')
+ api.nvim_buf_set_extmark(0, api.nvim_create_namespace(''), 0, 0, {
+ virt_text = { { '?', 'ErrorMsg' } },
+ virt_text_pos = 'right_align',
+ virt_text_repeat_linebreak = true,
+ })
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- ' 私は猫が大好き{1:>----} ',
- ' %^✨🐈✨ ',
+ 'aaaaaaaaaa{14:X}bbbbbbb {9:%?}',
+ 'bbb{14:X}cccccccccc %^ {9:%?}',
},
})
-
- feed('<esc><LeftMouse><3,4>')
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- ' 私は猫が大好き{1:>----} ',
- ' ✨%^🐈✨ ',
+ 'aaaaaaaaaa{14:X}bbbbbb%^b {9:%?}',
+ 'bbb{14:X}cccccccccc {9:%?}',
},
})
-
- feed('<esc><LeftMouse><5,4>')
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 16)
screen:expect({
any = {
- 'Section{1:>>--->--->---}t1 ',
- '{1:>--->--->---} t2 t3 ',
- 't4 ',
- ' 私は猫が大好き{1:>----} ',
- ' ✨🐈%^✨ ',
+ 'aaaaaaaaaa{14:X}bbbbbbb {9:%?}',
+ 'bbb{14:X}cccccccccc %^ {9:%?}',
},
})
- end) -- level 3 - wrapped
- end
-
- describe('on concealed text', function()
- -- Helpful for reading the test expectations:
- -- :match Error /\^/
-
- before_each(function()
- screen:try_resize(25, 7)
- feed('ggdG')
-
- command([[setlocal concealcursor=ni nowrap shiftwidth=2 tabstop=4 list listchars=tab:>-]])
- command([[highlight link X0 Normal]])
- command([[highlight link X1 NonText]])
- command([[highlight link X2 NonText]])
- command([[highlight link X3 NonText]])
-
- -- First column is there to retain the tabs.
- insert([[
- |Section *t1*
- | *t2* *t3* *t4*
- |x 私は猫が大好き *cats* ✨🐈✨
- ]])
-
- feed('gg<c-v>Gxgg')
- end)
-
- describe('(syntax)', function()
- before_each(function()
- command([[syntax region X0 matchgroup=X1 start=/\*/ end=/\*/ concealends contains=X2]])
- command([[syntax match X2 /cats/ conceal cchar=X contained]])
- command([[syntax match X3 /\n\@<=x/ conceal cchar=>]])
- end)
- test_mouse_click_conceal()
- end)
-
- describe('(matchadd())', function()
- before_each(function()
- fn.matchadd('Conceal', [[\*]])
- fn.matchadd('Conceal', [[cats]], 10, -1, { conceal = 'X' })
- fn.matchadd('Conceal', [[\n\@<=x]], 10, -1, { conceal = '>' })
- end)
- test_mouse_click_conceal()
end)
- describe('(extmarks)', function()
- before_each(function()
- local ns = api.nvim_create_namespace('conceal')
- api.nvim_buf_set_extmark(0, ns, 0, 11, { end_col = 12, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 0, 14, { end_col = 15, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 1, 5, { end_col = 6, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 1, 8, { end_col = 9, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 1, 10, { end_col = 11, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 1, 13, { end_col = 14, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 1, 15, { end_col = 16, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 1, 18, { end_col = 19, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 2, 24, { end_col = 25, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 2, 29, { end_col = 30, conceal = '' })
- api.nvim_buf_set_extmark(0, ns, 2, 25, { end_col = 29, conceal = 'X' })
- api.nvim_buf_set_extmark(0, ns, 2, 0, { end_col = 1, conceal = '>' })
- end)
- test_mouse_click_conceal()
- end)
- end)
+ it("mouse click on window separator in statusline doesn't crash", function()
+ api.nvim_set_option_value('winwidth', 1, {})
+ api.nvim_set_option_value('statusline', '%f', {})
- it('virtual text does not change cursor placement on concealed line', function()
- command('%delete')
- insert('aaaaaaaaaa|hidden|bbbbbbbbbb|hidden|cccccccccc')
- command('syntax match test /|hidden|/ conceal cchar=X')
- command('set conceallevel=2 concealcursor=n virtualedit=all')
- screen:expect({
- any = {
- 'aaaaaaaaaa{14:X}bbbbbbb ',
- 'bbb{14:X}ccccccccc%^c ',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
- screen:expect({
- any = {
- 'aaaaaaaaaa{14:X}bbbbbb%^b ',
- 'bbb{14:X}cccccccccc ',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 1, 16)
- screen:expect({
- any = {
- 'aaaaaaaaaa{14:X}bbbbbbb ',
- 'bbb{14:X}cccccccccc %^ ',
- },
- })
-
- api.nvim_buf_set_extmark(0, api.nvim_create_namespace(''), 0, 0, {
- virt_text = { { '?', 'ErrorMsg' } },
- virt_text_pos = 'right_align',
- virt_text_repeat_linebreak = true,
- })
- screen:expect({
- any = {
- 'aaaaaaaaaa{14:X}bbbbbbb {9:%?}',
- 'bbb{14:X}cccccccccc %^ {9:%?}',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
- screen:expect({
- any = {
- 'aaaaaaaaaa{14:X}bbbbbb%^b {9:%?}',
- 'bbb{14:X}cccccccccc {9:%?}',
- },
- })
- api.nvim_input_mouse('left', 'press', '', 0, 1, 16)
- screen:expect({
- any = {
- 'aaaaaaaaaa{14:X}bbbbbbb {9:%?}',
- 'bbb{14:X}cccccccccc %^ {9:%?}',
- },
- })
- end)
-
- it("mouse click on window separator in statusline doesn't crash", function()
- api.nvim_set_option_value('winwidth', 1, {})
- api.nvim_set_option_value('statusline', '%f', {})
+ command('vsplit')
+ command('redraw')
- command('vsplit')
- command('redraw')
+ local lines = api.nvim_get_option_value('lines', {})
+ local columns = api.nvim_get_option_value('columns', {})
- local lines = api.nvim_get_option_value('lines', {})
- local columns = api.nvim_get_option_value('columns', {})
-
- api.nvim_input_mouse('left', 'press', '', 0, lines - 1, math.floor(columns / 2))
- command('redraw')
- end)
+ api.nvim_input_mouse('left', 'press', '', 0, lines - 1, math.floor(columns / 2))
+ command('redraw')
+ end)
- it('getmousepos() works correctly', function()
- local winwidth = api.nvim_get_option_value('winwidth', {})
- -- Set winwidth=1 so that window sizes don't change.
- api.nvim_set_option_value('winwidth', 1, {})
- command('tabedit')
- local tabpage = api.nvim_get_current_tabpage()
- insert('hello')
- command('vsplit')
- local opts = {
- relative = 'editor',
- width = 12,
- height = 1,
- col = 8,
- row = 1,
- anchor = 'NW',
- style = 'minimal',
- border = 'single',
- focusable = 1,
- }
- local float = api.nvim_open_win(api.nvim_get_current_buf(), false, opts)
- command('redraw')
- local lines = api.nvim_get_option_value('lines', {})
- local columns = api.nvim_get_option_value('columns', {})
-
- -- Test that screenrow and screencol are set properly for all positions.
- for row = 0, lines - 1 do
- for col = 0, columns - 1 do
- -- Skip the X button that would close the tab.
- if row ~= 0 or col ~= columns - 1 then
- api.nvim_input_mouse('left', 'press', '', 0, row, col)
- api.nvim_set_current_tabpage(tabpage)
- local mousepos = fn.getmousepos()
- eq(row + 1, mousepos.screenrow)
- eq(col + 1, mousepos.screencol)
- -- All other values should be 0 when clicking on the command line.
- if row == lines - 1 then
- eq(0, mousepos.winid)
- eq(0, mousepos.winrow)
- eq(0, mousepos.wincol)
- eq(0, mousepos.line)
- eq(0, mousepos.column)
- eq(0, mousepos.coladd)
+ it('getmousepos() works correctly', function()
+ local winwidth = api.nvim_get_option_value('winwidth', {})
+ -- Set winwidth=1 so that window sizes don't change.
+ api.nvim_set_option_value('winwidth', 1, {})
+ command('tabedit')
+ local tabpage = api.nvim_get_current_tabpage()
+ insert('hello')
+ command('vsplit')
+ local opts = {
+ relative = 'editor',
+ width = 12,
+ height = 1,
+ col = 8,
+ row = 1,
+ anchor = 'NW',
+ style = 'minimal',
+ border = 'single',
+ focusable = 1,
+ }
+ local float = api.nvim_open_win(api.nvim_get_current_buf(), false, opts)
+ command('redraw')
+ local lines = api.nvim_get_option_value('lines', {})
+ local columns = api.nvim_get_option_value('columns', {})
+
+ -- Test that screenrow and screencol are set properly for all positions.
+ for row = 0, lines - 1 do
+ for col = 0, columns - 1 do
+ -- Skip the X button that would close the tab.
+ if row ~= 0 or col ~= columns - 1 then
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ api.nvim_set_current_tabpage(tabpage)
+ local mousepos = fn.getmousepos()
+ eq(row + 1, mousepos.screenrow)
+ eq(col + 1, mousepos.screencol)
+ -- All other values should be 0 when clicking on the command line.
+ if row == lines - 1 then
+ eq(0, mousepos.winid)
+ eq(0, mousepos.winrow)
+ eq(0, mousepos.wincol)
+ eq(0, mousepos.line)
+ eq(0, mousepos.column)
+ eq(0, mousepos.coladd)
+ end
end
end
end
- end
- -- Test that mouse position values are properly set for the floating window
- -- with a border. 1 is added to the height and width to account for the
- -- border.
- for win_row = 0, opts.height + 1 do
- for win_col = 0, opts.width + 1 do
- local row = win_row + opts.row
- local col = win_col + opts.col
- api.nvim_input_mouse('left', 'press', '', 0, row, col)
- local mousepos = fn.getmousepos()
- eq(float, mousepos.winid)
- eq(win_row + 1, mousepos.winrow)
- eq(win_col + 1, mousepos.wincol)
- local line = 0
- local column = 0
- local coladd = 0
- if
- win_row > 0
- and win_row < opts.height + 1
- and win_col > 0
- and win_col < opts.width + 1
- then
- -- Because of border, win_row and win_col don't need to be
- -- incremented by 1.
- line = math.min(win_row, fn.line('$'))
- column = math.min(win_col, #fn.getline(line) + 1)
- coladd = win_col - column
+ -- Test that mouse position values are properly set for the floating window
+ -- with a border. 1 is added to the height and width to account for the
+ -- border.
+ for win_row = 0, opts.height + 1 do
+ for win_col = 0, opts.width + 1 do
+ local row = win_row + opts.row
+ local col = win_col + opts.col
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = fn.getmousepos()
+ eq(float, mousepos.winid)
+ eq(win_row + 1, mousepos.winrow)
+ eq(win_col + 1, mousepos.wincol)
+ local line = 0
+ local column = 0
+ local coladd = 0
+ if
+ win_row > 0
+ and win_row < opts.height + 1
+ and win_col > 0
+ and win_col < opts.width + 1
+ then
+ -- Because of border, win_row and win_col don't need to be
+ -- incremented by 1.
+ line = math.min(win_row, fn.line('$'))
+ column = math.min(win_col, #fn.getline(line) + 1)
+ coladd = win_col - column
+ end
+ eq(line, mousepos.line)
+ eq(column, mousepos.column)
+ eq(coladd, mousepos.coladd)
end
- eq(line, mousepos.line)
- eq(column, mousepos.column)
- eq(coladd, mousepos.coladd)
- end
- end
-
- -- Test that mouse position values are properly set for the floating
- -- window, after removing the border.
- opts.border = 'none'
- api.nvim_win_set_config(float, opts)
- command('redraw')
- for win_row = 0, opts.height - 1 do
- for win_col = 0, opts.width - 1 do
- local row = win_row + opts.row
- local col = win_col + opts.col
- api.nvim_input_mouse('left', 'press', '', 0, row, col)
- local mousepos = fn.getmousepos()
- eq(float, mousepos.winid)
- eq(win_row + 1, mousepos.winrow)
- eq(win_col + 1, mousepos.wincol)
- local line = math.min(win_row + 1, fn.line('$'))
- local column = math.min(win_col + 1, #fn.getline(line) + 1)
- local coladd = win_col + 1 - column
- eq(line, mousepos.line)
- eq(column, mousepos.column)
- eq(coladd, mousepos.coladd)
end
- end
- -- Test that mouse position values are properly set for ordinary windows.
- -- Set the float to be unfocusable instead of closing, to additionally test
- -- that getmousepos() does not consider unfocusable floats. (see discussion
- -- in PR #14937 for details).
- opts.focusable = false
- api.nvim_win_set_config(float, opts)
- command('redraw')
- for nr = 1, 2 do
- for win_row = 0, fn.winheight(nr) - 1 do
- for win_col = 0, fn.winwidth(nr) - 1 do
- local row = win_row + fn.win_screenpos(nr)[1] - 1
- local col = win_col + fn.win_screenpos(nr)[2] - 1
+ -- Test that mouse position values are properly set for the floating
+ -- window, after removing the border.
+ opts.border = 'none'
+ api.nvim_win_set_config(float, opts)
+ command('redraw')
+ for win_row = 0, opts.height - 1 do
+ for win_col = 0, opts.width - 1 do
+ local row = win_row + opts.row
+ local col = win_col + opts.col
api.nvim_input_mouse('left', 'press', '', 0, row, col)
local mousepos = fn.getmousepos()
- eq(fn.win_getid(nr), mousepos.winid)
+ eq(float, mousepos.winid)
eq(win_row + 1, mousepos.winrow)
eq(win_col + 1, mousepos.wincol)
local line = math.min(win_row + 1, fn.line('$'))
@@ -1896,240 +1883,275 @@ describe('ui/mouse/input', function()
eq(coladd, mousepos.coladd)
end
end
- end
- -- Restore state and release mouse.
- command('tabclose!')
- api.nvim_set_option_value('winwidth', winwidth, {})
- api.nvim_input_mouse('left', 'release', '', 0, 0, 0)
- end)
+ -- Test that mouse position values are properly set for ordinary windows.
+ -- Set the float to be unfocusable instead of closing, to additionally test
+ -- that getmousepos() does not consider unfocusable floats. (see discussion
+ -- in PR #14937 for details).
+ opts.focusable = false
+ api.nvim_win_set_config(float, opts)
+ command('redraw')
+ for nr = 1, 2 do
+ for win_row = 0, fn.winheight(nr) - 1 do
+ for win_col = 0, fn.winwidth(nr) - 1 do
+ local row = win_row + fn.win_screenpos(nr)[1] - 1
+ local col = win_col + fn.win_screenpos(nr)[2] - 1
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = fn.getmousepos()
+ eq(fn.win_getid(nr), mousepos.winid)
+ eq(win_row + 1, mousepos.winrow)
+ eq(win_col + 1, mousepos.wincol)
+ local line = math.min(win_row + 1, fn.line('$'))
+ local column = math.min(win_col + 1, #fn.getline(line) + 1)
+ local coladd = win_col + 1 - column
+ eq(line, mousepos.line)
+ eq(column, mousepos.column)
+ eq(coladd, mousepos.coladd)
+ end
+ end
+ end
- it('scroll keys are not translated into multiclicks and can be mapped #6211 #6989', function()
- api.nvim_set_var('mouse_up', 0)
- api.nvim_set_var('mouse_up2', 0)
- command('nnoremap <ScrollWheelUp> <Cmd>let g:mouse_up += 1<CR>')
- command('nnoremap <2-ScrollWheelUp> <Cmd>let g:mouse_up2 += 1<CR>')
- feed('<ScrollWheelUp><0,0>')
- feed('<ScrollWheelUp><0,0>')
- api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
- api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
- eq(4, api.nvim_get_var('mouse_up'))
- eq(0, api.nvim_get_var('mouse_up2'))
- end)
+ -- Restore state and release mouse.
+ command('tabclose!')
+ api.nvim_set_option_value('winwidth', winwidth, {})
+ api.nvim_input_mouse('left', 'release', '', 0, 0, 0)
+ end)
- it('<MouseMove> to different locations can be mapped', function()
- api.nvim_set_var('mouse_move', 0)
- api.nvim_set_var('mouse_move2', 0)
- command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
- command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
- feed('<MouseMove><1,0>')
- feed('<MouseMove><2,0>')
- api.nvim_input_mouse('move', '', '', 0, 0, 3)
- api.nvim_input_mouse('move', '', '', 0, 0, 4)
- eq(4, api.nvim_get_var('mouse_move'))
- eq(0, api.nvim_get_var('mouse_move2'))
- end)
+ it('scroll keys are not translated into multiclicks and can be mapped #6211 #6989', function()
+ api.nvim_set_var('mouse_up', 0)
+ api.nvim_set_var('mouse_up2', 0)
+ command('nnoremap <ScrollWheelUp> <Cmd>let g:mouse_up += 1<CR>')
+ command('nnoremap <2-ScrollWheelUp> <Cmd>let g:mouse_up2 += 1<CR>')
+ feed('<ScrollWheelUp><0,0>')
+ feed('<ScrollWheelUp><0,0>')
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
+ eq(4, api.nvim_get_var('mouse_up'))
+ eq(0, api.nvim_get_var('mouse_up2'))
+ end)
- it('<MouseMove> to same location does not generate events #31103', function()
- api.nvim_set_var('mouse_move', 0)
- api.nvim_set_var('mouse_move2', 0)
- command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
- command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
- api.nvim_input_mouse('move', '', '', 0, 0, 3)
- eq(1, api.nvim_get_var('mouse_move'))
- eq(0, api.nvim_get_var('mouse_move2'))
- feed('<MouseMove><3,0>')
- feed('<MouseMove><3,0>')
- api.nvim_input_mouse('move', '', '', 0, 0, 3)
- api.nvim_input_mouse('move', '', '', 0, 0, 3)
- eq(1, api.nvim_get_var('mouse_move'))
- eq(0, api.nvim_get_var('mouse_move2'))
- eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
- feed('<MouseMove><3,0><Insert>')
- eq(1, api.nvim_get_var('mouse_move'))
- eq(0, api.nvim_get_var('mouse_move2'))
- eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
- end)
+ it('<MouseMove> to different locations can be mapped', function()
+ api.nvim_set_var('mouse_move', 0)
+ api.nvim_set_var('mouse_move2', 0)
+ command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
+ command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
+ feed('<MouseMove><1,0>')
+ feed('<MouseMove><2,0>')
+ api.nvim_input_mouse('move', '', '', 0, 0, 3)
+ api.nvim_input_mouse('move', '', '', 0, 0, 4)
+ eq(4, api.nvim_get_var('mouse_move'))
+ eq(0, api.nvim_get_var('mouse_move2'))
+ end)
- it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
- feed('<MouseMove>')
- n.poke_eventloop()
- n.assert_alive()
- end)
+ it('<MouseMove> to same location does not generate events #31103', function()
+ api.nvim_set_var('mouse_move', 0)
+ api.nvim_set_var('mouse_move2', 0)
+ command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
+ command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
+ api.nvim_input_mouse('move', '', '', 0, 0, 3)
+ eq(1, api.nvim_get_var('mouse_move'))
+ eq(0, api.nvim_get_var('mouse_move2'))
+ feed('<MouseMove><3,0>')
+ feed('<MouseMove><3,0>')
+ api.nvim_input_mouse('move', '', '', 0, 0, 3)
+ api.nvim_input_mouse('move', '', '', 0, 0, 3)
+ eq(1, api.nvim_get_var('mouse_move'))
+ eq(0, api.nvim_get_var('mouse_move2'))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ feed('<MouseMove><3,0><Insert>')
+ eq(1, api.nvim_get_var('mouse_move'))
+ eq(0, api.nvim_get_var('mouse_move2'))
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ end)
+
+ it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
+ feed('<MouseMove>')
+ n.poke_eventloop()
+ n.assert_alive()
+ end)
+
+ it('mousemodel=popup_setpos', function()
+ screen:try_resize(80, 24)
+ exec([[
+ 5new
+ call setline(1, ['the dish ran away with the spoon',
+ \ 'the cow jumped over the moon' ])
+
+ set mouse=a mousemodel=popup_setpos
+
+ aunmenu PopUp
+ nmenu PopUp.foo :let g:menustr = 'foo'<CR>
+ nmenu PopUp.bar :let g:menustr = 'bar'<CR>
+ nmenu PopUp.baz :let g:menustr = 'baz'<CR>
+ vmenu PopUp.foo y:<C-U>let g:menustr = 'foo'<CR>
+ vmenu PopUp.bar y:<C-U>let g:menustr = 'bar'<CR>
+ vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
+ ]])
+
+ api.nvim_win_set_cursor(0, { 1, 0 })
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 4)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 4)
+ feed('<Down><Down><CR>')
+ eq('bar', api.nvim_get_var('menustr'))
+ eq({ 1, 4 }, api.nvim_win_get_cursor(0))
+
+ -- Test for right click in visual mode inside the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
+ feed('vee')
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 11)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 11)
+ feed('<Down><CR>')
+ eq({ 1, 9 }, api.nvim_win_get_cursor(0))
+ eq('ran away', fn.getreg('"'))
+
+ -- Test for right click in visual mode right before the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
+ feed('vee')
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 8)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 8)
+ feed('<Down><CR>')
+ eq({ 1, 8 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('"'))
+
+ -- Test for right click in visual mode right after the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
+ feed('vee')
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 17)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 17)
+ feed('<Down><CR>')
+ eq({ 1, 17 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('"'))
+
+ -- Test for right click in block-wise visual mode inside the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
+ feed('<C-V>j3l')
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 16)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 16)
+ feed('<Down><CR>')
+ eq({ 1, 15 }, api.nvim_win_get_cursor(0))
+ eq('\0224', fn.getregtype('"'))
+
+ -- Test for right click in block-wise visual mode outside the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
+ feed('<C-V>j3l')
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 1)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 1)
+ feed('<Down><CR>')
+ eq({ 2, 1 }, api.nvim_win_get_cursor(0))
+ eq('v', fn.getregtype('"'))
+ eq('', fn.getreg('"'))
+
+ -- Test for right click in line-wise visual mode inside the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
+ feed('V')
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 9)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 9)
+ feed('<Down><CR>')
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
+ eq('V', fn.getregtype('"'))
+ eq(1, #fn.getreg('"', 1, true))
+
+ -- Test for right click in multi-line line-wise visual mode inside the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
+ feed('Vj')
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 19)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 19)
+ feed('<Down><CR>')
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
+ eq('V', fn.getregtype('"'))
+ eq(2, #fn.getreg('"', 1, true))
+
+ -- Test for right click in line-wise visual mode outside the selection
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
+ feed('V')
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 9)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 9)
+ feed('<Down><CR>')
+ eq({ 2, 9 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('"'))
+
+ -- Try clicking outside the window
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 2, 1 })
+ feed('vee')
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 1)
+ api.nvim_input_mouse('right', 'release', '', 0, 6, 1)
+ feed('<Down><CR>')
+ eq(2, fn.winnr())
+ eq('', fn.getreg('"'))
+
+ -- Test for right click in visual mode inside the selection with vertical splits
+ command('wincmd t')
+ command('rightbelow vsplit')
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
+ feed('vee')
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 52)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 52)
+ feed('<Down><CR>')
+ eq({ 1, 9 }, api.nvim_win_get_cursor(0))
+ eq('ran away', fn.getreg('"'))
+
+ -- Test for right click inside visual selection at bottom of window with winbar
+ command('setlocal winbar=WINBAR')
+ feed('2yyP')
+ fn.setreg('"', '')
+ feed('G$vbb')
+ api.nvim_input_mouse('right', 'press', '', 0, 4, 61)
+ api.nvim_input_mouse('right', 'release', '', 0, 4, 61)
+ feed('<Down><CR>')
+ eq({ 4, 20 }, api.nvim_win_get_cursor(0))
+ eq('the moon', fn.getreg('"'))
+
+ -- Try clicking in the cmdline
+ api.nvim_input_mouse('right', 'press', '', 0, 23, 0)
+ api.nvim_input_mouse('right', 'release', '', 0, 23, 0)
+ feed('<Down><Down><Down><CR>')
+ eq('baz', api.nvim_get_var('menustr'))
+
+ -- Try clicking in horizontal separator with global statusline
+ command('set laststatus=3')
+ api.nvim_input_mouse('right', 'press', '', 0, 5, 0)
+ api.nvim_input_mouse('right', 'release', '', 0, 5, 0)
+ feed('<Down><CR>')
+ eq('foo', api.nvim_get_var('menustr'))
+
+ -- Try clicking in the cmdline with global statusline
+ api.nvim_input_mouse('right', 'press', '', 0, 23, 0)
+ api.nvim_input_mouse('right', 'release', '', 0, 23, 0)
+ feed('<Down><Down><CR>')
+ eq('bar', api.nvim_get_var('menustr'))
+ end)
+
+ it('below a concealed line #33450', function()
+ api.nvim_set_option_value('conceallevel', 2, {})
+ api.nvim_buf_set_extmark(0, api.nvim_create_namespace(''), 1, 0, { conceal_lines = '' })
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
+ api.nvim_input_mouse('left', 'release', '', 0, 1, 0)
+ eq(3, fn.line('.'))
+ -- No error when clicking below last line that is concealed.
+ screen:try_resize(80, 10) -- Prevent hit-enter
+ api.nvim_set_option_value('cmdheight', 3, {})
+ local count = api.nvim_buf_line_count(0)
+ api.nvim_buf_set_extmark(0, 1, count - 1, 0, { conceal_lines = '' })
+ api.nvim_input_mouse('left', 'press', '', 0, count, 0)
+ eq('', api.nvim_get_vvar('errmsg'))
+ end)
+ end
- it('mousemodel=popup_setpos', function()
- screen:try_resize(80, 24)
- exec([[
- 5new
- call setline(1, ['the dish ran away with the spoon',
- \ 'the cow jumped over the moon' ])
-
- set mouse=a mousemodel=popup_setpos
-
- aunmenu PopUp
- nmenu PopUp.foo :let g:menustr = 'foo'<CR>
- nmenu PopUp.bar :let g:menustr = 'bar'<CR>
- nmenu PopUp.baz :let g:menustr = 'baz'<CR>
- vmenu PopUp.foo y:<C-U>let g:menustr = 'foo'<CR>
- vmenu PopUp.bar y:<C-U>let g:menustr = 'bar'<CR>
- vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
- ]])
-
- api.nvim_win_set_cursor(0, { 1, 0 })
- api.nvim_input_mouse('right', 'press', '', 0, 0, 4)
- api.nvim_input_mouse('right', 'release', '', 0, 0, 4)
- feed('<Down><Down><CR>')
- eq('bar', api.nvim_get_var('menustr'))
- eq({ 1, 4 }, api.nvim_win_get_cursor(0))
-
- -- Test for right click in visual mode inside the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 9 })
- feed('vee')
- api.nvim_input_mouse('right', 'press', '', 0, 0, 11)
- api.nvim_input_mouse('right', 'release', '', 0, 0, 11)
- feed('<Down><CR>')
- eq({ 1, 9 }, api.nvim_win_get_cursor(0))
- eq('ran away', fn.getreg('"'))
-
- -- Test for right click in visual mode right before the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 9 })
- feed('vee')
- api.nvim_input_mouse('right', 'press', '', 0, 0, 8)
- api.nvim_input_mouse('right', 'release', '', 0, 0, 8)
- feed('<Down><CR>')
- eq({ 1, 8 }, api.nvim_win_get_cursor(0))
- eq('', fn.getreg('"'))
-
- -- Test for right click in visual mode right after the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 9 })
- feed('vee')
- api.nvim_input_mouse('right', 'press', '', 0, 0, 17)
- api.nvim_input_mouse('right', 'release', '', 0, 0, 17)
- feed('<Down><CR>')
- eq({ 1, 17 }, api.nvim_win_get_cursor(0))
- eq('', fn.getreg('"'))
-
- -- Test for right click in block-wise visual mode inside the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 15 })
- feed('<C-V>j3l')
- api.nvim_input_mouse('right', 'press', '', 0, 1, 16)
- api.nvim_input_mouse('right', 'release', '', 0, 1, 16)
- feed('<Down><CR>')
- eq({ 1, 15 }, api.nvim_win_get_cursor(0))
- eq('\0224', fn.getregtype('"'))
-
- -- Test for right click in block-wise visual mode outside the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 15 })
- feed('<C-V>j3l')
- api.nvim_input_mouse('right', 'press', '', 0, 1, 1)
- api.nvim_input_mouse('right', 'release', '', 0, 1, 1)
- feed('<Down><CR>')
- eq({ 2, 1 }, api.nvim_win_get_cursor(0))
- eq('v', fn.getregtype('"'))
- eq('', fn.getreg('"'))
-
- -- Test for right click in line-wise visual mode inside the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 15 })
- feed('V')
- api.nvim_input_mouse('right', 'press', '', 0, 0, 9)
- api.nvim_input_mouse('right', 'release', '', 0, 0, 9)
- feed('<Down><CR>')
- eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
- eq('V', fn.getregtype('"'))
- eq(1, #fn.getreg('"', 1, true))
-
- -- Test for right click in multi-line line-wise visual mode inside the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 15 })
- feed('Vj')
- api.nvim_input_mouse('right', 'press', '', 0, 1, 19)
- api.nvim_input_mouse('right', 'release', '', 0, 1, 19)
- feed('<Down><CR>')
- eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
- eq('V', fn.getregtype('"'))
- eq(2, #fn.getreg('"', 1, true))
-
- -- Test for right click in line-wise visual mode outside the selection
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 15 })
- feed('V')
- api.nvim_input_mouse('right', 'press', '', 0, 1, 9)
- api.nvim_input_mouse('right', 'release', '', 0, 1, 9)
- feed('<Down><CR>')
- eq({ 2, 9 }, api.nvim_win_get_cursor(0))
- eq('', fn.getreg('"'))
-
- -- Try clicking outside the window
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 2, 1 })
- feed('vee')
- api.nvim_input_mouse('right', 'press', '', 0, 6, 1)
- api.nvim_input_mouse('right', 'release', '', 0, 6, 1)
- feed('<Down><CR>')
- eq(2, fn.winnr())
- eq('', fn.getreg('"'))
-
- -- Test for right click in visual mode inside the selection with vertical splits
- command('wincmd t')
- command('rightbelow vsplit')
- fn.setreg('"', '')
- api.nvim_win_set_cursor(0, { 1, 9 })
- feed('vee')
- api.nvim_input_mouse('right', 'press', '', 0, 0, 52)
- api.nvim_input_mouse('right', 'release', '', 0, 0, 52)
- feed('<Down><CR>')
- eq({ 1, 9 }, api.nvim_win_get_cursor(0))
- eq('ran away', fn.getreg('"'))
-
- -- Test for right click inside visual selection at bottom of window with winbar
- command('setlocal winbar=WINBAR')
- feed('2yyP')
- fn.setreg('"', '')
- feed('G$vbb')
- api.nvim_input_mouse('right', 'press', '', 0, 4, 61)
- api.nvim_input_mouse('right', 'release', '', 0, 4, 61)
- feed('<Down><CR>')
- eq({ 4, 20 }, api.nvim_win_get_cursor(0))
- eq('the moon', fn.getreg('"'))
-
- -- Try clicking in the cmdline
- api.nvim_input_mouse('right', 'press', '', 0, 23, 0)
- api.nvim_input_mouse('right', 'release', '', 0, 23, 0)
- feed('<Down><Down><Down><CR>')
- eq('baz', api.nvim_get_var('menustr'))
-
- -- Try clicking in horizontal separator with global statusline
- command('set laststatus=3')
- api.nvim_input_mouse('right', 'press', '', 0, 5, 0)
- api.nvim_input_mouse('right', 'release', '', 0, 5, 0)
- feed('<Down><CR>')
- eq('foo', api.nvim_get_var('menustr'))
-
- -- Try clicking in the cmdline with global statusline
- api.nvim_input_mouse('right', 'press', '', 0, 23, 0)
- api.nvim_input_mouse('right', 'release', '', 0, 23, 0)
- feed('<Down><Down><CR>')
- eq('bar', api.nvim_get_var('menustr'))
+ describe('with ext_multigrid', function()
+ with_ext_multigrid(true)
end)
- it('below a concealed line #33450', function()
- api.nvim_set_option_value('conceallevel', 2, {})
- api.nvim_buf_set_extmark(0, api.nvim_create_namespace(''), 1, 0, { conceal_lines = '' })
- api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
- api.nvim_input_mouse('left', 'release', '', 0, 1, 0)
- eq(3, fn.line('.'))
- -- No error when clicking below last line that is concealed.
- screen:try_resize(80, 10) -- Prevent hit-enter
- api.nvim_set_option_value('cmdheight', 3, {})
- local count = api.nvim_buf_line_count(0)
- api.nvim_buf_set_extmark(0, 1, count - 1, 0, { conceal_lines = '' })
- api.nvim_input_mouse('left', 'press', '', 0, count, 0)
- eq('', api.nvim_get_vvar('errmsg'))
+ describe('without ext_multigrid', function()
+ with_ext_multigrid(false)
end)
end)
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
@@ -1018,7 +1018,7 @@ end)
describe('builtin popupmenu', function()
before_each(clear)
- local function with_ext_multigrid(multigrid)
+ local function with_ext_multigrid(multigrid, send_mouse_grid)
local screen
before_each(function()
screen = Screen.new(32, 20, { ext_multigrid = multigrid })
@@ -2553,8 +2553,12 @@ describe('builtin popupmenu', function()
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 2, 9, 33)
+ else
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2595,7 +2599,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
- api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est ^ |
L{n: sunt }{12: }sit amet, consectetur |
@@ -2672,8 +2675,12 @@ describe('builtin popupmenu', function()
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'up', '', 2, 9, 33)
+ else
+ api.nvim_input_mouse('wheel', 'up', '', 0, 9, 40)
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2712,7 +2719,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
- api.nvim_input_mouse('wheel', 'up', '', 0, 9, 40)
screen:expect([[
Est e^ |
L{n: elit } sit amet, consectetur |
@@ -2781,8 +2787,12 @@ describe('builtin popupmenu', function()
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 2, 9, 33)
+ else
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2813,7 +2823,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
- api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est es^ |
L{n: esse } sit amet, consectetur |
@@ -2948,8 +2957,12 @@ describe('builtin popupmenu', function()
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 2, 9, 33)
+ else
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -2988,7 +3001,6 @@ describe('builtin popupmenu', function()
float_pos = { [5] = { -1, 'NW', 4, 1, 3, false, 100, 1, 1, 3 } },
})
else
- api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est eu^ |
L{n: elit } sit amet, consectetur |
@@ -6614,9 +6626,13 @@ describe('builtin popupmenu', function()
return new_state
end
- local no_sel_screen ---@type string|test.functional.ui.screen.Expect
- if multigrid then
+ local no_sel_screen ---@type string|test.function.ui.screen.Expect
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
+ else
+ feed('<RightMouse><4,0>')
+ end
+ if multigrid then
no_sel_screen = {
grid = [[
## grid 1
@@ -6635,7 +6651,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}
else
- feed('<RightMouse><4,0>')
no_sel_screen = [[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6673,8 +6688,12 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('bar', api.nvim_get_var('menustr'))
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 2, 20)
+ else
+ feed('<RightMouse><20,2>')
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6693,7 +6712,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 3, 19, false, 250, 2, 3, 19 } },
})
else
- feed('<RightMouse><20,2>')
screen:expect([[
^popup menu test |
{1:~ }|*2
@@ -6702,8 +6720,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'b{n: baz } |
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 18)
+ else
+ feed('<RightMouse><18,0>')
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6722,7 +6744,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 17, false, 250, 2, 1, 17 } },
})
else
- feed('<RightMouse><18,0>')
screen:expect([[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6732,8 +6753,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' |
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 4, 1, 3)
+ else
+ feed('<RightMouse><20,2>')
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6752,7 +6777,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 3, 19, false, 250, 2, 3, 19 } },
})
else
- feed('<RightMouse><20,2>')
screen:expect([[
^popup menu test |
{1:~ }|*2
@@ -6761,7 +6785,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'b{n: baz } |
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
feed('<LeftMouse><21,5>')
@@ -6770,8 +6794,12 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('baz', api.nvim_get_var('menustr'))
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
+ else
+ feed('<RightMouse><4,0>')
+ end
+ if multigrid then
no_sel_screen = {
grid = [[
## grid 1
@@ -6790,7 +6818,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250, 2, 1, 3 } },
}
else
- feed('<RightMouse><4,0>')
no_sel_screen = [[
^popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6801,13 +6828,13 @@ describe('builtin popupmenu', function()
]]
end
screen:expect(no_sel_screen)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'drag', '', 2, 3, 6)
else
feed('<RightDrag><6,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{12: baz }'))
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'release', '', 2, 1, 6)
else
feed('<RightRelease><6,1>')
@@ -6818,35 +6845,36 @@ describe('builtin popupmenu', function()
no_sel_screen = screen_replace(no_sel_screen, [['baz']], [['foo']])
eq(false, screen.options.mousemoveevent)
- if multigrid then
+
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
else
feed('<RightMouse><4,0>')
end
screen:expect(no_sel_screen)
eq(true, screen.options.mousemoveevent)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'up', '', 2, 0, 4)
else
feed('<ScrollWheelUp><4,0>')
end
screen:expect(screen_replace(no_sel_screen, '{n: foo }', '{12: foo }'))
eq(true, screen.options.mousemoveevent)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('move', '', '', 4, 2, 3)
else
feed('<MouseMove><6,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: baz }', '{12: baz }'))
eq(true, screen.options.mousemoveevent)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('wheel', 'down', '', 4, 2, 3)
else
feed('<ScrollWheelDown><6,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: bar }', '{12: bar }'))
eq(true, screen.options.mousemoveevent)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 3)
else
feed('<LeftMouse><6,2>')
@@ -6857,8 +6885,12 @@ describe('builtin popupmenu', function()
eq('bar', api.nvim_get_var('menustr'))
command('set laststatus=0 | botright split')
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 5, 1, 20)
+ else
+ feed('<RightMouse><20,4>')
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6882,7 +6914,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'SW', 5, 1, 19, false, 250, 2, 1, 19 } },
})
else
- feed('<RightMouse><20,4>')
screen:expect([[
popup menu test |
{1:~ }{n: foo }{1: }|
@@ -6892,8 +6923,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' |
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
+ else
+ feed('<LeftMouse><21,3>')
+ end
+ if multigrid then
screen:expect([[
## grid 1
[2:--------------------------------]|*2
@@ -6910,7 +6945,6 @@ describe('builtin popupmenu', function()
{1:~ }|
]])
else
- feed('<LeftMouse><21,3>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -6923,8 +6957,12 @@ describe('builtin popupmenu', function()
eq('baz', api.nvim_get_var('menustr'))
command('set winwidth=1 | rightbelow vsplit')
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
+ else
+ feed('<RightMouse><30,4>')
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -6951,7 +6989,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250, 2, 1, 28 } },
})
else
- feed('<RightMouse><30,4>')
screen:expect([[
popup menu test |
{1:~ }{n: foo}|
@@ -6961,8 +6998,12 @@ describe('builtin popupmenu', function()
:let g:menustr = 'baz' |
]])
end
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 0, 2)
+ else
+ feed('<LeftMouse><31,1>')
+ end
+ if multigrid then
screen:expect([[
## grid 1
[2:--------------------------------]|*2
@@ -6982,7 +7023,6 @@ describe('builtin popupmenu', function()
{1:~ }|
]])
else
- feed('<LeftMouse><31,1>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -6995,8 +7035,12 @@ describe('builtin popupmenu', function()
eq('foo', api.nvim_get_var('menustr'))
command('setlocal winbar=WINBAR')
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
+ else
+ feed('<RightMouse><30,4>')
+ end
+ if multigrid then
no_sel_screen = {
grid = [[
## grid 1
@@ -7023,7 +7067,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250, 2, 1, 28 } },
}
else
- feed('<RightMouse><30,4>')
no_sel_screen = [[
popup menu test |
{1:~ }{n: foo}|
@@ -7034,20 +7077,24 @@ describe('builtin popupmenu', function()
]]
end
screen:expect(no_sel_screen)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'drag', '', 6, 0, 15)
else
feed('<RightDrag><31,3>')
end
screen:expect(screen_replace(no_sel_screen, '{n: baz}', '{12: baz}'))
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'release', '', 6, 1, 15)
else
feed('<RightRelease><31,4>')
end
screen:expect(no_sel_screen)
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('left', 'press', '', 4, 1, 2)
+ else
+ feed('<LeftMouse><31,2>')
+ end
+ if multigrid then
screen:expect([[
## grid 1
[2:--------------------------------]|*2
@@ -7067,7 +7114,6 @@ describe('builtin popupmenu', function()
^popup menu test |
]])
else
- feed('<LeftMouse><31,2>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -7181,7 +7227,7 @@ describe('builtin popupmenu', function()
{ 0, 5, 19 },
{ 0, 5, 18 },
}
- if multigrid then
+ if send_mouse_grid then
for i = 1, 7 do
local _, row, col = unpack(pos[i])
pos[i] = { 2, row - 2, col - 5 }
@@ -7206,7 +7252,7 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
- if multigrid then
+ if send_mouse_grid then
for i = 2, 6, 2 do
local _, row, col = unpack(pos[i])
pos[i] = { 4, row - 1, col - 14 }
@@ -7329,7 +7375,7 @@ describe('builtin popupmenu', function()
{ 0, 5, 21 },
{ 0, 5, 22 },
}
- if multigrid then
+ if send_mouse_grid then
for i = 1, 7 do
local _, row, col = unpack(pos[i])
pos[i] = { 2, row - 2, col - 5 }
@@ -7352,7 +7398,7 @@ describe('builtin popupmenu', function()
screen:expect(no_menu_screen)
eq('', api.nvim_get_var('menustr'))
- if multigrid then
+ if send_mouse_grid then
for i = 2, 6, 2 do
local _, row, col = unpack(pos[i])
pos[i] = { 4, row - 1, col - 12 }
@@ -7551,8 +7597,12 @@ describe('builtin popupmenu', function()
call setline(1, join(range(20)))
]])
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 45 - 1)
+ else
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1)
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -7578,7 +7628,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 33, false, 250, 2, 1, 33 } },
})
else
- api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1)
screen:expect([[
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ^18 19 |
{1:~ }{n: Undo }|
@@ -7598,8 +7647,12 @@ describe('builtin popupmenu', function()
feed('<Esc>')
command('set rightleft')
- if multigrid then
+ if send_mouse_grid then
api.nvim_input_mouse('right', 'press', '', 2, 0, 50 - 45)
+ else
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45)
+ end
+ if multigrid then
screen:expect({
grid = [[
## grid 1
@@ -7625,7 +7678,6 @@ describe('builtin popupmenu', function()
float_pos = { [4] = { -1, 'NW', 2, 1, 0, false, 250, 2, 1, 0 } },
})
else
- api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45)
screen:expect([[
91 8^1 71 61 51 41 31 21 11 01 9 8 7 6 5 4 3 2 1 0|
{n: odnU }{1: ~}|
@@ -8678,11 +8730,15 @@ describe('builtin popupmenu', function()
end
end
- describe('with ext_multigrid', function()
- with_ext_multigrid(true)
+ describe('with ext_multigrid and actual mouse grid', function()
+ with_ext_multigrid(true, true)
+ end)
+
+ describe('with ext_multigrid and mouse grid 0', function()
+ with_ext_multigrid(true, false)
end)
describe('without ext_multigrid', function()
- with_ext_multigrid(false)
+ with_ext_multigrid(false, false)
end)
end)