diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-21 12:16:33 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-08-21 14:16:16 +0800 |
commit | 7ce2acd59be89e5e6d2ac778ad074a9ae42951cd (patch) | |
tree | 3e1c882297afabac76ed2de1a22b68e174d52556 | |
parent | a0b912c6ecd4bbbcf3ebdf7c1d4e60acaa7019cb (diff) | |
download | rneovim-7ce2acd59be89e5e6d2ac778ad074a9ae42951cd.tar.gz rneovim-7ce2acd59be89e5e6d2ac778ad074a9ae42951cd.tar.bz2 rneovim-7ce2acd59be89e5e6d2ac778ad074a9ae42951cd.zip |
vim-patch:8.1.2053: SafeStateAgain not triggered if callback uses feedkeys()
Problem: SafeStateAgain not triggered if callback uses feedkeys().
Solution: Check for safe state in the input loop. Make log messages easier
to find. Add 'S' flag to state().
https://github.com/vim/vim/commit/d103ee78432f9036d243b18dd5aac1263d3b7dc9
Include misc1.c change from patch 8.1.2062.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | runtime/doc/builtin.txt | 7 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 7 | ||||
-rw-r--r-- | src/nvim/eval.lua | 7 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 3 | ||||
-rw-r--r-- | src/nvim/getchar.c | 4 | ||||
-rw-r--r-- | src/nvim/normal.c | 2 | ||||
-rw-r--r-- | src/nvim/state.c | 29 |
7 files changed, 41 insertions, 18 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c57b8637e0..2ce66d8cc2 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -7385,13 +7385,16 @@ state([{what}]) *state()* added. E.g, this checks if the screen has scrolled: >vim if state('s') != '' - These characters indicate the state: + These characters indicate the state, generally indicating that + something is busy: m halfway a mapping, :normal command, feedkeys() or stuffed command o operator pending or waiting for a command argument a Insert mode autocomplete active x executing an autocommand - c callback invoked (repeats for recursiveness up to "ccc") + S not triggering SafeState + c callback invoked, including timer (repeats for + recursiveness up to "ccc") s screen has scrolled for messages stdioopen({opts}) *stdioopen()* diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index 4665f71052..70d1aa4a79 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -8760,13 +8760,16 @@ function vim.fn.srand(expr) end --- added. E.g, this checks if the screen has scrolled: >vim --- if state('s') != '' --- ---- These characters indicate the state: +--- These characters indicate the state, generally indicating that +--- something is busy: --- m halfway a mapping, :normal command, feedkeys() or --- stuffed command --- o operator pending or waiting for a command argument --- a Insert mode autocomplete active --- x executing an autocommand ---- c callback invoked (repeats for recursiveness up to "ccc") +--- S not triggering SafeState +--- c callback invoked, including timer (repeats for +--- recursiveness up to "ccc") --- s screen has scrolled for messages --- --- @param what? string diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index f244d26375..64b875c981 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -10471,13 +10471,16 @@ M.funcs = { added. E.g, this checks if the screen has scrolled: >vim if state('s') != '' - These characters indicate the state: + These characters indicate the state, generally indicating that + something is busy: m halfway a mapping, :normal command, feedkeys() or stuffed command o operator pending or waiting for a command argument a Insert mode autocomplete active x executing an autocommand - c callback invoked (repeats for recursiveness up to "ccc") + S not triggering SafeState + c callback invoked, including timer (repeats for + recursiveness up to "ccc") s screen has scrolled for messages ]=], name = 'state', diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c47fd4cfcb..8c07623369 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4955,6 +4955,9 @@ static void f_state(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!ctrl_x_mode_none()) { may_add_state_char(&ga, include, 'a'); } + if (!get_was_safe_state()) { + may_add_state_char(&ga, include, 'S'); + } for (int i = 0; i < get_callback_depth() && i < 3; i++) { may_add_state_char(&ga, include, 'c'); } diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 957f13b1da..d10e021f14 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -885,7 +885,7 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent) if (++typebuf.tb_change_cnt == 0) { typebuf.tb_change_cnt = 1; } - state_no_longer_safe(); + state_no_longer_safe("ins_typebuf()"); addlen = (int)strlen(str); @@ -1629,7 +1629,7 @@ int vgetc(void) // Need to process the character before we know it's safe to do something // else. if (c != K_IGNORE) { - state_no_longer_safe(); + state_no_longer_safe("key typed"); } return c; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 56bc75d658..40bef6b580 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1412,7 +1412,7 @@ static int normal_check(VimState *state) quit_more = false; // it's not safe unless normal_check_safe_state() is called - state_no_longer_safe(); + state_no_longer_safe(NULL); // If skip redraw is set (for ":" in wait_return()), don't redraw now. // If there is nothing in the stuff_buffer or do_redraw is true, diff --git a/src/nvim/state.c b/src/nvim/state.c index 89e4b9cbbf..ccf2a81adb 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -272,20 +272,26 @@ void may_trigger_modechanged(void) /// When true in a safe state when starting to wait for a character. static bool was_safe = false; +/// Return whether currently it is safe, assuming it was safe before (high level +/// state didn't change). +static bool is_safe_now(void) +{ + return stuff_empty() + && typebuf.tb_len == 0 + && !using_script() + && !global_busy; +} + /// Trigger SafeState if currently in s safe state, that is "safe" is TRUE and /// there is no typeahead. void may_trigger_safestate(bool safe) { - bool is_safe = safe - && stuff_empty() - && typebuf.tb_len == 0 - && !using_script() - && !global_busy; + bool is_safe = safe && is_safe_now(); if (was_safe != is_safe) { // Only log when the state changes, otherwise it happens at nearly // every key stroke. - DLOG(is_safe ? "Start triggering SafeState" : "Stop triggering SafeState"); + DLOG(is_safe ? "SafeState: Start triggering" : "SafeState: Stop triggering"); } if (is_safe) { apply_autocmds(EVENT_SAFESTATE, NULL, NULL, false, curbuf); @@ -296,10 +302,15 @@ void may_trigger_safestate(bool safe) /// Something changed which causes the state possibly to be unsafe, e.g. a /// character was typed. It will remain unsafe until the next call to /// may_trigger_safestate(). -void state_no_longer_safe(void) +void state_no_longer_safe(const char *reason) { - if (was_safe) { - DLOG("safe state reset"); + if (was_safe && reason != NULL) { + DLOG("SafeState reset: %s", reason); } was_safe = false; } + +bool get_was_safe_state(void) +{ + return was_safe; +} |