0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.0.1494: no autocmd triggered in Insert mode with visible popup menu

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.
This commit is contained in:
Bram Moolenaar
2018-02-10 18:15:19 +01:00
parent 9b56a57cda
commit 5a09343719
10 changed files with 112 additions and 19 deletions

View 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

View 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);
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)

View 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.
*/

View 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 */

View 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

View 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);

View 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. */

View 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

View File

@@ -771,6 +771,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1494,
/**/
1493,
/**/

View File

@@ -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 */