aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/aucmd.c6
-rw-r--r--src/nvim/buffer_defs.h6
-rw-r--r--src/nvim/channel.c6
-rw-r--r--src/nvim/edit.c5
-rw-r--r--src/nvim/ex_getln.c12
-rw-r--r--src/nvim/file_search.c5
-rw-r--r--src/nvim/misc1.c31
-rw-r--r--src/nvim/ops.c5
-rw-r--r--src/nvim/terminal.c5
-rw-r--r--src/nvim/testdir/test_edit.vim6
10 files changed, 67 insertions, 20 deletions
diff --git a/src/nvim/aucmd.c b/src/nvim/aucmd.c
index af519dcba9..a236b47027 100644
--- a/src/nvim/aucmd.c
+++ b/src/nvim/aucmd.c
@@ -8,6 +8,7 @@
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/main.h"
+#include "nvim/misc1.h"
#include "nvim/os/os.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -25,13 +26,14 @@ void do_autocmd_uienter(uint64_t chanid, bool attached)
}
recursive = true;
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *dict = get_v_event(&save_v_event);
assert(chanid < VARNUMBER_MAX);
tv_dict_add_nr(dict, S_LEN("chan"), (varnumber_T)chanid);
tv_dict_set_keys_readonly(dict);
apply_autocmds(attached ? EVENT_UIENTER : EVENT_UILEAVE,
NULL, NULL, false, curbuf);
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
recursive = false;
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index bd9c5efa44..3d7b03d921 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1116,6 +1116,12 @@ typedef struct {
pos_T w_cursor_corr; // corrected cursor position
} pos_save_T;
+// Struct passed to get_v_event() and restore_v_event().
+typedef struct {
+ bool sve_did_save;
+ hashtab_T sve_hashtab;
+} save_v_event_T;
+
/// Indices into vimmenu_T->strings[] and vimmenu_T->noremap[] for each mode
/// \addtogroup MENU_INDEX
/// @{
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index 9662f6205f..a662f3a951 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -10,6 +10,7 @@
#include "nvim/event/socket.h"
#include "nvim/fileio.h"
#include "nvim/lua/executor.h"
+#include "nvim/misc1.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/os/shell.h"
@@ -821,7 +822,8 @@ static void set_info_event(void **argv)
Channel *chan = argv[0];
event_T event = (event_T)(ptrdiff_t)argv[1];
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *dict = get_v_event(&save_v_event);
Dictionary info = channel_info(chan->id);
typval_T retval;
(void)object_to_vim(DICTIONARY_OBJ(info), &retval, NULL);
@@ -829,7 +831,7 @@ static void set_info_event(void **argv)
apply_autocmds(event, NULL, NULL, false, curbuf);
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
api_free_dictionary(info);
channel_decref(chan);
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index a6b7461c59..cccb33b792 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -2719,12 +2719,13 @@ static bool pum_enough_matches(void)
static void trigger_complete_changed_event(int cur)
{
static bool recursive = false;
+ save_v_event_T save_v_event;
if (recursive) {
return;
}
- dict_T *v_event = get_vim_var_dict(VV_EVENT);
+ dict_T *v_event = get_v_event(&save_v_event);
if (cur < 0) {
tv_dict_add_dict(v_event, S_LEN("completed_item"), tv_dict_alloc());
} else {
@@ -2740,7 +2741,7 @@ static void trigger_complete_changed_event(int cur)
textlock--;
recursive = false;
- tv_dict_clear(v_event);
+ restore_v_event(v_event, &save_v_event);
}
/// Show the popup menu for the list of matches.
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 09f379d0b9..2823cb7567 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -880,7 +880,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
TryState tstate;
Error err = ERROR_INIT;
bool tl_ret = true;
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2];
firstcbuf[0] = (char)(firstc > 0 ? firstc : '-');
firstcbuf[1] = 0;
@@ -894,7 +895,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
apply_autocmds(EVENT_CMDLINEENTER, (char_u *)firstcbuf, (char_u *)firstcbuf,
false, curbuf);
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
tl_ret = try_leave(&tstate, &err);
@@ -925,7 +926,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent)
if (tv_dict_get_number(dict, "abort") != 0) {
s->gotesc = 1;
}
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
}
cmdmsg_rl = false;
@@ -2290,7 +2291,8 @@ static int command_line_changed(CommandLineState *s)
if (has_event(EVENT_CMDLINECHANGED)) {
TryState tstate;
Error err = ERROR_INIT;
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *dict = get_v_event(&save_v_event);
char firstcbuf[2];
firstcbuf[0] = (char)(s->firstc > 0 ? s->firstc : '-');
@@ -2304,7 +2306,7 @@ static int command_line_changed(CommandLineState *s)
apply_autocmds(EVENT_CMDLINECHANGED, (char_u *)firstcbuf,
(char_u *)firstcbuf, false, curbuf);
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
bool tl_ret = try_leave(&tstate, &err);
if (!tl_ret && ERROR_SET(&err)) {
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 36257fefb3..fe991963a0 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -1603,7 +1603,8 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
recursive = true;
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *dict = get_v_event(&save_v_event);
char buf[8];
switch (scope) {
@@ -1648,7 +1649,7 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope, CdCause cause)
apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false,
curbuf);
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
recursive = false;
}
diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c
index b50d8682eb..9900a68fac 100644
--- a/src/nvim/misc1.c
+++ b/src/nvim/misc1.c
@@ -1060,6 +1060,31 @@ void add_time(char_u *buf, size_t buflen, time_t tt)
}
}
+dict_T *get_v_event(save_v_event_T *sve)
+{
+ dict_T *v_event = get_vim_var_dict(VV_EVENT);
+
+ if (v_event->dv_hashtab.ht_used > 0) {
+ // recursive use of v:event, save, make empty and restore later
+ sve->sve_did_save = true;
+ sve->sve_hashtab = v_event->dv_hashtab;
+ hash_init(&v_event->dv_hashtab);
+ } else {
+ sve->sve_did_save = false;
+ }
+ return v_event;
+}
+
+void restore_v_event(dict_T *v_event, save_v_event_T *sve)
+{
+ tv_dict_free_contents(v_event);
+ if (sve->sve_did_save) {
+ v_event->dv_hashtab = sve->sve_hashtab;
+ } else {
+ hash_init(&v_event->dv_hashtab);
+ }
+}
+
/// Fires a ModeChanged autocmd.
void trigger_modechanged(void)
{
@@ -1073,7 +1098,8 @@ void trigger_modechanged(void)
return;
}
- dict_T *v_event = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *v_event = get_v_event(&save_v_event);
tv_dict_add_str(v_event, S_LEN("new_mode"), mode);
tv_dict_add_str(v_event, S_LEN("old_mode"), last_mode);
@@ -1086,6 +1112,5 @@ void trigger_modechanged(void)
last_mode = mode;
xfree(pat);
- tv_dict_free_contents(v_event);
- hash_init(&v_event->dv_hashtab);
+ restore_v_event(v_event, &save_v_event);
}
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 7d7db2a8a6..c2555add50 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2792,8 +2792,9 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
recursive = true;
+ save_v_event_T save_v_event;
// Set the v:event dictionary with information about the yank.
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ dict_T *dict = get_v_event(&save_v_event);
// The yanked text contents.
list_T *const list = tv_list_alloc((ptrdiff_t)reg->y_size);
@@ -2830,7 +2831,7 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
textlock++;
apply_autocmds(EVENT_TEXTYANKPOST, NULL, NULL, false, curbuf);
textlock--;
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
recursive = false;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 30f6ae6f34..83ade74db1 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -324,10 +324,11 @@ void terminal_close(Terminal *term, int status)
}
if (buf && !is_autocmd_blocked()) {
- dict_T *dict = get_vim_var_dict(VV_EVENT);
+ save_v_event_T save_v_event;
+ dict_T *dict = get_v_event(&save_v_event);
tv_dict_add_nr(dict, S_LEN("status"), status);
apply_autocmds(EVENT_TERMCLOSE, NULL, NULL, false, buf);
- tv_dict_clear(dict);
+ restore_v_event(dict, &save_v_event);
}
}
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index 95eb5a0c8b..7a7f4cb036 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -1721,4 +1721,10 @@ func Test_mode_changes()
unlet! g:i_to_any
endfunc
+func Test_recursive_ModeChanged()
+ au! ModeChanged * norm 0u
+ sil! norm 
+ au!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab