diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index a39ee5d038..21cba96ba7 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -1283,8 +1283,6 @@ theend: api_free_array(args); if (cancel || phase == -1 || phase == 3) { // End of paste-stream. draining = false; - // XXX: Tickle main loop to ensure cursor is updated. - loop_schedule_deferred(&main_loop, event_create(loop_dummy_event, 0)); } return !cancel; diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 3de1b531e6..f51aa3c6d4 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -269,7 +269,9 @@ static int nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL #endif // vim - if (luaL_dostring(lstate, (char *)&vim_module[0])) { + const char *code = (char *)&vim_module[0]; + if (luaL_loadbuffer(lstate, code, strlen(code), "@vim.lua") + || lua_pcall(lstate, 0, LUA_MULTRET, 0)) { nlua_error(lstate, _("E5106: Error while creating vim module: %.*s")); return 1; } diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 1f67e6ce13..c6c9527dd9 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -106,17 +106,15 @@ static void tinput_wait_enqueue(void **argv) RBUFFER_UNTIL_EMPTY(input->key_buffer, buf, len) { const String keys = { .data = buf, .size = len }; if (input->paste) { - Error err = ERROR_INIT; - // Paste phase: "continue" (unless handler canceled). - input->paste = !nvim_paste(keys, true, input->paste, &err) - ? 0 : (1 == input->paste ? 2 : input->paste); + String copy = copy_string(keys); + 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 (ERROR_SET(&err)) { - // TODO(justinmk): emsgf() does not display, why? - msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, "paste: %s", err.msg); - api_clear_error(&err); - } } else { const size_t consumed = input_enqueue(keys); if (consumed) { @@ -134,6 +132,33 @@ static void tinput_wait_enqueue(void **argv) uv_mutex_unlock(&input->key_buffer_mutex); } +static void tinput_paste_event(void **argv) +{ + static bool canceled = false; + + String keys = { .data = argv[0], .size = (size_t)argv[1] }; + intptr_t phase = (intptr_t)argv[2]; + + if (phase == -1 || phase == 1) { + canceled = false; + } + + Error err = ERROR_INIT; + if (!canceled) { + if (!nvim_paste(keys, true, phase, &err)) { + // paste failed, ingore further segments of the same paste + canceled = true; + } + } + + if (ERROR_SET(&err)) { + emsgf("paste: %s", err.msg); + api_clear_error(&err); + } + + api_free_string(keys); +} + static void tinput_flush(TermInput *input, bool wait_until_empty) { size_t drain_boundary = wait_until_empty ? 0 : 0xff; diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 8d8c0e3647..07c91d43e1 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -352,15 +352,23 @@ describe('TUI', function() ]]} -- Start pasting... feed_data('\027[200~line 1\nline 2\n') - expect_child_buf_lines({'foo',''}) - screen:expect{any='paste: Error executing lua'} + screen:expect{grid=[[ + foo | + | + {5: }| + {8:paste: Error executing lua: [string ""]:2: f}| + {8:ake fail} | + {10:Press ENTER or type command to continue}{1: } | + {3:-- TERMINAL --} | + ]]} -- Remaining chunks are discarded after vim.paste() failure. feed_data('line 3\nline 4\n') feed_data('line 5\nline 6\n') feed_data('line 7\nline 8\n') -- Stop paste. feed_data('\027[201~') - feed_data('\n') -- + feed_data('\n') -- + expect_child_buf_lines({'foo',''}) --Dot-repeat/redo is not modified by failed paste. feed_data('.') screen:expect{grid=[[ @@ -388,7 +396,7 @@ describe('TUI', function() vim.paste = _G.save_paste_fn ]], {}) feed_data('\027[200~line A\nline B\n\027[201~') - feed_data('\n') -- + feed_data('\n') -- screen:expect{grid=[[ foo | typed input...line A | @@ -414,7 +422,15 @@ describe('TUI', function() it("paste: 'nomodifiable' buffer", function() child_session:request('nvim_command', 'set nomodifiable') feed_data('\027[200~fail 1\nfail 2\n\027[201~') - screen:expect{any='Vim:E21'} + screen:expect{grid=[[ + | + {4:~ }| + {5: }| + {8:paste: Error executing lua: vim.lua:194: Vim:E21: }| + {8:Cannot make changes, 'modifiable' is off} | + {10:Press ENTER or type command to continue}{1: } | + {3:-- TERMINAL --} | + ]]} feed_data('\n') -- child_session:request('nvim_command', 'set modifiable') feed_data('\027[200~success 1\nsuccess 2\n\027[201~')