aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/state.c
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-02-03 13:43:48 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-02-03 13:43:48 +0800
commit74998b0449c4df0494c3bfe5d4034c575d972406 (patch)
tree17b7c5603cdb095a1b88f837a1d8bf91f3d5e6db /src/nvim/state.c
parent21cdecc8e0233d7a99d971327d21f701dbd65ba1 (diff)
downloadrneovim-74998b0449c4df0494c3bfe5d4034c575d972406.tar.gz
rneovim-74998b0449c4df0494c3bfe5d4034c575d972406.tar.bz2
rneovim-74998b0449c4df0494c3bfe5d4034c575d972406.zip
fix(event-loop): call vpeekc() directly first to check for character
Expand mappings first by calling `vpeekc()` directly.
Diffstat (limited to 'src/nvim/state.c')
-rw-r--r--src/nvim/state.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 9e4c9b2bad..f9a3aaab7f 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -39,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
@@ -55,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) {