aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2018-05-19 11:48:37 +0200
committerJustin M. Keyes <justinkz@gmail.com>2018-05-19 11:48:37 +0200
commitfb28b0c734c259b0964615ea2ddeb4aabeb23fe8 (patch)
tree2f4a9a7217955b5dd37632bb4fb6e31b1bda2afb
parenta82ac8accb0dba4c13b670c69f0024c94c59cdd4 (diff)
parentd995825c6627dd99213aeeecef56663d4655f701 (diff)
downloadrneovim-fb28b0c734c259b0964615ea2ddeb4aabeb23fe8.tar.gz
rneovim-fb28b0c734c259b0964615ea2ddeb4aabeb23fe8.tar.bz2
rneovim-fb28b0c734c259b0964615ea2ddeb4aabeb23fe8.zip
Merge #8377 'TextChangedP autocommand'
-rw-r--r--runtime/doc/autocmd.txt8
-rw-r--r--src/nvim/auevents.lua3
-rw-r--r--src/nvim/buffer_defs.h5
-rw-r--r--src/nvim/edit.c19
-rw-r--r--src/nvim/fileio.c5
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/normal.c10
-rw-r--r--src/nvim/testdir/test_autocmd.vim57
-rw-r--r--test/functional/viml/completion_spec.lua89
9 files changed, 179 insertions, 20 deletions
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index 06a016eddb..0b7cd5b2cd 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -325,6 +325,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
|ColorScheme| after loading a color scheme
@@ -969,6 +972,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.
*User*
User Never executed automatically. To be used for
autocommands that are only executed with
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 1153314e76..f07a92ab87 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -85,7 +85,8 @@ return {
'TermOpen', -- after opening a terminal buffer
'TermResponse', -- after setting "v:termresponse"
'TextChanged', -- text was modified
- 'TextChangedI', -- text was modified in Insert mode
+ 'TextChangedI', -- text was modified in Insert mode(no popup)
+ 'TextChangedP', -- text was modified in Insert mode(popup)
'TextYankPost', -- after a yank or delete was done (y, d, c)
'User', -- user defined autocommand
'VimEnter', -- after starting Vim
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 53edae58a5..807baf02c1 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -484,6 +484,11 @@ struct file_buffer {
#define b_changedtick changedtick_di.di_tv.vval.v_number
ChangedtickDictItem changedtick_di; // b:changedtick dictionary item.
+ varnumber_T b_last_changedtick; // b:changedtick when TextChanged or
+ // TextChangedI was last triggered.
+ varnumber_T b_last_changedtick_pum; // b:changedtick when TextChangedP was
+ // last triggered.
+
bool b_saving; /* Set to true if we are in the middle of
saving the buffer. */
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index a1987cf2d5..462762aea0 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -1387,13 +1387,20 @@ ins_redraw (
// Trigger TextChangedI if b_changedtick differs.
if (ready && has_event(EVENT_TEXTCHANGEDI)
- && last_changedtick != curbuf->b_changedtick
+ && curbuf->b_last_changedtick != curbuf->b_changedtick
&& !pum_visible()) {
- if (last_changedtick_buf == curbuf) {
- apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, false, curbuf);
- }
- last_changedtick_buf = curbuf;
- last_changedtick = curbuf->b_changedtick;
+ apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, false, curbuf);
+ curbuf->b_last_changedtick = curbuf->b_changedtick;
+ }
+
+ // 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_event(EVENT_TEXTCHANGEDP)
+ && curbuf->b_last_changedtick_pum != curbuf->b_changedtick
+ && pum_visible()) {
+ apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, false, curbuf);
+ curbuf->b_last_changedtick_pum = curbuf->b_changedtick;
}
if (must_redraw)
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index efeee1ba2b..520aedaac7 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -3571,9 +3571,8 @@ restore_backup:
unchanged(buf, TRUE);
/* buf->b_changedtick is always incremented in unchanged() but that
* should not trigger a TextChanged event. */
- if (last_changedtick + 1 == buf->b_changedtick
- && last_changedtick_buf == buf) {
- last_changedtick = buf->b_changedtick;
+ if (buf->b_last_changedtick + 1 == buf->b_changedtick) {
+ buf->b_last_changedtick = buf->b_changedtick;
}
u_unchanged(buf);
u_update_save_nr(buf);
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index ddc58c2425..4aa0ef7def 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -868,9 +868,6 @@ EXTERN int did_cursorhold INIT(= false); // set when CursorHold t'gerd
// for CursorMoved event
EXTERN pos_T last_cursormoved INIT(= INIT_POS_T(0, 0, 0));
-EXTERN varnumber_T last_changedtick INIT(= 0); // for TextChanged event
-EXTERN buf_T *last_changedtick_buf INIT(= NULL);
-
EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */
EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */
EXTERN int postponed_split_tab INIT(= 0); /* cmdmod.tab */
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 43e8b6fb3d..a2aaf8f9af 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -1215,13 +1215,9 @@ static void normal_check_text_changed(NormalState *s)
{
// Trigger TextChanged if b_changedtick differs.
if (!finish_op && has_event(EVENT_TEXTCHANGED)
- && last_changedtick != curbuf->b_changedtick) {
- if (last_changedtick_buf == curbuf) {
- apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, false, curbuf);
- }
-
- last_changedtick_buf = curbuf;
- last_changedtick = curbuf->b_changedtick;
+ && curbuf->b_last_changedtick != curbuf->b_changedtick) {
+ apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, false, curbuf);
+ curbuf->b_last_changedtick = curbuf->b_changedtick;
}
}
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 24651b75e1..238de5a87d 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -1165,3 +1165,60 @@ func Test_nocatch_wipe_dummy_buffer()
call assert_fails('lv½ /x', 'E480')
au!
endfunc
+
+" Test TextChangedI and TextChangedP
+func Test_ChangedP() abort
+ " Nvim does not support test_override().
+ throw 'skipped: see test/functional/viml/completion_spec.lua'
+ 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/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua
index 216ccb3744..c14f7fc1a6 100644
--- a/test/functional/viml/completion_spec.lua
+++ b/test/functional/viml/completion_spec.lua
@@ -3,7 +3,10 @@ local Screen = require('test.functional.ui.screen')
local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect
+local curbufmeths = helpers.curbufmeths
+local command = helpers.command
local meths = helpers.meths
+local wait = helpers.wait
describe('completion', function()
local screen
@@ -971,4 +974,90 @@ describe('ui/ext_popupmenu', function()
eq(nil, items) -- popupmenu was hidden
end)
end)
+
+ it('TextChangedP autocommand', function()
+ curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar'})
+ source([[
+ set complete=. completeopt=menuone
+ let g:foo = []
+ autocmd! TextChanged * :call add(g:foo, "N")
+ autocmd! TextChangedI * :call add(g:foo, "I")
+ autocmd! TextChangedP * :call add(g:foo, "P")
+ call cursor(3, 1)
+ ]])
+
+ command('let g:foo = []')
+ feed('o')
+ wait()
+ feed('<esc>')
+ eq({'I'}, eval('g:foo'))
+
+ command('let g:foo = []')
+ feed('S')
+ wait()
+ feed('f')
+ wait()
+ eq({'I', 'I'}, eval('g:foo'))
+ feed('<esc>')
+
+ command('let g:foo = []')
+ feed('S')
+ wait()
+ feed('f')
+ wait()
+ feed('<C-N>')
+ wait()
+ eq({'I', 'I', 'P'}, eval('g:foo'))
+ feed('<esc>')
+
+ command('let g:foo = []')
+ feed('S')
+ wait()
+ feed('f')
+ wait()
+ feed('<C-N>')
+ wait()
+ feed('<C-N>')
+ wait()
+ eq({'I', 'I', 'P', 'P'}, eval('g:foo'))
+ feed('<esc>')
+
+ command('let g:foo = []')
+ feed('S')
+ wait()
+ feed('f')
+ wait()
+ feed('<C-N>')
+ wait()
+ feed('<C-N>')
+ wait()
+ feed('<C-N>')
+ wait()
+ eq({'I', 'I', 'P', 'P', 'P'}, eval('g:foo'))
+ feed('<esc>')
+
+ command('let g:foo = []')
+ feed('S')
+ wait()
+ feed('f')
+ wait()
+ feed('<C-N>')
+ wait()
+ feed('<C-N>')
+ wait()
+ feed('<C-N>')
+ wait()
+ feed('<C-N>')
+ eq({'I', 'I', 'P', 'P', 'P', 'P'}, eval('g:foo'))
+ feed('<esc>')
+
+ eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")'))
+
+ source([[
+ au! TextChanged
+ au! TextChangedI
+ au! TextChangedP
+ set complete&vim completeopt&vim
+ ]])
+ end)
end)