aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2019-08-29 12:16:31 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2019-08-31 09:20:24 +0200
commit7a857928842476bce8c9bed7cf549fc76c4e6489 (patch)
tree1ee399db9dd38bf498566a91bacf852dc8c2aae5
parent8a03acb8dad4abaf507d502b11a66bd5a2b5e51e (diff)
downloadrneovim-7a857928842476bce8c9bed7cf549fc76c4e6489.tar.gz
rneovim-7a857928842476bce8c9bed7cf549fc76c4e6489.tar.bz2
rneovim-7a857928842476bce8c9bed7cf549fc76c4e6489.zip
tui/input: defer nvim_paste properly.
Otherwise cursor and redraw code for normal and insert mode will not run. The "tickle" workaround was used for this instead, and can now be removed. The builtin vim.lua got the name [string "-- Nvim-Lua stdlib: thevimmodule (:help l..."] in error messages. Fix it to something reasonable.
-rw-r--r--src/nvim/api/vim.c2
-rw-r--r--src/nvim/lua/executor.c4
-rw-r--r--src/nvim/tui/input.c43
-rw-r--r--test/functional/terminal/tui_spec.lua26
4 files changed, 58 insertions, 17 deletions
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 "<nvim>"]: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') -- <Enter>
+ feed_data('\n') -- <CR>
+ 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') -- <Enter>
+ feed_data('\n') -- <CR>
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') -- <Enter>
child_session:request('nvim_command', 'set modifiable')
feed_data('\027[200~success 1\nsuccess 2\n\027[201~')