Mirror of the Vim source from https://github.com/vim/vim
リビジョン | a2870e6f5b453631c7946ce0617b92043ea3be83 (tree) |
---|---|
日時 | 2019-09-16 06:15:03 |
作者 | Bram Moolenaar <Bram@vim....> |
コミッター | Bram Moolenaar |
patch 8.1.2044: no easy way to process postponed work
Commit: https://github.com/vim/vim/commit/8aeec40207b5adcd3a155277dc4f29189343b963
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Sep 15 23:02:04 2019 +0200
@@ -355,6 +355,9 @@ | ||
355 | 355 | when popup menu visible |
356 | 356 | |TextYankPost| after text has been yanked or deleted |
357 | 357 | |
358 | +|SafeState| nothing pending, going to wait for the user to type a | |
359 | + character | |
360 | + | |
358 | 361 | |ColorSchemePre| before loading a color scheme |
359 | 362 | |ColorScheme| after loading a color scheme |
360 | 363 |
@@ -955,6 +958,27 @@ | ||
955 | 958 | Note that even if an autocommand is defined, |
956 | 959 | the reply should be read with |remote_read()| |
957 | 960 | to consume it. |
961 | + *SafeState* | |
962 | +SafeState When nothing is pending, going to wait for the | |
963 | + user to type a character. | |
964 | + This will not be triggered when: | |
965 | + - an operator is pending | |
966 | + - a register was entered with "r | |
967 | + - halfway executing a command | |
968 | + - executing a mapping | |
969 | + - there is typeahead | |
970 | + - Insert mode completion is active | |
971 | + - Command line completion is active | |
972 | + You can use `mode()` to find out what state | |
973 | + Vim is in. That may be: | |
974 | + - VIsual mode | |
975 | + - Normal mode | |
976 | + - Insert mode | |
977 | + - Command-line mode | |
978 | + Depending on what you want to do, you may also | |
979 | + check more with `state()`, e.g. whether the | |
980 | + screen was scrolled for messages. | |
981 | + | |
958 | 982 | *SessionLoadPost* |
959 | 983 | SessionLoadPost After loading the session file created using |
960 | 984 | the |:mksession| command. |
@@ -155,6 +155,7 @@ | ||
155 | 155 | {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE}, |
156 | 156 | {"QuitPre", EVENT_QUITPRE}, |
157 | 157 | {"RemoteReply", EVENT_REMOTEREPLY}, |
158 | + {"SafeState", EVENT_SAFESTATE}, | |
158 | 159 | {"SessionLoadPost", EVENT_SESSIONLOADPOST}, |
159 | 160 | {"ShellCmdPost", EVENT_SHELLCMDPOST}, |
160 | 161 | {"ShellFilterPost", EVENT_SHELLFILTERPOST}, |
@@ -3589,10 +3589,17 @@ | ||
3589 | 3589 | sock_T fd; |
3590 | 3590 | int timeout; |
3591 | 3591 | chanpart_T *chanpart = &channel->ch_part[part]; |
3592 | + int retval = FAIL; | |
3592 | 3593 | |
3593 | 3594 | ch_log(channel, "Blocking read JSON for id %d", id); |
3595 | + | |
3596 | + // Not considered a safe state here, since we are processing a JSON message | |
3597 | + // and parsing other messages while waiting. | |
3598 | + enter_unsafe_state(); | |
3599 | + | |
3594 | 3600 | if (id >= 0) |
3595 | 3601 | channel_add_block_id(chanpart, id); |
3602 | + | |
3596 | 3603 | for (;;) |
3597 | 3604 | { |
3598 | 3605 | more = channel_parse_json(channel, part); |
@@ -3600,10 +3607,9 @@ | ||
3600 | 3607 | // search for message "id" |
3601 | 3608 | if (channel_get_json(channel, part, id, TRUE, rettv) == OK) |
3602 | 3609 | { |
3603 | - if (id >= 0) | |
3604 | - channel_remove_block_id(chanpart, id); | |
3605 | 3610 | ch_log(channel, "Received JSON for id %d", id); |
3606 | - return OK; | |
3611 | + retval = OK; | |
3612 | + break; | |
3607 | 3613 | } |
3608 | 3614 | |
3609 | 3615 | if (!more) |
@@ -3659,7 +3665,11 @@ | ||
3659 | 3665 | } |
3660 | 3666 | if (id >= 0) |
3661 | 3667 | channel_remove_block_id(chanpart, id); |
3662 | - return FAIL; | |
3668 | + | |
3669 | + // This may trigger a SafeState autocommand. | |
3670 | + leave_unsafe_state(); | |
3671 | + | |
3672 | + return retval; | |
3663 | 3673 | } |
3664 | 3674 | |
3665 | 3675 | /* |
@@ -4195,9 +4205,9 @@ | ||
4195 | 4205 | free_job_options(&opt); |
4196 | 4206 | } |
4197 | 4207 | |
4198 | -# define KEEP_OPEN_TIME 20 /* msec */ | |
4199 | - | |
4200 | -# if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO) | |
4208 | +#define KEEP_OPEN_TIME 20 /* msec */ | |
4209 | + | |
4210 | +#if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO) | |
4201 | 4211 | /* |
4202 | 4212 | * Add open channels to the poll struct. |
4203 | 4213 | * Return the adjusted struct index. |
@@ -4288,9 +4298,9 @@ | ||
4288 | 4298 | |
4289 | 4299 | return ret; |
4290 | 4300 | } |
4291 | -# endif /* UNIX && !HAVE_SELECT */ | |
4292 | - | |
4293 | -# if (!defined(MSWIN) && defined(HAVE_SELECT)) || defined(PROTO) | |
4301 | +#endif /* UNIX && !HAVE_SELECT */ | |
4302 | + | |
4303 | +#if (!defined(MSWIN) && defined(HAVE_SELECT)) || defined(PROTO) | |
4294 | 4304 | |
4295 | 4305 | /* |
4296 | 4306 | * The "fd_set" type is hidden to avoid problems with the function proto. |
@@ -4381,7 +4391,7 @@ | ||
4381 | 4391 | if (ret > 0 && in_part->ch_fd != INVALID_FD |
4382 | 4392 | && FD_ISSET(in_part->ch_fd, wfds)) |
4383 | 4393 | { |
4384 | - /* Clear the flag first, ch_fd may change in channel_write_input(). */ | |
4394 | + // Clear the flag first, ch_fd may change in channel_write_input(). | |
4385 | 4395 | FD_CLR(in_part->ch_fd, wfds); |
4386 | 4396 | channel_write_input(channel); |
4387 | 4397 | --ret; |
@@ -4390,11 +4400,12 @@ | ||
4390 | 4400 | |
4391 | 4401 | return ret; |
4392 | 4402 | } |
4393 | -# endif /* !MSWIN && HAVE_SELECT */ | |
4403 | +#endif // !MSWIN && HAVE_SELECT | |
4394 | 4404 | |
4395 | 4405 | /* |
4396 | 4406 | * Execute queued up commands. |
4397 | - * Invoked from the main loop when it's safe to execute received commands. | |
4407 | + * Invoked from the main loop when it's safe to execute received commands, | |
4408 | + * and during a blocking wait for ch_evalexpr(). | |
4398 | 4409 | * Return TRUE when something was done. |
4399 | 4410 | */ |
4400 | 4411 | int |
@@ -1509,6 +1509,11 @@ | ||
1509 | 1509 | (linenr_T)(curwin->w_cursor.lnum + 1)); |
1510 | 1510 | } |
1511 | 1511 | |
1512 | + // Trigger SafeState if nothing is pending. | |
1513 | + may_trigger_safestate(ready | |
1514 | + && !ins_compl_active() | |
1515 | + && !pum_visible()); | |
1516 | + | |
1512 | 1517 | #if defined(FEAT_CONCEAL) |
1513 | 1518 | if ((conceal_update_lines |
1514 | 1519 | && (conceal_old_cursor_line != conceal_new_cursor_line |
@@ -971,6 +971,9 @@ | ||
971 | 971 | that occurs while typing a command should |
972 | 972 | cause the command not to be executed. */ |
973 | 973 | |
974 | + // Trigger SafeState if nothing is pending. | |
975 | + may_trigger_safestate(xpc.xp_numfiles <= 0); | |
976 | + | |
974 | 977 | cursorcmd(); /* set the cursor on the right spot */ |
975 | 978 | |
976 | 979 | /* Get a character. Ignore K_IGNORE and K_NOP, they should not do |
@@ -1028,6 +1028,64 @@ | ||
1028 | 1028 | return params.not_a_term; |
1029 | 1029 | } |
1030 | 1030 | |
1031 | + | |
1032 | +static int was_safe = FALSE; | |
1033 | +static int not_safe_now = 0; | |
1034 | + | |
1035 | +/* | |
1036 | + * Trigger SafeState if currently in a safe state for main_loop(). | |
1037 | + */ | |
1038 | + static void | |
1039 | +may_trigger_safestate_main(oparg_T *oap) | |
1040 | +{ | |
1041 | + may_trigger_safestate( | |
1042 | + !finish_op | |
1043 | + && oap->prev_opcount > 0 | |
1044 | + && oap->prev_count0 == 0 | |
1045 | + && oap->op_type == OP_NOP | |
1046 | + && oap->regname == NUL | |
1047 | + && restart_edit == 0); | |
1048 | +} | |
1049 | + | |
1050 | +/* | |
1051 | + * Trigger SafeState if currently in s safe state, that is "safe" is TRUE and | |
1052 | + * there is no typeahead. | |
1053 | + */ | |
1054 | + void | |
1055 | +may_trigger_safestate(int safe) | |
1056 | +{ | |
1057 | + int is_safe = safe | |
1058 | + && stuff_empty() | |
1059 | + && typebuf.tb_len == 0 | |
1060 | + && !global_busy; | |
1061 | + | |
1062 | + if (is_safe) | |
1063 | + apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf); | |
1064 | + was_safe = is_safe; | |
1065 | +} | |
1066 | + | |
1067 | +/* | |
1068 | + * Entering a not-safe state. | |
1069 | + */ | |
1070 | + void | |
1071 | +enter_unsafe_state(void) | |
1072 | +{ | |
1073 | + ++not_safe_now; | |
1074 | +} | |
1075 | + | |
1076 | +/* | |
1077 | + * Leaving a not-safe state. Trigger SafeState if we were in a safe state | |
1078 | + * before first calling enter_not_safe_state(). | |
1079 | + */ | |
1080 | + void | |
1081 | +leave_unsafe_state(void) | |
1082 | +{ | |
1083 | + --not_safe_now; | |
1084 | + if (not_safe_now == 0 && was_safe) | |
1085 | + apply_autocmds(EVENT_SAFESTATE, NULL, NULL, FALSE, curbuf); | |
1086 | +} | |
1087 | + | |
1088 | + | |
1031 | 1089 | /* |
1032 | 1090 | * Main loop: Execute Normal mode commands until exiting Vim. |
1033 | 1091 | * Also used to handle commands in the command-line window, until the window |
@@ -1133,6 +1191,9 @@ | ||
1133 | 1191 | msg_scroll = FALSE; |
1134 | 1192 | quit_more = FALSE; |
1135 | 1193 | |
1194 | + // it's not safe unless may_trigger_safestate_main() is called | |
1195 | + was_safe = FALSE; | |
1196 | + | |
1136 | 1197 | /* |
1137 | 1198 | * If skip redraw is set (for ":" in wait_return()), don't redraw now. |
1138 | 1199 | * If there is nothing in the stuff_buffer or do_redraw is TRUE, |
@@ -1211,6 +1272,10 @@ | ||
1211 | 1272 | curbuf->b_last_changedtick = CHANGEDTICK(curbuf); |
1212 | 1273 | } |
1213 | 1274 | |
1275 | + // If nothing is pending and we are going to wait for the user to | |
1276 | + // type a character, trigger SafeState. | |
1277 | + may_trigger_safestate_main(&oa); | |
1278 | + | |
1214 | 1279 | #if defined(FEAT_DIFF) |
1215 | 1280 | // Updating diffs from changed() does not always work properly, |
1216 | 1281 | // esp. updating folds. Do an update just before redrawing if |
@@ -2,6 +2,9 @@ | ||
2 | 2 | int vim_main2(void); |
3 | 3 | void common_init(mparm_T *paramp); |
4 | 4 | int is_not_a_term(void); |
5 | +void may_trigger_safestate(int safe); | |
6 | +void enter_unsafe_state(void); | |
7 | +void leave_unsafe_state(void); | |
5 | 8 | void main_loop(int cmdwin, int noexmode); |
6 | 9 | void getout_preserve_modified(int exitval); |
7 | 10 | void getout(int exitval); |
@@ -758,6 +758,8 @@ | ||
758 | 758 | static int included_patches[] = |
759 | 759 | { /* Add new patch number below this line */ |
760 | 760 | /**/ |
761 | + 2044, | |
762 | +/**/ | |
761 | 763 | 2043, |
762 | 764 | /**/ |
763 | 765 | 2042, |
@@ -1315,6 +1315,7 @@ | ||
1315 | 1315 | EVENT_QUICKFIXCMDPRE, // before :make, :grep etc. |
1316 | 1316 | EVENT_QUITPRE, // before :quit |
1317 | 1317 | EVENT_REMOTEREPLY, // upon string reception from a remote vim |
1318 | + EVENT_SAFESTATE, // going to wait for a character | |
1318 | 1319 | EVENT_SESSIONLOADPOST, // after loading a session file |
1319 | 1320 | EVENT_SHELLCMDPOST, // after ":!cmd" |
1320 | 1321 | EVENT_SHELLFILTERPOST, // after ":1,2!cmd", ":w !cmd", ":r !cmd". |