aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt4
-rw-r--r--src/nvim/eval.c53
-rw-r--r--src/nvim/eval.h3
-rw-r--r--test/functional/eval/vvar_event_spec.lua15
4 files changed, 66 insertions, 9 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index ad736e9c81..bc3dda97a5 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1386,6 +1386,10 @@ v:errors Errors found by assert functions, such as |assert_true()|.
< If v:errors is set to anything but a list it is made an empty
list by the assert function.
+ *v:event* *event-variable*
+v:event Dictionary of event data for the current |autocommand|. The
+ available keys differ per event type and are specified at the
+ documentation for each |event|.
*v:exception* *exception-variable*
v:exception The value of the exception most recently caught and not
finished. See also |v:throwpoint| and |throw-variables|.
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 76deedfad0..376ec5cedb 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -378,6 +378,7 @@ static struct vimvar {
{ VV_NAME("option_type", VAR_STRING), VV_RO },
{ VV_NAME("errors", VAR_LIST), 0 },
{ VV_NAME("msgpack_types", VAR_DICT), VV_RO },
+ { VV_NAME("event", VAR_DICT), VV_RO },
};
/* shorthand */
@@ -545,6 +546,10 @@ void eval_init(void)
set_vim_var_dict(VV_MSGPACK_TYPES, msgpack_types_dict);
set_vim_var_dict(VV_COMPLETED_ITEM, dict_alloc());
+
+ dict_T *v_event = dict_alloc();
+ v_event->dv_lock = VAR_FIXED;
+ set_vim_var_dict(VV_EVENT, v_event);
set_vim_var_list(VV_ERRORS, list_alloc());
set_vim_var_nr(VV_SEARCHFORWARD, 1L);
set_vim_var_nr(VV_HLSEARCH, 1L);
@@ -6017,6 +6022,27 @@ static void rettv_dict_alloc(typval_T *rettv)
++d->dv_refcount;
}
+/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary.
+///
+/// @param d The Dictionary to clear
+void dict_clear(dict_T *d)
+ FUNC_ATTR_NONNULL_ALL
+{
+ hash_lock(&d->dv_hashtab);
+ assert(d->dv_hashtab.ht_locked > 0);
+
+ size_t todo = d->dv_hashtab.ht_used;
+ for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) {
+ if (!HASHITEM_EMPTY(hi)) {
+ dictitem_free(HI2DI(hi));
+ hash_remove(&d->dv_hashtab, hi);
+ todo--;
+ }
+ }
+
+ hash_unlock(&d->dv_hashtab);
+}
+
/*
* Unreference a Dictionary: decrement the reference count and free it when it
@@ -6258,6 +6284,24 @@ int dict_add_list(dict_T *d, char *key, list_T *list)
return OK;
}
+/// Set all existing keys in "dict" as read-only.
+///
+/// This does not protect against adding new keys to the Dictionary.
+///
+/// @param dict The dict whose keys should be frozen
+void dict_set_keys_readonly(dict_T *dict)
+ FUNC_ATTR_NONNULL_ALL
+{
+ size_t todo = dict->dv_hashtab.ht_used;
+ for (hashitem_T *hi = dict->dv_hashtab.ht_array; todo > 0 ; hi++) {
+ if (HASHITEM_EMPTY(hi)) {
+ continue;
+ }
+ todo--;
+ HI2DI(hi)->di_flags |= DI_FLAGS_RO | DI_FLAGS_FIX;
+ }
+}
+
/*
* Get the number of items in a Dictionary.
*/
@@ -18162,14 +18206,7 @@ void set_vim_var_dict(int idx, dict_T *val)
if (val != NULL) {
++val->dv_refcount;
// Set readonly
- size_t todo = val->dv_hashtab.ht_used;
- for (hashitem_T *hi = val->dv_hashtab.ht_array; todo > 0 ; ++hi) {
- if (HASHITEM_EMPTY(hi)) {
- continue;
- }
- --todo;
- HI2DI(hi)->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
- }
+ dict_set_keys_readonly(val);
}
}
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 79a1341d98..f51b0f4921 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -113,7 +113,8 @@ enum {
VV_OPTION_TYPE,
VV_ERRORS,
VV_MSGPACK_TYPES,
- VV_LEN, /* number of v: vars */
+ VV_EVENT,
+ VV_LEN, // number of v: vars
};
/// Maximum number of function arguments
diff --git a/test/functional/eval/vvar_event_spec.lua b/test/functional/eval/vvar_event_spec.lua
new file mode 100644
index 0000000000..bbac86524f
--- /dev/null
+++ b/test/functional/eval/vvar_event_spec.lua
@@ -0,0 +1,15 @@
+local helpers = require('test.functional.helpers')
+local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq
+local command = helpers.command
+describe('v:event', function()
+ before_each(clear)
+ it('is empty before any autocommand', function()
+ eq({}, eval('v:event'))
+ end)
+
+ it('is immutable', function()
+ eq(false, pcall(command, 'let v:event = {}'))
+ eq(false, pcall(command, 'let v:event.mykey = {}'))
+ end)
+end)
+