mirror of
https://github.com/neovim/neovim.git
synced 2025-09-05 19:08:15 +00:00
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.
8aeec40207
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
@@ -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.
|
||||
|
@@ -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"
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user