Patch 8.1.2046
Problem:    SafeState may be triggered at the wrong moment.
Solution:   Move it up higher to after where messages are processed.  Add a
            SafeStateAgain event to tigger there.
Files:      runtime/doc/autocmd.txt, src/main.c, src/proto/main.pro,
            src/getchar.c, src/channel.c, src/autocmd.c, src/vim.h


*** ../vim-8.1.2045/runtime/doc/autocmd.txt     2019-09-15 23:02:00.387231965 
+0200
--- runtime/doc/autocmd.txt     2019-09-16 21:56:58.233025424 +0200
***************
*** 357,362 ****
--- 357,363 ----
  
  |SafeState|           nothing pending, going to wait for the user to type a
                        character
+ |SafeStateAgain|      repeated SafeState
  
  |ColorSchemePre|      before loading a color scheme
  |ColorScheme|         after loading a color scheme
***************
*** 979,984 ****
--- 979,989 ----
                                Depending on what you want to do, you may also
                                check more with `state()`, e.g. whether the
                                screen was scrolled for messages.
+                                                       *SafeStateAgain*
+ SafeStateAgain                        Like SafeState but after processing any
+                               messages and invoking callbacks. This may be
+                               triggered often, don't do something that takes
+                               time.
  
                                                        *SessionLoadPost*
  SessionLoadPost                       After loading the session file created 
using
*** ../vim-8.1.2045/src/main.c  2019-09-15 23:02:00.387231965 +0200
--- src/main.c  2019-09-16 21:51:54.090121706 +0200
***************
*** 1029,1036 ****
  }
  
  
  static int    was_safe = FALSE;
- static int    not_safe_now = 0;
  
  /*
   * Trigger SafeState if currently in a safe state for main_loop().
--- 1029,1036 ----
  }
  
  
+ // When TRUE in a safe state when starting to wait for a character.
  static int    was_safe = FALSE;
  
  /*
   * Trigger SafeState if currently in a safe state for main_loop().
***************
*** 1057,1062 ****
--- 1057,1063 ----
      int is_safe = safe
                    && stuff_empty()
                    && typebuf.tb_len == 0
+                   && scriptin[curscript] == NULL
                    && !global_busy;
  
      if (is_safe)
***************
*** 1065,1088 ****
  }
  
  /*
!  * 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);
  }
  
  
--- 1066,1090 ----
  }
  
  /*
!  * Something changed which causes the state possibly to be unsafe, e.g. a
!  * character was typed.  It will remain unsafe until the next call to
!  * may_trigger_safestate().
   */
      void
! state_no_longer_safe(void)
  {
!     was_safe = FALSE;
  }
  
  /*
!  * Invoked when leaving code that invokes callbacks.  Then trigger
!  * SafeStateAgain, if it was safe when starting to wait for a character.
   */
      void
  leave_unsafe_state(void)
  {
!     if (was_safe)
!       apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf);
  }
  
  
*** ../vim-8.1.2045/src/proto/main.pro  2019-09-15 23:02:00.387231965 +0200
--- src/proto/main.pro  2019-09-16 21:49:55.022549676 +0200
***************
*** 3,9 ****
  void common_init(mparm_T *paramp);
  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 getout_preserve_modified(int exitval);
--- 3,9 ----
  void common_init(mparm_T *paramp);
  int is_not_a_term(void);
  void may_trigger_safestate(int safe);
! void state_no_longer_safe(void);
  void leave_unsafe_state(void);
  void main_loop(int cmdwin, int noexmode);
  void getout_preserve_modified(int exitval);
*** ../vim-8.1.2045/src/getchar.c       2019-09-15 21:00:51.358604291 +0200
--- src/getchar.c       2019-09-16 21:49:39.066607001 +0200
***************
*** 933,938 ****
--- 933,939 ----
      init_typebuf();
      if (++typebuf.tb_change_cnt == 0)
        typebuf.tb_change_cnt = 1;
+     state_no_longer_safe();
  
      addlen = (int)STRLEN(str);
  
***************
*** 1779,1788 ****
       */
      may_garbage_collect = FALSE;
  #endif
  #ifdef FEAT_BEVAL_TERM
      if (c != K_MOUSEMOVE && c != K_IGNORE && c != K_CURSORHOLD)
      {
!       /* Don't trigger 'balloonexpr' unless only the mouse was moved. */
        bevalexpr_due_set = FALSE;
        ui_remove_balloon();
      }
--- 1780,1790 ----
       */
      may_garbage_collect = FALSE;
  #endif
