]> granicus.if.org Git - vim/commitdiff
patch 8.0.1494: no autocmd triggered in Insert mode with visible popup menu v8.0.1494
authorBram Moolenaar <Bram@vim.org>
Sat, 10 Feb 2018 17:15:19 +0000 (18:15 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 10 Feb 2018 17:15:19 +0000 (18:15 +0100)
Problem:    No autocmd triggered in Insert mode with visible popup menu.
Solution:   Add TextChangedP. (Prabir Shrestha, Christian Brabandt,
            closes #2372, closes #1691)
            Fix that the TextChanged autocommands are not always triggered
            when sourcing a script.

runtime/doc/autocmd.txt
src/edit.c
src/fileio.c
src/globals.h
src/main.c
src/proto/fileio.pro
src/structs.h
src/testdir/test_autocmd.vim
src/version.c
src/vim.h

index ede536ed6839fc8e8ebc82db6f6930fd2064c4cb..fe67774cf023bbc25647401659a85fad8b34c5e9 100644 (file)
@@ -1,4 +1,4 @@
-*autocmd.txt*   For Vim version 8.0.  Last change: 2018 Feb 09
+*autocmd.txt*   For Vim version 8.0.  Last change: 2018 Feb 10
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -332,6 +332,9 @@ Name                        triggered by ~
 
 |TextChanged|          after a change was made to the text in Normal mode
 |TextChangedI|         after a change was made to the text in Insert mode
+                       when popup menu is not visible
+|TextChangedP|         after a change was made to the text in Insert mode
+                       when popup menu visible
 |TextYankPost|         after text is yanked or deleted
 
 |ColorScheme|          after loading a color scheme
@@ -976,6 +979,11 @@ TextChangedI                       After a change was made to the text in the
                                current buffer in Insert mode.
                                Not triggered when the popup menu is visible.
                                Otherwise the same as TextChanged.
+                                                       *TextChangedP*
+TextChangedP                   After a change was made to the text in the
+                               current buffer in Insert mode, only when the
+                               popup menu is visible.  Otherwise the same as
+                               TextChanged.
                                                        *TextYankPost*
 TextYankPost                   After text has been yanked or deleted in the
                                current buffer.  The following values of
index a9e6343a806c3c932f5459db8c780d7b1c9ecd93..7074f264869cf96cbed5fb89a9ad8b4bac95697d 100644 (file)
@@ -1682,17 +1682,28 @@ ins_redraw(
 #ifdef FEAT_AUTOCMD
     /* Trigger TextChangedI if b_changedtick differs. */
     if (ready && has_textchangedI()
-           && last_changedtick != CHANGEDTICK(curbuf)
+           && curbuf->b_last_changedtick != CHANGEDTICK(curbuf)
 # ifdef FEAT_INS_EXPAND
            && !pum_visible()
 # endif
            )
     {
-       if (last_changedtick_buf == curbuf)
-           apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
-       last_changedtick_buf = curbuf;
-       last_changedtick = CHANGEDTICK(curbuf);
+       apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
+       curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
     }
+
+# ifdef FEAT_INS_EXPAND
+    /* Trigger TextChangedP if b_changedtick differs. When the popupmenu closes
+     * TextChangedI will need to trigger for backwards compatibility, thus use
+     * different b_last_changedtick* variables. */
+    if (ready && has_textchangedP()
+           && curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf)
+           && pum_visible())
+    {
+       apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf);
+       curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf);
+    }
+# endif
 #endif
 
     if (must_redraw)
index ab216abbf6984438d9b6ce3fac14799a71a828e3..d4735f344e4cf44679d8dfdef2e48036f0c592b8 100644 (file)
@@ -5037,9 +5037,8 @@ restore_backup:
 #ifdef FEAT_AUTOCMD
        /* b:changedtick is always incremented in unchanged() but that
         * should not trigger a TextChanged event. */
