summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt7
-rw-r--r--src/getchar.c7
-rw-r--r--src/main.c49
-rw-r--r--src/proto/main.pro3
-rw-r--r--src/version.c2
5 files changed, 51 insertions, 17 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 7806120d6..062196665 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -9060,7 +9060,8 @@ state([{what}]) *state()*
added. E.g, this checks if the screen has scrolled: >
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
@@ -9068,7 +9069,9 @@ state([{what}]) *state()*
x executing an autocommand
w blocked on waiting, e.g. ch_evalexpr() and
ch_read(), ch_readraw() when reading json.
- c callback invoked (repeats for recursiveness up to "ccc")
+ S not triggering SafeState or SafeStateAgain
+ c callback invoked, including timer (repeats for
+ recursiveness up to "ccc")
s screen has scrolled for messages
str2float({expr}) *str2float()*
diff --git a/src/getchar.c b/src/getchar.c
index 93d0d64ee..1056e938e 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -933,7 +933,7 @@ ins_typebuf(
init_typebuf();
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);
@@ -1797,7 +1797,7 @@ 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;
}
@@ -2047,6 +2047,7 @@ parse_queued_messages(void)
int i;
int save_may_garbage_collect = may_garbage_collect;
static int entered = 0;
+ int was_safe = get_was_safe_state();
// Do not handle messages while redrawing, because it may cause buffers to
// change or be wiped while they are being redrawn.
@@ -2102,7 +2103,7 @@ parse_queued_messages(void)
// When not nested we'll go back to waiting for a typed character. If it
// was safe before then this triggers a SafeStateAgain autocommand event.
- if (entered == 1)
+ if (entered == 1 && was_safe)
may_trigger_safestateagain();
may_garbage_collect = save_may_garbage_collect;
diff --git a/src/main.c b/src/main.c
index 52bbafe6c..8c56c17b5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1049,24 +1049,33 @@ op_pending(void)
}
/*
+ * Return whether currently it is safe, assuming it was safe before (high level
+ * state didn't change).
+ */
+ static int
+is_safe_now(void)
+{
+ return stuff_empty()
+ && typebuf.tb_len == 0
+ && scriptin[curscript] == NULL
+ && !global_busy;
+}
+
+/*
* 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
- && scriptin[curscript] == NULL
- && !global_busy;
+ int is_safe = safe && is_safe_now();
#ifdef FEAT_JOB_CHANNEL
if (was_safe != is_safe)
// Only log when the state changes, otherwise it happens at nearly
// every key stroke.
- ch_log(NULL, is_safe ? "Start triggering SafeState"
- : "Stop triggering SafeState");
+ ch_log(NULL, is_safe ? "SafeState: Start triggering"
+ : "SafeState: Stop triggering");
#endif
if (is_safe)
apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf);
@@ -1079,15 +1088,21 @@ may_trigger_safestate(int safe)
* may_trigger_safestate().
*/
void
-state_no_longer_safe(void)
+state_no_longer_safe(char *reason UNUSED)
{
#ifdef FEAT_JOB_CHANNEL
if (was_safe)
- ch_log(NULL, "safe state reset");
+ ch_log(NULL, "SafeState: reset: %s", reason);
#endif
was_safe = FALSE;
}
+ int
+get_was_safe_state(void)
+{
+ return was_safe;
+}
+
/*
* Invoked when leaving code that invokes callbacks. Then trigger
* SafeStateAgain, if it was safe when starting to wait for a character.
@@ -1095,16 +1110,28 @@ state_no_longer_safe(void)
void
may_trigger_safestateagain(void)
{
+ if (!was_safe)
+ {
+ // If the safe state was reset in state_no_longer_safe(), e.g. because
+ // of calling feedkeys(), we check if it's now safe again (all keys
+ // were consumed).
+ was_safe = is_safe_now();
+#ifdef FEAT_JOB_CHANNEL
+ if (was_safe)
+ ch_log(NULL, "SafeState: undo reset");
+#endif
+ }
if (was_safe)
{
#ifdef FEAT_JOB_CHANNEL
- ch_log(NULL, "Leaving unsafe area, triggering SafeStateAgain");
+ ch_log(NULL, "SafeState: back to waiting, triggering SafeStateAgain");
#endif
apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf);
}
#ifdef FEAT_JOB_CHANNEL
else
- ch_log(NULL, "Leaving unsafe area, not triggering SafeStateAgain");
+ ch_log(NULL,
+ "SafeState: back to waiting, not triggering SafeStateAgain");
#endif
}
diff --git a/src/proto/main.pro b/src/proto/main.pro
index 873255d8f..c663cd2b1 100644
--- a/src/proto/main.pro
+++ b/src/proto/main.pro
@@ -4,7 +4,8 @@ void common_init(mparm_T *paramp);
int is_not_a_term(void);
int op_pending(void);
void may_trigger_safestate(int safe);
-void state_no_longer_safe(void);
+void state_no_longer_safe(char *reason);
+int get_was_safe_state(void);
void may_trigger_safestateagain(void);
void main_loop(int cmdwin, int noexmode);
void getout_preserve_modified(int exitval);
diff --git a/src/version.c b/src/version.c
index c0d161aac..debc3d7b1 100644
--- a/src/version.c
+++ b/src/version.c
@@ -758,6 +758,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2053,
+/**/
2052,
/**/
2051,