From 7a857928842476bce8c9bed7cf549fc76c4e6489 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Thu, 29 Aug 2019 12:16:31 +0200 Subject: 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. --- src/nvim/api/vim.c | 2 -- src/nvim/lua/executor.c | 4 +++- src/nvim/tui/input.c | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 37 insertions(+), 12 deletions(-) (limited to 'src') 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; -- cgit From f8b5d6e124f97ec39002297dd0e8e32b955b6a95 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Thu, 29 Aug 2019 12:48:01 +0200 Subject: events: loop_schedule() is unclear, rename it loop_schedule_fast() --- src/nvim/event/loop.c | 12 ++++++------ src/nvim/message.c | 2 +- src/nvim/tui/input.c | 4 ++-- src/nvim/tui/tui.c | 2 +- src/nvim/ui.c | 6 +++++- 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 529ddd8eba..a01bbc9888 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -71,7 +71,7 @@ bool loop_poll_events(Loop *loop, int ms) return timeout_expired; } -/// Schedules an event from another thread. +/// Schedules a fast event from another thread. /// /// @note Event is queued into `fast_events`, which is processed outside of the /// primary `events` queue by loop_poll_events(). For `main_loop`, that @@ -79,7 +79,7 @@ bool loop_poll_events(Loop *loop, int ms) /// (VimState.execute), so redraw and other side-effects are likely to be /// skipped. /// @see loop_schedule_deferred -void loop_schedule(Loop *loop, Event event) +void loop_schedule_fast(Loop *loop, Event event) { uv_mutex_lock(&loop->mutex); multiqueue_put_event(loop->thread_events, event); @@ -87,15 +87,15 @@ void loop_schedule(Loop *loop, Event event) uv_mutex_unlock(&loop->mutex); } -/// Schedules an event from another thread. Unlike loop_schedule(), the event -/// is forwarded to `Loop.events`, instead of being processed immediately. +/// Schedules an event from another thread. Unlike loop_schedule_fast(), the +/// event is forwarded to `Loop.events`, instead of being processed immediately. /// -/// @see loop_schedule +/// @see loop_schedule_fast void loop_schedule_deferred(Loop *loop, Event event) { Event *eventp = xmalloc(sizeof(*eventp)); *eventp = event; - loop_schedule(loop, event_create(loop_deferred_event, 2, loop, eventp)); + loop_schedule_fast(loop, event_create(loop_deferred_event, 2, loop, eventp)); } static void loop_deferred_event(void **argv) { diff --git a/src/nvim/message.c b/src/nvim/message.c index 9bea9f5c4a..c8deaa590c 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -753,7 +753,7 @@ void msg_schedule_emsgf(const char *const fmt, ...) va_end(ap); char *s = xstrdup((char *)IObuff); - loop_schedule(&main_loop, event_create(msg_emsgf_event, 1, s)); + multiqueue_put(main_loop.events, msg_emsgf_event, 1, s); } /* diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index c6c9527dd9..4ac3524df2 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -164,7 +164,7 @@ static void tinput_flush(TermInput *input, bool wait_until_empty) size_t drain_boundary = wait_until_empty ? 0 : 0xff; do { uv_mutex_lock(&input->key_buffer_mutex); - loop_schedule(&main_loop, event_create(tinput_wait_enqueue, 1, input)); + loop_schedule_fast(&main_loop, event_create(tinput_wait_enqueue, 1, input)); input->waiting = true; while (input->waiting) { uv_cond_wait(&input->key_buffer_cond, &input->key_buffer_mutex); @@ -522,7 +522,7 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, TermInput *input = data; if (eof) { - loop_schedule(&main_loop, event_create(tinput_done_event, 0)); + loop_schedule_fast(&main_loop, event_create(tinput_done_event, 0)); return; } diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index ea8f9d9f71..6e1b7ef2db 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -454,7 +454,7 @@ static void tui_scheduler(Event event, void *d) { UI *ui = d; TUIData *data = ui->data; - loop_schedule(data->loop, event); // `tui_loop` local to tui_main(). + loop_schedule_fast(data->loop, event); // `tui_loop` local to tui_main(). } #ifdef UNIX diff --git a/src/nvim/ui.c b/src/nvim/ui.c index fc4a3a403d..5d191314ba 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -228,7 +228,11 @@ static void ui_refresh_event(void **argv) void ui_schedule_refresh(void) { - loop_schedule(&main_loop, event_create(ui_refresh_event, 0)); + // TODO(bfredl): "fast" is not optimal. UI should be refreshed only at + // deferred processing plus a few more blocked-on-input situtions like + // wait_return(), but not any os_breakcheck(). Alternatively make this + // defered and make wait_return() process deferred events already. + loop_schedule_fast(&main_loop, event_create(ui_refresh_event, 0)); } void ui_default_colors_set(void) -- cgit From dff06a90e496c93931b4761ee9538a301477690f Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 30 Aug 2019 20:19:56 +0200 Subject: api: make nvim_put support "\022{NUM}" regtype as returned by getregtype() --- src/nvim/ops.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/ops.c b/src/nvim/ops.c index df4452cd4a..bfd02d4ff1 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5685,9 +5685,6 @@ end: /// @param[out] reg Expected to be empty bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines) { - if (regtype.size > 1) { - return false; - } char type = regtype.data ? regtype.data[0] : NUL; switch (type) { @@ -5707,6 +5704,23 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines) return false; } + reg->y_width = 0; + if (regtype.size > 1) { + if (reg->y_type != kMTBlockWise) { + return false; + } + + // allow "b7" for a block at least 7 spaces wide + if (!ascii_isdigit(regtype.data[1])) { + return false; + } + const char *p = regtype.data+1; + reg->y_width = getdigits_int((char_u **)&p)-1; + if (regtype.size > (size_t)(p-regtype.data)) { + return false; + } + } + reg->y_array = xcalloc(lines, sizeof(uint8_t *)); reg->y_size = lines; reg->additional_data = NULL; @@ -5743,7 +5757,7 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust) } } assert(maxlen <= INT_MAX); - reg->y_width = (int)maxlen - 1; + reg->y_width = MAX(reg->y_width, (int)maxlen - 1); } } -- cgit From 2c605d1f22a243bc34b680f69c7c8cfe01b80887 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 31 Aug 2019 09:18:48 +0200 Subject: tui/input: remove "cancel paste" logic which should be redundant --- src/nvim/tui/input.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'src') diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 4ac3524df2..ed9b410a19 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -134,23 +134,11 @@ static void tinput_wait_enqueue(void **argv) 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; - } - } - + nvim_paste(keys, true, phase, &err); if (ERROR_SET(&err)) { emsgf("paste: %s", err.msg); api_clear_error(&err); -- cgit