-       if (last_changedtick + 1 == CHANGEDTICK(buf)
-                                              && last_changedtick_buf == buf)
-           last_changedtick = CHANGEDTICK(buf);
+       if (buf->b_last_changedtick + 1 == CHANGEDTICK(buf))
+           buf->b_last_changedtick = CHANGEDTICK(buf);
 #endif
        u_unchanged(buf);
        u_update_save_nr(buf);
@@ -7851,6 +7850,7 @@ static struct event_name
     {"TermResponse",   EVENT_TERMRESPONSE},
     {"TextChanged",    EVENT_TEXTCHANGED},
     {"TextChangedI",   EVENT_TEXTCHANGEDI},
+    {"TextChangedP",   EVENT_TEXTCHANGEDP},
     {"User",           EVENT_USER},
     {"VimEnter",       EVENT_VIMENTER},
     {"VimLeave",       EVENT_VIMLEAVE},
@@ -9376,6 +9376,15 @@ has_textchangedI(void)
     return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
 }
 
+/*
+ * Return TRUE when there is a TextChangedP autocommand defined.
+ */
+    int
+has_textchangedP(void)
+{
+    return (first_autopat[(int)EVENT_TEXTCHANGEDP] != NULL);
+}
+
 /*
  * Return TRUE when there is an InsertCharPre autocommand defined.
  */
index 943bb3130a830f56b0a589d43a053721adec5942..1b2b1e8bf14d37a75b3db369e64a5c8f118c93fa 100644 (file)
@@ -1085,8 +1085,6 @@ EXTERN pos_T      last_cursormoved              /* for CursorMoved event */
                        = INIT_POS_T(0, 0, 0)
 # endif
                        ;
-EXTERN varnumber_T last_changedtick INIT(= 0);   /* for TextChanged event */
-EXTERN buf_T   *last_changedtick_buf INIT(= NULL);
 #endif
 
 EXTERN int     postponed_split INIT(= 0);  /* for CTRL-W CTRL-] command */
index 9f443aef252044781158d65404cd4b2fa79e0840..971590aab69e97d5b1bf77f1e7c6a1fecac270aa 100644 (file)
@@ -1201,13 +1201,10 @@ main_loop(
 #ifdef FEAT_AUTOCMD
            /* Trigger TextChanged if b:changedtick differs. */
            if (!finish_op && has_textchanged()
-                   && last_changedtick != CHANGEDTICK(curbuf))
+                   && curbuf->b_last_changedtick != CHANGEDTICK(curbuf))
            {
-               if (last_changedtick_buf == curbuf)
-                   apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL,
-                                                              FALSE, curbuf);
-               last_changedtick_buf = curbuf;
-               last_changedtick = CHANGEDTICK(curbuf);
+               apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, FALSE, curbuf);
+               curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
            }
 #endif
 
index 757963113f4ec951c49b033e6fa8ac71b1dc5acc..12d5c14ff3ebd94e1afb59f181838cd11cea68d4 100644 (file)
@@ -48,6 +48,7 @@ int has_cursormoved(void);
 int has_cursormovedI(void);
 int has_textchanged(void);
 int has_textchangedI(void);
+int has_textchangedP(void);
 int has_insertcharpre(void);
 int has_cmdundefined(void);
 int has_funcundefined(void);
index abfb73176fc27cab205de2bb2229804fe9a71f3c..3efd6ab3d9b78fb08f36230084b6ebd2fc1f490f 100644 (file)
@@ -1983,6 +1983,15 @@ struct file_buffer
                                   incremented for each change, also for undo */
 #define CHANGEDTICK(buf) ((buf)->b_ct_di.di_tv.vval.v_number)
 
+#ifdef FEAT_AUTOCMD
+    varnumber_T        b_last_changedtick; /* b:changedtick when TextChanged or
+                                      TextChangedI was last triggered. */
+# ifdef FEAT_INS_EXPAND
+    varnumber_T        b_last_changedtick_pum; /* b:changedtick when TextChangedP was
+                                          last triggered. */
+# endif
+#endif
+
     int                b_saving;       /* Set to TRUE if we are in the middle of
                                   saving the buffer. */
 
