aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml7
-rw-r--r--src/nvim/buffer.c8
-rw-r--r--src/nvim/eval/buffer.c4
-rw-r--r--src/nvim/globals.h1
-rw-r--r--src/nvim/memline.c127
-rw-r--r--src/nvim/mouse.c28
-rw-r--r--src/nvim/popupmenu.c2
-rw-r--r--test/functional/ui/statuscolumn_spec.lua16
8 files changed, 111 insertions, 82 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 48a450be36..c07ae66c6f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -6,8 +6,13 @@ body:
- type: markdown
attributes:
value: |
- _Before reporting:_ run `make distclean` when encountering build issues, search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ). Usage or "How to" questions belong on the [stackoverflow](https://vi.stackexchange.com/) and will be closed.
+ *Before reporting:*
+ - Confirm the problem is reproducible on [**master**](https://github.com/neovim/neovim/releases/nightly) or [**latest stable**](https://github.com/neovim/neovim/releases/stable) release
+ - run `make distclean` when encountering build issues
+ - search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
+ - check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ)
+ Usage or "How to" questions belong on the [stackoverflow](https://vi.stackexchange.com/) and will be closed.
- type: textarea
attributes:
label: "Problem"
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index c89d4f667a..9df886ef9a 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -930,10 +930,14 @@ static void free_buffer_stuff(buf_T *buf, int free_flags)
/// Go to another buffer. Handles the result of the ATTENTION dialog.
void goto_buffer(exarg_T *eap, int start, int dir, int count)
{
+ const int save_sea = swap_exists_action;
+
bufref_T old_curbuf;
set_bufref(&old_curbuf, curbuf);
- swap_exists_action = SEA_DIALOG;
+ if (swap_exists_action == SEA_NONE) {
+ swap_exists_action = SEA_DIALOG;
+ }
(void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
start, dir, count, eap->forceit);
@@ -946,7 +950,7 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
// Quitting means closing the split window, nothing else.
win_close(curwin, true, false);
- swap_exists_action = SEA_NONE;
+ swap_exists_action = save_sea;
swap_exists_did_quit = true;
// Restore the error/interrupt/exception state if not discarded by a
diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c
index 616c1e06fc..93e4f14980 100644
--- a/src/nvim/eval/buffer.c
+++ b/src/nvim/eval/buffer.c
@@ -298,7 +298,9 @@ void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr)
buf_T *buf = get_buf_arg(&argvars[0]);
if (buf != NULL) {
- swap_exists_action = SEA_NONE;
+ if (swap_exists_action != SEA_READONLY) {
+ swap_exists_action = SEA_NONE;
+ }
buf_ensure_loaded(buf);
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 077f48580c..cc66fac48f 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -684,6 +684,7 @@ EXTERN bool in_assert_fails INIT( = false); // assert_fails() active
#define SEA_DIALOG 1 // use dialog when possible
#define SEA_QUIT 2 // quit editing the file
#define SEA_RECOVER 3 // recover the file
+#define SEA_READONLY 4 // no dialog, mark buffer as read-only
EXTERN int swap_exists_action INIT( = SEA_NONE); ///< For dialog when swap file already exists.
EXTERN bool swap_exists_did_quit INIT( = false); ///< Selected "quit" at the dialog.
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 26757d6ed1..ea7a61b8dd 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -235,6 +235,16 @@ typedef enum {
UB_SAME_DIR, // update the B0_SAME_DIR flag
} upd_block0_T;
+typedef enum {
+ SEA_CHOICE_NONE = 0,
+ SEA_CHOICE_READONLY = 1,
+ SEA_CHOICE_EDIT = 2,
+ SEA_CHOICE_RECOVER = 3,
+ SEA_CHOICE_DELETE = 4,
+ SEA_CHOICE_QUIT = 5,
+ SEA_CHOICE_ABORT = 6,
+} sea_choice_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memline.c.generated.h"
#endif
@@ -3235,15 +3245,8 @@ static void attention_message(buf_T *buf, char *fname)
/// Trigger the SwapExists autocommands.
///
-/// @return a value for equivalent to do_dialog() (see below):
-/// 0: still need to ask for a choice
-/// 1: open read-only
-/// 2: edit anyway
-/// 3: recover
-/// 4: delete it
-/// 5: quit
-/// 6: abort
-static int do_swapexists(buf_T *buf, char *fname)
+/// @return a value for equivalent to do_dialog().
+static sea_choice_T do_swapexists(buf_T *buf, char *fname)
{
set_vim_var_string(VV_SWAPNAME, fname, -1);
set_vim_var_string(VV_SWAPCHOICE, NULL, -1);
@@ -3258,20 +3261,20 @@ static int do_swapexists(buf_T *buf, char *fname)
switch (*get_vim_var_str(VV_SWAPCHOICE)) {
case 'o':
- return 1;
+ return SEA_CHOICE_READONLY;
case 'e':
- return 2;
+ return SEA_CHOICE_EDIT;
case 'r':
- return 3;
+ return SEA_CHOICE_RECOVER;
case 'd':
- return 4;
+ return SEA_CHOICE_DELETE;
case 'q':
- return 5;
+ return SEA_CHOICE_QUIT;
case 'a':
- return 6;
+ return SEA_CHOICE_ABORT;
}
- return 0;
+ return SEA_CHOICE_NONE;
}
/// Find out what name to use for the swapfile for buffer 'buf'.
@@ -3384,13 +3387,13 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// - the buffer was not recovered
if (differ == false && !(curbuf->b_flags & BF_RECOVERED)
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL) {
- int choice = 0;
+ sea_choice_T choice = SEA_CHOICE_NONE;
// It's safe to delete the swapfile if all these are true:
// - the edited file exists
// - the swapfile has no changes and looks OK
if (os_path_exists(buf->b_fname) && swapfile_unchanged(fname)) {
- choice = 4;
+ choice = SEA_CHOICE_DELETE;
if (p_verbose > 0) {
verb_msg(_("Found a swap file that is not useful, deleting it"));
}
@@ -3398,14 +3401,19 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// If there is a SwapExists autocommand and we can handle the
// response, trigger it. It may return 0 to ask the user anyway.
- if (choice == 0
+ if (choice == SEA_CHOICE_NONE
&& swap_exists_action != SEA_NONE
&& has_autocmd(EVENT_SWAPEXISTS, buf_fname, buf)) {
choice = do_swapexists(buf, fname);
}
+ if (choice == SEA_CHOICE_NONE && swap_exists_action == SEA_READONLY) {
+ // always open readonly.
+ choice = SEA_CHOICE_READONLY;
+ }
+
process_running = 0; // Set by attention_message..swapfile_info.
- if (choice == 0) {
+ if (choice == SEA_CHOICE_NONE) {
// Show info about the existing swapfile.
attention_message(buf, fname);
@@ -3418,7 +3426,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
flush_buffers(FLUSH_TYPEAHEAD);
}
- if (swap_exists_action != SEA_NONE && choice == 0) {
+ if (swap_exists_action != SEA_NONE && choice == SEA_CHOICE_NONE) {
const char *const sw_msg_1 = _("Swap file \"");
const char *const sw_msg_2 = _("\" already exists!");
@@ -3432,56 +3440,57 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
memcpy(name, sw_msg_1, sw_msg_1_len + 1);
home_replace(NULL, fname, &name[sw_msg_1_len], fname_len, true);
xstrlcat(name, sw_msg_2, name_len);
- choice = do_dialog(VIM_WARNING, _("VIM - ATTENTION"),
- name,
- process_running
- ? _("&Open Read-Only\n&Edit anyway\n&Recover"
- "\n&Quit\n&Abort")
- : _("&Open Read-Only\n&Edit anyway\n&Recover"
- "\n&Delete it\n&Quit\n&Abort"),
- 1, NULL, false);
-
- if (process_running && choice >= 4) {
- choice++; // Skip missing "Delete it" button.
+ int dialog_result
+ = do_dialog(VIM_WARNING,
+ _("VIM - ATTENTION"),
+ name,
+ process_running
+ ? _("&Open Read-Only\n&Edit anyway\n&Recover\n&Quit\n&Abort")
+ : _("&Open Read-Only\n&Edit anyway\n&Recover\n&Delete it\n&Quit\n&Abort"),
+ 1, NULL, false);
+
+ if (process_running && dialog_result >= 4) {
+ // compensate for missing "Delete it" button
+ dialog_result++;
}
+ choice = (sea_choice_T)dialog_result;
xfree(name);
// pretend screen didn't scroll, need redraw anyway
msg_reset_scroll();
}
- if (choice > 0) {
- switch (choice) {
- case 1: // "Open Read-Only"
- buf->b_p_ro = true;
- break;
- case 2: // "Edit anyway"
- break;
- case 3: // "Recover"
- swap_exists_action = SEA_RECOVER;
- break;
- case 4: // "Delete it"
- os_remove(fname);
- break;
- case 5: // "Quit"
- swap_exists_action = SEA_QUIT;
- break;
- case 6: // "Abort"
- swap_exists_action = SEA_QUIT;
- got_int = true;
- break;
- }
-
- // If the swapfile was deleted this `fname` can be used.
- if (!os_path_exists(fname)) {
- break;
- }
- } else {
+ switch (choice) {
+ case SEA_CHOICE_READONLY: // "Open Read-Only"
+ buf->b_p_ro = true;
+ break;
+ case SEA_CHOICE_EDIT: // "Edit anyway"
+ break;
+ case SEA_CHOICE_RECOVER: // "Recover"
+ swap_exists_action = SEA_RECOVER;
+ break;
+ case SEA_CHOICE_DELETE: // "Delete it"
+ os_remove(fname);
+ break;
+ case SEA_CHOICE_QUIT: // "Quit"
+ swap_exists_action = SEA_QUIT;
+ break;
+ case SEA_CHOICE_ABORT: // "Abort"
+ swap_exists_action = SEA_QUIT;
+ got_int = true;
+ break;
+ case SEA_CHOICE_NONE:
msg_puts("\n");
if (msg_silent == 0) {
// call wait_return() later
need_wait_return = true;
}
+ break;
+ }
+
+ // If the swapfile was deleted this `fname` can be used.
+ if (choice != SEA_CHOICE_NONE && !os_path_exists(fname)) {
+ break;
}
}
}
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 368153cad6..0b4cd5dd14 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -132,6 +132,8 @@ static void move_tab_to_mouse(void)
}
}
+static bool got_click = false; // got a click some time back
+
/// Call click definition function for column "col" in the "click_defs" array for button
/// "which_button".
static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button)
@@ -187,6 +189,8 @@ static void call_click_def_func(StlClickDefinition *click_defs, int col, int whi
typval_T rettv;
(void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
tv_clear(&rettv);
+ // Make sure next click does not register as drag when callback absorbs the release event.
+ got_click = false;
}
/// Translate window coordinates to buffer position without any side effects.
@@ -241,14 +245,6 @@ static int get_fpos_of_mouse(pos_T *mpos)
return IN_BUFFER;
}
-static bool mouse_got_click = false; ///< got a click some time back
-
-/// Reset the flag that a mouse click was seen.
-void reset_mouse_got_click(void)
-{
- mouse_got_click = false;
-}
-
/// Do the appropriate action for the current mouse click in the current mode.
/// Not used for Command-line mode.
///
@@ -347,13 +343,13 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
// Ignore drag and release events if we didn't get a click.
if (is_click) {
- mouse_got_click = true;
+ got_click = true;
} else {
- if (!mouse_got_click) { // didn't get click, ignore
+ if (!got_click) { // didn't get click, ignore
return false;
}
if (!is_drag) { // release, reset got_click
- mouse_got_click = false;
+ got_click = false;
if (in_tab_line) {
in_tab_line = false;
return false;
@@ -370,7 +366,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
stuffnumReadbuff(count);
}
stuffcharReadbuff(Ctrl_T);
- mouse_got_click = false; // ignore drag&release now
+ got_click = false; // ignore drag&release now
return false;
}
@@ -594,7 +590,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
ui_flush(); // Update before showing popup menu
}
show_popupmenu();
- mouse_got_click = false; // ignore release events
+ got_click = false; // ignore release events
return (jump_flags & CURSOR_MOVED) != 0;
}
if (which_button == MOUSE_LEFT
@@ -634,7 +630,7 @@ popupexit:
// If an operator is pending, ignore all drags and releases until the next mouse click.
if (!is_drag && oap != NULL && oap->op_type != OP_NOP) {
- mouse_got_click = false;
+ got_click = false;
oap->motion_type = kMTCharWise;
}
@@ -844,7 +840,7 @@ popupexit:
} else { // location list window
do_cmdline_cmd(".ll");
}
- mouse_got_click = false; // ignore drag&release now
+ got_click = false; // ignore drag&release now
} else if ((mod_mask & MOD_MASK_CTRL)
|| (curbuf->b_help && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)) {
// Ctrl-Mouse click (or double click in a help window) jumps to the tag
@@ -853,7 +849,7 @@ popupexit:
stuffcharReadbuff(Ctrl_O);
}
stuffcharReadbuff(Ctrl_RSB);
- mouse_got_click = false; // ignore drag&release now
+ got_click = false; // ignore drag&release now
} else if ((mod_mask & MOD_MASK_SHIFT)) {
// Shift-Mouse click searches for the next occurrence of the word under
// the mouse pointer
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index e04d0c7acd..a6eb32ecb1 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -26,7 +26,6 @@
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
-#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
@@ -1148,7 +1147,6 @@ void pum_show_popupmenu(vimmenu_T *menu)
// right mouse release: select clicked item, close if any
pum_select_mouse_pos();
if (pum_selected >= 0) {
- reset_mouse_got_click();
pum_execute_menu(menu, mode);
break;
}
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index 73039701cd..6eaf15cfad 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -590,7 +590,7 @@ describe('statuscolumn', function()
eq('0 1 l 11', eval("g:testvar"))
end)
- it('selecting popupmenu does not drag mouse', function()
+ it('popupmenu callback does not drag mouse on close', function()
screen:try_resize(screen._width, 2)
screen:set_default_attr_ids({
[0] = {foreground = Screen.colors.Brown},
@@ -604,6 +604,7 @@ describe('statuscolumn', function()
popup PopupStc
endfunction
]])
+ -- clicking an item does not drag mouse
meths.input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{0:8 }^aaaaa |
@@ -615,6 +616,19 @@ describe('statuscolumn', function()
{0:8 }^aaaaa |
0 1 l 8 |
]])
+ command('echo')
+ -- clicking outside to close the menu does not drag mouse
+ meths.input_mouse('left', 'press', '', 0, 0, 0)
+ screen:expect([[
+ {0:8 }^aaaaa |
+ {1: Echo } |
+ ]])
+ meths.input_mouse('left', 'press', '', 0, 0, 10)
+ meths.input_mouse('left', 'release', '', 0, 0, 10)
+ screen:expect([[
+ {0:8 }^aaaaa |
+ |
+ ]])
end)
end)
end