mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
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.
This commit is contained in:
parent
ea8dcf8346
commit
8aeec40207
@ -355,6 +355,9 @@ Name triggered by ~
|
|||||||
when popup menu visible
|
when popup menu visible
|
||||||
|TextYankPost| after text has been yanked or deleted
|
|TextYankPost| after text has been yanked or deleted
|
||||||
|
|
||||||
|
|SafeState| nothing pending, going to wait for the user to type a
|
||||||
|
character
|
||||||
|
|
||||||
|ColorSchemePre| before loading a color scheme
|
|ColorSchemePre| before loading a color scheme
|
||||||
|ColorScheme| after loading a color scheme
|
|ColorScheme| after loading a color scheme
|
||||||
|
|
||||||
@ -955,6 +958,27 @@ RemoteReply When a reply from a Vim that functions as
|
|||||||
Note that even if an autocommand is defined,
|
Note that even if an autocommand is defined,
|
||||||
the reply should be read with |remote_read()|
|
the reply should be read with |remote_read()|
|
||||||
to consume it.
|
to consume it.
|
||||||
|
*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*
|
||||||
SessionLoadPost After loading the session file created using
|
SessionLoadPost After loading the session file created using
|
||||||
the |:mksession| command.
|
the |:mksession| command.
|
||||||
|
@ -155,6 +155,7 @@ static struct event_name
|
|||||||
{"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
|
{"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
|
||||||
{"QuitPre", EVENT_QUITPRE},
|
{"QuitPre", EVENT_QUITPRE},
|
||||||
{"RemoteReply", EVENT_REMOTEREPLY},
|
{"RemoteReply", EVENT_REMOTEREPLY},
|
||||||
|
{"SafeState", EVENT_SAFESTATE},
|
||||||
{"SessionLoadPost", EVENT_SESSIONLOADPOST},
|
{"SessionLoadPost", EVENT_SESSIONLOADPOST},
|
||||||
{"ShellCmdPost", EVENT_SHELLCMDPOST},
|
{"ShellCmdPost", EVENT_SHELLCMDPOST},
|
||||||
{"ShellFilterPost", EVENT_SHELLFILTERPOST},
|
{"ShellFilterPost", EVENT_SHELLFILTERPOST},
|
||||||
|
@ -3589,10 +3589,17 @@ channel_read_json_block(
|
|||||||
sock_T fd;
|
sock_T fd;
|
||||||
int timeout;
|
int timeout;
|
||||||
chanpart_T *chanpart = &channel->ch_part[part];
|
chanpart_T *chanpart = &channel->ch_part[part];
|
||||||
|
int retval = FAIL;
|
||||||
|
|
||||||
ch_log(channel, "Blocking read JSON for id %d", id);
|
ch_log(channel, "Blocking read JSON for id %d", id);
|
||||||
|
|
||||||
|
// Not considered a safe state here, since we are processing a JSON message
|
||||||
|
// and parsing other messages while waiting.
|
||||||
|
enter_unsafe_state();
|
||||||
|
|
||||||
if (id >= 0)
|
if (id >= 0)
|
||||||
channel_add_block_id(chanpart, id);
|
channel_add_block_id(chanpart, id);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
more = channel_parse_json(channel, part);
|
more = channel_parse_json(channel, part);
|
||||||
@ -3600,10 +3607,9 @@ channel_read_json_block(
|
|||||||
// search for message "id"
|
// search for message "id"
|
||||||
if (channel_get_json(channel, part, id, TRUE, rettv) == OK)
|
if (channel_get_json(channel, part, id, TRUE, rettv) == OK)
|
||||||
{
|
{
|
||||||
if (id >= 0)
|
|
||||||
channel_remove_block_id(chanpart, id);
|
|
||||||
ch_log(channel, "Received JSON for id %d", id);
|
ch_log(channel, "Received JSON for id %d", id);
|
||||||
return OK;
|
retval = OK;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!more)
|
if (!more)
|
||||||
@ -3659,7 +3665,11 @@ channel_read_json_block(
|
|||||||
}
|
}
|
||||||
if (id >= 0)
|
if (id >= 0)
|
||||||
channel_remove_block_id(chanpart, id);
|
channel_remove_block_id(chanpart, id);
|
||||||
return FAIL;
|
|
||||||
|
// This may trigger a SafeState autocommand.
|
||||||
|
leave_unsafe_state();
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4381,7 +4391,7 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
|
|||||||
if (ret > 0 && in_part->ch_fd != INVALID_FD
|
if (ret > 0 && in_part->ch_fd != INVALID_FD
|
||||||
&& FD_ISSET(in_part->ch_fd, wfds))
|
&& FD_ISSET(in_part->ch_fd, wfds))
|
||||||
{
|
{
|
||||||
/* Clear the flag first, ch_fd may change in channel_write_input(). */
|
// Clear the flag first, ch_fd may change in channel_write_input().
|
||||||
FD_CLR(in_part->ch_fd, wfds);
|
FD_CLR(in_part->ch_fd, wfds);
|
||||||
channel_write_input(channel);
|
channel_write_input(channel);
|
||||||
--ret;
|
--ret;
|
||||||
@ -4390,11 +4400,12 @@ channel_select_check(int ret_in, void *rfds_in, void *wfds_in)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
# endif /* !MSWIN && HAVE_SELECT */
|
#endif // !MSWIN && HAVE_SELECT
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute queued up commands.
|
* Execute queued up commands.
|
||||||
* Invoked from the main loop when it's safe to execute received commands.
|
* Invoked from the main loop when it's safe to execute received commands,
|
||||||
|
* and during a blocking wait for ch_evalexpr().
|
||||||
* Return TRUE when something was done.
|
* Return TRUE when something was done.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
@ -1509,6 +1509,11 @@ ins_redraw(int ready) // not busy with something
|
|||||||
(linenr_T)(curwin->w_cursor.lnum + 1));
|
(linenr_T)(curwin->w_cursor.lnum + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger SafeState if nothing is pending.
|
||||||
|
may_trigger_safestate(ready
|
||||||
|
&& !ins_compl_active()
|
||||||
|
&& !pum_visible());
|
||||||
|
|
||||||
#if defined(FEAT_CONCEAL)
|
#if defined(FEAT_CONCEAL)
|
||||||
if ((conceal_update_lines
|
if ((conceal_update_lines
|
||||||
&& (conceal_old_cursor_line != conceal_new_cursor_line
|
&& (conceal_old_cursor_line != conceal_new_cursor_line
|
||||||
|
@ -971,6 +971,9 @@ getcmdline_int(
|
|||||||
that occurs while typing a command should
|
that occurs while typing a command should
|
||||||
cause the command not to be executed. */
|
cause the command not to be executed. */
|
||||||
|
|
||||||
|
// Trigger SafeState if nothing is pending.
|
||||||
|
may_trigger_safestate(xpc.xp_numfiles <= 0);
|
||||||
|
|
||||||
cursorcmd(); /* set the cursor on the right spot */
|
cursorcmd(); /* set the cursor on the right spot */
|
||||||
|
|
||||||
/* Get a character. Ignore K_IGNORE and K_NOP, they should not do
|
/* Get a character. Ignore K_IGNORE and K_NOP, they should not do
|
||||||
|
65
src/main.c
65
src/main.c
@ -1028,6 +1028,64 @@ is_not_a_term()
|
|||||||
return params.not_a_term;
|
return params.not_a_term;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int was_safe = FALSE;
|
||||||
|
static int not_safe_now = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trigger SafeState if currently in a safe state for main_loop().
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
may_trigger_safestate_main(oparg_T *oap)
|
||||||
|
{
|
||||||
|
may_trigger_safestate(
|
||||||
|
!finish_op
|
||||||
|
&& oap->prev_opcount > 0
|
||||||
|
&& oap->prev_count0 == 0
|
||||||
|
&& oap->op_type == OP_NOP
|
||||||
|
&& oap->regname == NUL
|
||||||
|
&& restart_edit == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trigger SafeState if currently in s safe state, that is "safe" is TRUE and
|
||||||
|
* there is no typeahead.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
may_trigger_safestate(int safe)
|
||||||
|
{
|
||||||
|
int 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main loop: Execute Normal mode commands until exiting Vim.
|
* Main loop: Execute Normal mode commands until exiting Vim.
|
||||||
* Also used to handle commands in the command-line window, until the window
|
* Also used to handle commands in the command-line window, until the window
|
||||||
@ -1133,6 +1191,9 @@ main_loop(
|
|||||||
msg_scroll = FALSE;
|
msg_scroll = FALSE;
|
||||||
quit_more = FALSE;
|
quit_more = FALSE;
|
||||||
|
|
||||||
|
// it's not safe unless may_trigger_safestate_main() is called
|
||||||
|
was_safe = FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If skip redraw is set (for ":" in wait_return()), don't redraw now.
|
* 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,
|
* If there is nothing in the stuff_buffer or do_redraw is TRUE,
|
||||||
@ -1211,6 +1272,10 @@ main_loop(
|
|||||||
curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
|
curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If nothing is pending and we are going to wait for the user to
|
||||||
|
// type a character, trigger SafeState.
|
||||||
|
may_trigger_safestate_main(&oa);
|
||||||
|
|
||||||
#if defined(FEAT_DIFF)
|
#if defined(FEAT_DIFF)
|
||||||
// Updating diffs from changed() does not always work properly,
|
// Updating diffs from changed() does not always work properly,
|
||||||
// esp. updating folds. Do an update just before redrawing if
|
// esp. updating folds. Do an update just before redrawing if
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
int vim_main2(void);
|
int vim_main2(void);
|
||||||
void common_init(mparm_T *paramp);
|
void common_init(mparm_T *paramp);
|
||||||
int is_not_a_term(void);
|
int is_not_a_term(void);
|
||||||
|
void may_trigger_safestate(int safe);
|
||||||
|
void enter_unsafe_state(void);
|
||||||
|
void leave_unsafe_state(void);
|
||||||
void main_loop(int cmdwin, int noexmode);
|
void main_loop(int cmdwin, int noexmode);
|
||||||
void getout_preserve_modified(int exitval);
|
void getout_preserve_modified(int exitval);
|
||||||
void getout(int exitval);
|
void getout(int exitval);
|
||||||
|
@ -757,6 +757,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2044,
|
||||||
/**/
|
/**/
|
||||||
2043,
|
2043,
|
||||||
/**/
|
/**/
|
||||||
|
@ -1315,6 +1315,7 @@ enum auto_event
|
|||||||
EVENT_QUICKFIXCMDPRE, // before :make, :grep etc.
|
EVENT_QUICKFIXCMDPRE, // before :make, :grep etc.
|
||||||
EVENT_QUITPRE, // before :quit
|
EVENT_QUITPRE, // before :quit
|
||||||
EVENT_REMOTEREPLY, // upon string reception from a remote vim
|
EVENT_REMOTEREPLY, // upon string reception from a remote vim
|
||||||
|
EVENT_SAFESTATE, // going to wait for a character
|
||||||
EVENT_SESSIONLOADPOST, // after loading a session file
|
EVENT_SESSIONLOADPOST, // after loading a session file
|
||||||
EVENT_SHELLCMDPOST, // after ":!cmd"
|
EVENT_SHELLCMDPOST, // after ":!cmd"
|
||||||
EVENT_SHELLFILTERPOST, // after ":1,2!cmd", ":w !cmd", ":r !cmd".
|
EVENT_SHELLFILTERPOST, // after ":1,2!cmd", ":w !cmd", ":r !cmd".
|
||||||
|
Loading…
x
Reference in New Issue
Block a user