index 065ac4e29d0d1cd41ddccd4dd9f8c5d1a636fb34..d1ce5619735749f0aabeed2e55a2117fea683f7b 100644 (file)
@@ -1249,3 +1249,58 @@ function Test_dirchanged_auto()
   bwipe!
   call s:After_test_dirchanged()
 endfunc
+
+" Test TextChangedI and TextChangedP
+func Test_ChangedP()
+  new
+  call setline(1, ['foo', 'bar', 'foobar'])
+  call test_override("char_avail", 1)
+  set complete=. completeopt=menuone
+
+  func! TextChangedAutocmd(char)
+    let g:autocmd .= a:char
+  endfunc
+
+  au! TextChanged <buffer> :call TextChangedAutocmd('N')
+  au! TextChangedI <buffer> :call TextChangedAutocmd('I')
+  au! TextChangedP <buffer> :call TextChangedAutocmd('P')
+
+  call cursor(3, 1)
+  let g:autocmd = ''
+  call feedkeys("o\<esc>", 'tnix')
+  call assert_equal('I', g:autocmd)
+
+  let g:autocmd = ''
+  call feedkeys("Sf", 'tnix')
+  call assert_equal('II', g:autocmd)
+
+  let g:autocmd = ''
+  call feedkeys("Sf\<C-N>", 'tnix')
+  call assert_equal('IIP', g:autocmd)
+
+  let g:autocmd = ''
+  call feedkeys("Sf\<C-N>\<C-N>", 'tnix')
+  call assert_equal('IIPP', g:autocmd)
+
+  let g:autocmd = ''
+  call feedkeys("Sf\<C-N>\<C-N>\<C-N>", 'tnix')
+  call assert_equal('IIPPP', g:autocmd)
+
+  let g:autocmd = ''
+  call feedkeys("Sf\<C-N>\<C-N>\<C-N>\<C-N>", 'tnix')
+  call assert_equal('IIPPPP', g:autocmd)
+
+  call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$'))
+  " TODO: how should it handle completeopt=noinsert,noselect?
+
+  " CleanUp
+  call test_override("char_avail", 0)
+  au! TextChanged
+  au! TextChangedI
+  au! TextChangedP
+  delfu TextChangedAutocmd
+  unlet! g:autocmd
+  set complete&vim completeopt&vim
+
+  bw!
+endfunc
index 261e3d7c699e81eaae46e92d38641e8c13010f5c..f5772a8c26a1eab60ab93b451deb7d5335b45df3 100644 (file)
@@ -771,6 +771,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1494,
 /**/
     1493,
 /**/
index bd8ac0872316f29c7ce5ab0cb6d80b2ba6c7efc7..5e9f7d6d1e498fd0994595b327696682abb855ab 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -1337,8 +1337,11 @@ enum auto_event
     EVENT_TABCLOSED,           /* after closing a tab page */
     EVENT_SHELLCMDPOST,                /* after ":!cmd" */
     EVENT_SHELLFILTERPOST,     /* after ":1,2!cmd", ":w !cmd", ":r !cmd". */
-    EVENT_TEXTCHANGED,         /* text was modified */
-    EVENT_TEXTCHANGEDI,                /* text was modified in Insert mode*/
+    EVENT_TEXTCHANGED,         /* text was modified not in Insert mode */
+    EVENT_TEXTCHANGEDI,         /* text was modified in Insert mode without
+                                  popup menu visible */
+    EVENT_TEXTCHANGEDP,         /* text was modified in Insert mode with popup
+                                  menu visible */
     EVENT_CMDUNDEFINED,                /* command undefined */
     EVENT_OPTIONSET,           /* option was set */
     EVENT_TEXTYANKPOST,                /* after some text was yanked */