aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2023-08-21 10:45:25 +0800
committerzeertzjq <zeertzjq@outlook.com>2023-08-21 14:16:15 +0800
commitab45d5bf6d46abd9b29389dee6689044fd63e225 (patch)
tree02f0cf7db2832114639613ead497b45a409deb40
parent91d8f2ac534a51859c0e3c6562d07c94b27f4478 (diff)
downloadrneovim-ab45d5bf6d46abd9b29389dee6689044fd63e225.tar.gz
rneovim-ab45d5bf6d46abd9b29389dee6689044fd63e225.tar.bz2
rneovim-ab45d5bf6d46abd9b29389dee6689044fd63e225.zip
vim-patch:8.1.2044: no easy way to process postponed work
Problem: No easy way to process postponed work. (Paul Jolly) Solution: Add the SafeState autocommand event. https://github.com/vim/vim/commit/8aeec40207b5adcd3a155277dc4f29189343b963 Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r--runtime/doc/autocmd.txt21
-rw-r--r--src/nvim/auevents.lua1
-rw-r--r--src/nvim/edit.c5
-rw-r--r--src/nvim/ex_getln.c5
-rw-r--r--src/nvim/normal.c50
5 files changed, 82 insertions, 0 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index a7c28e25d0..90211fc5db 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -862,6 +862,27 @@ RecordingLeave When a macro stops recording.
Sets these |v:event| keys:
regcontents
regname
+ *SafeState*
+SafeState When nothing is pending, going to wait for the
+ user to type a character.
+ This will not be triggered when:
+ - an operator is pending
+ - a register was entered with "r
+ - halfway executing a command
+ - executing a mapping
+ - there is typeahead
+ - Insert mode completion is active
+ - Command line completion is active
+ You can use `mode()` to find out what state
+ Vim is in. That may be:
+ - VIsual mode
+ - Normal mode
+ - Insert mode
+ - Command-line mode
+ Depending on what you want to do, you may also
+ check more with `state()`, e.g. whether the
+ screen was scrolled for messages.
+
*SessionLoadPost*
SessionLoadPost After loading the session file created using
the |:mksession| command.
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index f023ee1340..696df7c534 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -85,6 +85,7 @@ return {
'RecordingEnter', -- when starting to record a macro
'RecordingLeave', -- just before a macro stops recording
'RemoteReply', -- upon string reception from a remote vim
+ 'SafeState', -- going to wait for a character
'SearchWrapped', -- after the search wrapped around
'SessionLoadPost', -- after loading a session file
'ShellCmdPost', -- after ":!cmd"
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index b8d2eca810..d980699162 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1355,6 +1355,11 @@ void ins_redraw(bool ready)
curbuf->b_changed_invalid = false;
}
+ // Trigger SafeState if nothing is pending.
+ may_trigger_safestate(ready
+ && !ins_compl_active()
+ && !pum_visible());
+
pum_check_clear();
show_cursor_info_later(false);
if (must_redraw) {
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 89f5e92c33..6af79bfd21 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -943,6 +943,8 @@ theend:
static int command_line_check(VimState *state)
{
+ CommandLineState *s = (CommandLineState *)state;
+
redir_off = true; // Don't redirect the typed command.
// Repeated, because a ":redir" inside
// completion may switch it on.
@@ -952,6 +954,9 @@ static int command_line_check(VimState *state)
// that occurs while typing a command should
// cause the command not to be executed.
+ // Trigger SafeState if nothing is pending.
+ may_trigger_safestate(s->xpc.xp_numfiles <= 0);
+
cursorcmd(); // set the cursor on the right spot
ui_cursor_shape();
return 1;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index e72a0fe385..253a3f288e 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -482,6 +482,40 @@ bool check_text_or_curbuf_locked(oparg_T *oap)
return true;
}
+static bool was_safe = false;
+static int not_safe_now = 0;
+
+/// 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
+ && !global_busy;
+
+ if (is_safe) {
+ apply_autocmds(EVENT_SAFESTATE, NULL, NULL, false, curbuf);
+ }
+ was_safe = is_safe;
+}
+
+/// Entering a not-safe state.
+void enter_unsafe_state(void)
+{
+ not_safe_now++;
+}
+
+/// Leaving a not-safe state. Trigger SafeState if we were in a safe state
+/// before first calling enter_not_safe_state().
+void leave_unsafe_state(void)
+{
+ not_safe_now--;
+ if (not_safe_now == 0 && was_safe) {
+ apply_autocmds(EVENT_SAFESTATE, NULL, NULL, false, curbuf);
+ }
+}
+
/// Normal state entry point. This is called on:
///
/// - Startup, In this case the function never returns.
@@ -1295,6 +1329,18 @@ static void normal_check_buffer_modified(NormalState *s)
}
}
+/// If nothing is pending and we are going to wait for the user to
+/// type a character, trigger SafeState.
+static void normal_check_safe_state(NormalState *s)
+{
+ may_trigger_safestate(!finish_op
+ && s->oa.prev_opcount > 0
+ && s->oa.prev_count0 == 0
+ && s->oa.op_type == OP_NOP
+ && s->oa.regname == NUL
+ && restart_edit == 0);
+}
+
static void normal_check_folds(NormalState *s)
{
// Include a closed fold completely in the Visual area.
@@ -1387,6 +1433,9 @@ static int normal_check(VimState *state)
}
quit_more = false;
+ // it's not safe unless normal_check_safe_state() is called
+ was_safe = false;
+
// 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,
// update cursor and redraw.
@@ -1403,6 +1452,7 @@ static int normal_check(VimState *state)
normal_check_text_changed(s);
normal_check_window_scrolled(s);
normal_check_buffer_modified(s);
+ normal_check_safe_state(s);
// Updating diffs from changed() does not always work properly,
// esp. updating folds. Do an update just before redrawing if