diff options
Diffstat (limited to 'src/nvim/state.c')
-rw-r--r-- | src/nvim/state.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/src/nvim/state.c b/src/nvim/state.c index 68bc76660d..f9a3aaab7f 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -12,6 +12,7 @@ #include "nvim/lib/kvec.h" #include "nvim/log.h" #include "nvim/main.h" +#include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/os/input.h" #include "nvim/state.h" @@ -38,10 +39,16 @@ void state_enter(VimState *s) int key; getkey: - if (char_avail() || using_script() || input_available()) { - // Don't block for events if there's a character already available for - // processing. Characters can come from mappings, scripts and other - // sources, so this scenario is very common. + // Expand mappings first by calling vpeekc() directly. + // - If vpeekc() returns non-NUL, there is a character already available for processing, so + // don't block for events. vgetc() may still block, in case of an incomplete UTF-8 sequence. + // - If vpeekc() returns NUL, vgetc() will block, and there are three cases: + // - There is no input available. + // - All of available input maps to an empty string. + // - There is an incomplete mapping. + // A blocking wait for a character should only be done in the third case, which is the only + // case of the three where typebuf.tb_len > 0 after vpeekc() returns NUL. + if (vpeekc() != NUL || typebuf.tb_len > 0) { key = safe_vgetc(); } else if (!multiqueue_empty(main_loop.events)) { // Event was made available after the last multiqueue_process_events call @@ -54,9 +61,11 @@ getkey: // mapping engine. (void)os_inchar(NULL, 0, -1, 0, main_loop.events); // If an event was put into the queue, we send K_EVENT directly. - key = !multiqueue_empty(main_loop.events) - ? K_EVENT - : safe_vgetc(); + if (!multiqueue_empty(main_loop.events)) { + key = K_EVENT; + } else { + goto getkey; + } } if (key == K_EVENT) { @@ -107,15 +116,17 @@ void state_handle_k_event(void) /// Return true if in the current mode we need to use virtual. bool virtual_active(void) { + unsigned int cur_ve_flags = get_ve_flags(); + // While an operator is being executed we return "virtual_op", because // VIsual_active has already been reset, thus we can't check for "block" // being used. if (virtual_op != kNone) { return virtual_op; } - return ve_flags == VE_ALL - || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V) - || ((ve_flags & VE_INSERT) && (State & INSERT)); + return cur_ve_flags == VE_ALL + || ((cur_ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V) + || ((cur_ve_flags & VE_INSERT) && (State & INSERT)); } /// VISUAL, SELECTMODE and OP_PENDING State are never set, they are equal to @@ -180,7 +191,7 @@ char *get_mode(void) buf[1] = 'x'; } } - } else if (State & CMDLINE) { + } else if ((State & CMDLINE) || exmode_active) { buf[0] = 'c'; if (exmode_active) { buf[1] = 'v'; |