aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/private/converter.c3
-rw-r--r--src/nvim/autocmd.c11
-rw-r--r--src/nvim/eval.c12
-rw-r--r--src/nvim/lua/converter.c3
-rw-r--r--src/nvim/ops.c4
-rw-r--r--src/nvim/tui/input.c48
-rw-r--r--test/functional/api/autocmd_spec.lua28
-rw-r--r--test/functional/api/vim_spec.lua12
-rw-r--r--test/functional/lua/vim_spec.lua33
9 files changed, 114 insertions, 40 deletions
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index 82ec1ad0d8..a26383ec7d 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -65,8 +65,7 @@ typedef struct {
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \
ufunc_T *fp = find_func(fun); \
- assert(fp != NULL); \
- if (fp->uf_cb == nlua_CFunction_func_call) { \
+ if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \
LuaRef ref = api_new_luaref(((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
kvi_push(edata->stack, LUAREF_OBJ(ref)); \
} else { \
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index df336d8703..a36f2c97b5 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -2013,6 +2013,7 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
}
AutoCmd *ac = acp->nextcmd;
+ bool oneshot = ac->once;
if (p_verbose >= 9) {
verbose_enter_scroll();
@@ -2024,7 +2025,13 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
if (ac->exec.type == CALLABLE_CB) {
typval_T argsin = TV_INITIAL_VALUE;
typval_T rettv = TV_INITIAL_VALUE;
- callback_call(&ac->exec.callable.cb, 0, &argsin, &rettv);
+ if (callback_call(&ac->exec.callable.cb, 0, &argsin, &rettv)) {
+ if (ac->exec.callable.cb.type == kCallbackLua) {
+ // If a Lua callback returns 'true' then the autocommand is removed
+ oneshot = true;
+ }
+ }
+
// TODO(tjdevries):
//
@@ -2042,7 +2049,7 @@ char_u *getnextac(int c, void *cookie, int indent, bool do_concat)
}
// Remove one-shot ("once") autocmd in anticipation of its execution.
- if (ac->once) {
+ if (oneshot) {
aucmd_del(ac);
}
autocmd_nested = ac->nested;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index af7c3d4985..33e8469768 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7730,6 +7730,7 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
partial_T *partial;
char_u *name;
Array args = ARRAY_DICT_INIT;
+ Object rv;
switch (callback->type) {
case kCallbackFuncref:
name = callback->data.funcref;
@@ -7742,10 +7743,13 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
break;
case kCallbackLua:
- nlua_call_ref(callback->data.luaref, NULL, args, false, NULL);
-
- return false;
- break;
+ rv = nlua_call_ref(callback->data.luaref, NULL, args, true, NULL);
+ switch (rv.type) {
+ case kObjectTypeBoolean:
+ return rv.data.boolean;
+ default:
+ return false;
+ }
case kCallbackNone:
return false;
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 0bb224c729..ef49a03660 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -477,8 +477,7 @@ static bool typval_conv_special = false;
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
do { \
ufunc_T *fp = find_func(fun); \
- assert(fp != NULL); \
- if (fp->uf_cb == nlua_CFunction_func_call) { \
+ if (fp != NULL && fp->uf_cb == nlua_CFunction_func_call) { \
nlua_pushref(lstate, ((LuaCFunctionState *)fp->uf_cb_state)->lua_callable.func_ref); \
} else { \
TYPVAL_ENCODE_CONV_NIL(tv); \
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 244a1881aa..fc66fb5f06 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -2835,9 +2835,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
curr->y_size = j;
xfree(reg->y_array);
}
- if (curwin->w_p_rnu) {
- redraw_later(curwin, SOME_VALID); // cursor moved to start
- }
+
if (message) { // Display message about yank?
if (yank_type == kMTCharWise && yanklines == 1) {
yanklines = 0;
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 917847608a..24958ce041 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -115,34 +115,28 @@ static void tinput_done_event(void **argv)
static void tinput_wait_enqueue(void **argv)
{
TermInput *input = argv[0];
- if (rbuffer_size(input->key_buffer) == 0 && input->paste == 3) {
- // End streamed paste with an empty string.
- const String keys = { .data = "", .size = 0 };
- String copy = copy_string(keys);
- multiqueue_put(main_loop.events, tinput_paste_event, 3,
- copy.data, copy.size, (intptr_t)input->paste);
- }
- RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) {
- const String keys = { .data = buf, .size = len };
- if (input->paste) {
- String copy = copy_string(keys);
- if (ui_client_channel_id) {
- Array args = ARRAY_DICT_INIT;
- ADD(args, STRING_OBJ(copy_string(keys))); // 'data'
- ADD(args, BOOLEAN_OBJ(true)); // 'crlf'
- ADD(args, INTEGER_OBJ(input->paste)); // 'phase'
- rpc_send_event(ui_client_channel_id, "nvim_paste", args);
- } else {
- multiqueue_put(main_loop.events, tinput_paste_event, 3,
- copy.data, copy.size, (intptr_t)input->paste);
- }
- if (input->paste == 1) {
- // Paste phase: "continue"
- input->paste = 2;
- }
- rbuffer_consumed(input->key_buffer, len);
- rbuffer_reset(input->key_buffer);
+ if (input->paste) { // produce exactly one paste event
+ const size_t len = rbuffer_size(input->key_buffer);
+ String keys = { .data = xmallocz(len), .size = len };
+ rbuffer_read(input->key_buffer, keys.data, len);
+ if (ui_client_channel_id) {
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, STRING_OBJ(keys)); // 'data'
+ ADD(args, BOOLEAN_OBJ(true)); // 'crlf'
+ ADD(args, INTEGER_OBJ(input->paste)); // 'phase'
+ rpc_send_event(ui_client_channel_id, "nvim_paste", args);
} else {
+ multiqueue_put(main_loop.events, tinput_paste_event, 3,
+ keys.data, keys.size, (intptr_t)input->paste);
+ }
+ if (input->paste == 1) {
+ // Paste phase: "continue"
+ input->paste = 2;
+ }
+ rbuffer_reset(input->key_buffer);
+ } else { // enqueue input for the main thread or Nvim server
+ RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) {
+ const String keys = { .data = buf, .size = len };
size_t consumed;
if (ui_client_channel_id) {
Array args = ARRAY_DICT_INIT;
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index 372cbf2c30..a58ca00a75 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -154,6 +154,34 @@ describe('autocmd api', function()
eq(1, #aus, aus)
end)
end)
+
+ it('removes an autocommand if the callback returns true', function()
+ meths.set_var("some_condition", false)
+
+ exec_lua [[
+ vim.api.nvim_create_autocmd("User", {
+ pattern = "Test",
+ desc = "A test autocommand",
+ callback = function()
+ return vim.g.some_condition
+ end,
+ })
+ ]]
+
+ meths.do_autocmd("User", {pattern = "Test"})
+ eq({{
+ buflocal = false,
+ command = 'A test autocommand',
+ desc = 'A test autocommand',
+ event = 'User',
+ id = 1,
+ once = false,
+ pattern = 'Test',
+ }}, meths.get_autocmds({event = "User", pattern = "Test"}))
+ meths.set_var("some_condition", true)
+ meths.do_autocmd("User", {pattern = "Test"})
+ eq({}, meths.get_autocmds({event = "User", pattern = "Test"}))
+ end)
end)
describe('nvim_get_autocmds', function()
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index af6872760a..ed9d915954 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -6,6 +6,7 @@ local assert_alive = helpers.assert_alive
local NIL = helpers.NIL
local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq
local command = helpers.command
+local exec = helpers.exec
local eval = helpers.eval
local expect = helpers.expect
local funcs = helpers.funcs
@@ -1271,6 +1272,17 @@ describe('API', function()
eq('Key is locked: lua', pcall_err(meths.del_var, 'lua'))
eq('Key is locked: lua', pcall_err(meths.set_var, 'lua', 1))
+ exec([[
+ function Test()
+ endfunction
+ function s:Test()
+ endfunction
+ let g:Unknown_func = function('Test')
+ let g:Unknown_script_func = function('s:Test')
+ ]])
+ eq(NIL, meths.get_var('Unknown_func'))
+ eq(NIL, meths.get_var('Unknown_script_func'))
+
-- Check if autoload works properly
local pathsep = helpers.get_pathsep()
local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index 5b4daf02ea..38cb54fbc6 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -1043,6 +1043,17 @@ describe('lua stdlib', function()
exec_lua([[vim.api.nvim_get_var('funcs').add()]])
eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
+ exec([[
+ function Test()
+ endfunction
+ function s:Test()
+ endfunction
+ let g:Unknown_func = function('Test')
+ let g:Unknown_script_func = function('s:Test')
+ ]])
+ eq(NIL, exec_lua([[return vim.g.Unknown_func]]))
+ eq(NIL, exec_lua([[return vim.g.Unknown_script_func]]))
+
-- Check if autoload works properly
local pathsep = helpers.get_pathsep()
local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
@@ -1136,6 +1147,17 @@ describe('lua stdlib', function()
exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
+ exec([[
+ function Test()
+ endfunction
+ function s:Test()
+ endfunction
+ let b:Unknown_func = function('Test')
+ let b:Unknown_script_func = function('s:Test')
+ ]])
+ eq(NIL, exec_lua([[return vim.b.Unknown_func]]))
+ eq(NIL, exec_lua([[return vim.b.Unknown_script_func]]))
+
exec_lua [[
vim.cmd "vnew"
]]
@@ -1219,6 +1241,17 @@ describe('lua stdlib', function()
exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
+ exec([[
+ function Test()
+ endfunction
+ function s:Test()
+ endfunction
+ let w:Unknown_func = function('Test')
+ let w:Unknown_script_func = function('s:Test')
+ ]])
+ eq(NIL, exec_lua([[return vim.w.Unknown_func]]))
+ eq(NIL, exec_lua([[return vim.w.Unknown_script_func]]))
+
exec_lua [[
vim.cmd "vnew"
]]