summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-02-10 18:15:19 +0100
committerBram Moolenaar <Bram@vim.org>2018-02-10 18:15:19 +0100
commit5a093437199001a0d60d8e18e2b9539b99a7757c (patch)
tree4897a21d58c38ac3adc0c3b309381a58f4bbde45 /src
parent9b56a57cdae31f7a2c85d440392bf63d3253a158 (diff)
patch 8.0.1494: no autocmd triggered in Insert mode with visible popup menuv8.0.1494
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.
Diffstat (limited to 'src')
-rw-r--r--src/edit.c21
-rw-r--r--src/fileio.c15
-rw-r--r--src/globals.h2
-rw-r--r--src/main.c9
-rw-r--r--src/proto/fileio.pro1
-rw-r--r--src/structs.h9
-rw-r--r--src/testdir/test_autocmd.vim55
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h7
9 files changed, 103 insertions, 18 deletions
diff --git a/src/edit.c b/src/edit.c
index a9e6343a80..7074f26486 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -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)
diff --git a/src/fileio.c b/src/fileio.c
index ab216abbf6..d4735f344e 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -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},
@@ -9377,6 +9377,15 @@ has_textchangedI(void)
}
/*
+ * 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.
*/
int
diff --git a/src/globals.h b/src/globals.h
index 943bb3130a..1b2b1e8bf1 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -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 */
diff --git a/src/main.c b/src/main.c
index 9f443aef25..971590aab6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro
index 757963113f..12d5c14ff3 100644
--- a/src/proto/fileio.pro
+++ b/src/proto/fileio.pro
@@ -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);
diff --git a/src/structs.h b/src/structs.h
index abfb73176f..3efd6ab3d9 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -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. */
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index 065ac4e29d..d1ce561973 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -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
diff --git a/src/version.c b/src/version.c
index 261e3d7c69..f5772a8c26 100644
--- a/src/version.c
+++ b/src/version.c
@@ -772,6 +772,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1494,
+/**/
1493,
/**/
1492,
diff --git a/src/vim.h b/src/vim.h
index bd8ac08723..5e9f7d6d1e 100644
--- 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 */