+ 
  #ifdef FEAT_BEVAL_TERM
      if (c != K_MOUSEMOVE && c != K_IGNORE && c != K_CURSORHOLD)
      {
!       // Don't trigger 'balloonexpr' unless only the mouse was moved.
        bevalexpr_due_set = FALSE;
        ui_remove_balloon();
      }
***************
*** 1792,1797 ****
--- 1794,1804 ----
        c = K_IGNORE;
  #endif
  
+     // Need to process the character before we know it's safe to do something
+     // else.
+     if (c != K_IGNORE)
+       state_no_longer_safe();
+ 
      return c;
  }
  
***************
*** 2039,2050 ****
--- 2046,2060 ----
      int           old_curbuf_fnum = curbuf->b_fnum;
      int           i;
      int           save_may_garbage_collect = may_garbage_collect;
+     static int entered = 0;
  
      // Do not handle messages while redrawing, because it may cause buffers to
      // change or be wiped while they are being redrawn.
      if (updating_screen)
        return;
  
+     ++entered;
+ 
      // may_garbage_collect is set in main_loop() to do garbage collection when
      // blocking to wait on a character.  We don't want that while parsing
      // messages, a callback may invoke vgetc() while lists and dicts are in 
use
***************
*** 2090,2101 ****
--- 2100,2118 ----
        break;
      }
  
+     // 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)
+       leave_unsafe_state();
+ 
      may_garbage_collect = save_may_garbage_collect;
  
      // If the current window or buffer changed we need to bail out of the
      // waiting loop.  E.g. when a job exit callback closes the terminal 
window.
      if (curwin->w_id != old_curwin_id || curbuf->b_fnum != old_curbuf_fnum)
        ins_char_typebuf(K_IGNORE);
+ 
+     --entered;
  }
  #endif
  
*** ../vim-8.1.2045/src/channel.c       2019-09-15 23:02:00.387231965 +0200
--- src/channel.c       2019-09-16 21:28:26.819018925 +0200
***************
*** 3593,3602 ****
  
      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)
        channel_add_block_id(chanpart, id);
  
--- 3593,3598 ----
***************
*** 3666,3674 ****
      if (id >= 0)
        channel_remove_block_id(chanpart, id);
  
-     // This may trigger a SafeState autocommand.
-     leave_unsafe_state();
- 
      return retval;
  }
  
--- 3662,3667 ----
*** ../vim-8.1.2045/src/autocmd.c       2019-09-15 23:02:00.387231965 +0200
--- src/autocmd.c       2019-09-16 21:31:46.302365909 +0200
***************
*** 156,161 ****
--- 156,162 ----
      {"QuitPre",               EVENT_QUITPRE},
      {"RemoteReply",   EVENT_REMOTEREPLY},
      {"SafeState",     EVENT_SAFESTATE},
+     {"SafeStateAgain",        EVENT_SAFESTATEAGAIN},
      {"SessionLoadPost",       EVENT_SESSIONLOADPOST},
      {"ShellCmdPost",  EVENT_SHELLCMDPOST},
      {"ShellFilterPost",       EVENT_SHELLFILTERPOST},
*** ../vim-8.1.2045/src/vim.h   2019-09-15 23:02:00.387231965 +0200
--- src/vim.h   2019-09-16 21:32:13.858273782 +0200
***************
*** 1316,1321 ****
--- 1316,1322 ----
      EVENT_QUITPRE,            // before :quit
      EVENT_REMOTEREPLY,                // upon string reception from a remote 
vim
      EVENT_SAFESTATE,          // going to wait for a character
+     EVENT_SAFESTATEAGAIN,     // still waiting for a character
      EVENT_SESSIONLOADPOST,    // after loading a session file
      EVENT_SHELLCMDPOST,               // after ":!cmd"
      EVENT_SHELLFILTERPOST,    // after ":1,2!cmd", ":w !cmd", ":r !cmd".
*** ../vim-8.1.2045/src/version.c       2019-09-16 21:05:21.127911692 +0200
--- src/version.c       2019-09-16 21:56:18.445169041 +0200
***************
*** 759,760 ****
--- 759,762 ----
  {   /* Add new patch number below this line */
+ /**/
+     2046,
  /**/

-- 
ARTHUR: (as the MAN next to him is squashed by a sheep) Knights!  Run away!
   Midst echoing shouts of "run away" the KNIGHTS retreat to cover with the odd
   cow or goose hitting them still.  The KNIGHTS crouch down under cover.
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201909161958.x8GJwfsm010843%40masaka.moolenaar.net.

Raspunde prin e-mail lui