forked from aniani/vim
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:
@@ -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
|
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
|
|TextChanged| after a change was made to the text in Normal mode
|
||||||
|TextChangedI| after a change was made to the text in Insert 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
|
|TextYankPost| after text is yanked or deleted
|
||||||
|
|
||||||
|ColorScheme| after loading a color scheme
|
|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.
|
current buffer in Insert mode.
|
||||||
Not triggered when the popup menu is visible.
|
Not triggered when the popup menu is visible.
|
||||||
Otherwise the same as TextChanged.
|
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*
|
||||||
TextYankPost After text has been yanked or deleted in the
|
TextYankPost After text has been yanked or deleted in the
|
||||||
current buffer. The following values of
|
current buffer. The following values of
|
||||||
|
21
src/edit.c
21
src/edit.c
@@ -1682,17 +1682,28 @@ ins_redraw(
|
|||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
/* Trigger TextChangedI if b_changedtick differs. */
|
/* Trigger TextChangedI if b_changedtick differs. */
|
||||||
if (ready && has_textchangedI()
|
if (ready && has_textchangedI()
|
||||||
&& last_changedtick != CHANGEDTICK(curbuf)
|
&& curbuf->b_last_changedtick != CHANGEDTICK(curbuf)
|
||||||
# ifdef FEAT_INS_EXPAND
|
# ifdef FEAT_INS_EXPAND
|
||||||
&& !pum_visible()
|
&& !pum_visible()
|
||||||
# endif
|
# endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (last_changedtick_buf == curbuf)
|
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
|
||||||
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
|
curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
|
||||||
last_changedtick_buf = curbuf;
|
|
||||||
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
|
#endif
|
||||||
|
|
||||||
if (must_redraw)
|
if (must_redraw)
|
||||||
|
15
src/fileio.c
15
src/fileio.c
@@ -5037,9 +5037,8 @@ restore_backup:
|
|||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
/* b:changedtick is always incremented in unchanged() but that
|
/* b:changedtick is always incremented in unchanged() but that
|
||||||
* should not trigger a TextChanged event. */
|
* should not trigger a TextChanged event. */
|
||||||
if (last_changedtick + 1 == CHANGEDTICK(buf)
|
if (buf->b_last_changedtick + 1 == CHANGEDTICK(buf))
|
||||||
&& last_changedtick_buf == buf)
|
buf->b_last_changedtick = CHANGEDTICK(buf);
|
||||||
last_changedtick = CHANGEDTICK(buf);
|
|
||||||
#endif
|
#endif
|
||||||
u_unchanged(buf);
|
u_unchanged(buf);
|
||||||
u_update_save_nr(buf);
|
u_update_save_nr(buf);
|
||||||
@@ -7851,6 +7850,7 @@ static struct event_name
|
|||||||
{"TermResponse", EVENT_TERMRESPONSE},
|
{"TermResponse", EVENT_TERMRESPONSE},
|
||||||
{"TextChanged", EVENT_TEXTCHANGED},
|
{"TextChanged", EVENT_TEXTCHANGED},
|
||||||
{"TextChangedI", EVENT_TEXTCHANGEDI},
|
{"TextChangedI", EVENT_TEXTCHANGEDI},
|
||||||
|
{"TextChangedP", EVENT_TEXTCHANGEDP},
|
||||||
{"User", EVENT_USER},
|
{"User", EVENT_USER},
|
||||||
{"VimEnter", EVENT_VIMENTER},
|
{"VimEnter", EVENT_VIMENTER},
|
||||||
{"VimLeave", EVENT_VIMLEAVE},
|
{"VimLeave", EVENT_VIMLEAVE},
|
||||||
@@ -9376,6 +9376,15 @@ has_textchangedI(void)
|
|||||||
return (first_autopat[(int)EVENT_TEXTCHANGEDI] != NULL);
|
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.
|
* Return TRUE when there is an InsertCharPre autocommand defined.
|
||||||
*/
|
*/
|
||||||
|
@@ -1085,8 +1085,6 @@ EXTERN pos_T last_cursormoved /* for CursorMoved event */
|
|||||||
= INIT_POS_T(0, 0, 0)
|
= INIT_POS_T(0, 0, 0)
|
||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
EXTERN varnumber_T last_changedtick INIT(= 0); /* for TextChanged event */
|
|
||||||
EXTERN buf_T *last_changedtick_buf INIT(= NULL);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */
|
EXTERN int postponed_split INIT(= 0); /* for CTRL-W CTRL-] command */
|
||||||
|
@@ -1201,13 +1201,10 @@ main_loop(
|
|||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
/* Trigger TextChanged if b:changedtick differs. */
|
/* Trigger TextChanged if b:changedtick differs. */
|
||||||
if (!finish_op && has_textchanged()
|
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);
|
||||||
apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL,
|
curbuf->b_last_changedtick = CHANGEDTICK(curbuf);
|
||||||
FALSE, curbuf);
|
|
||||||
last_changedtick_buf = curbuf;
|
|
||||||
last_changedtick = CHANGEDTICK(curbuf);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ int has_cursormoved(void);
|
|||||||
int has_cursormovedI(void);
|
int has_cursormovedI(void);
|
||||||
int has_textchanged(void);
|
int has_textchanged(void);
|
||||||
int has_textchangedI(void);
|
int has_textchangedI(void);
|
||||||
|
int has_textchangedP(void);
|
||||||
int has_insertcharpre(void);
|
int has_insertcharpre(void);
|
||||||
int has_cmdundefined(void);
|
int has_cmdundefined(void);
|
||||||
int has_funcundefined(void);
|
int has_funcundefined(void);
|
||||||
|
@@ -1983,6 +1983,15 @@ struct file_buffer
|
|||||||
incremented for each change, also for undo */
|
incremented for each change, also for undo */
|
||||||
#define CHANGEDTICK(buf) ((buf)->b_ct_di.di_tv.vval.v_number)
|
#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
|
int b_saving; /* Set to TRUE if we are in the middle of
|
||||||
saving the buffer. */
|
saving the buffer. */
|
||||||
|
|
||||||
|
@@ -1249,3 +1249,58 @@ function Test_dirchanged_auto()
|
|||||||
bwipe!
|
bwipe!
|
||||||
call s:After_test_dirchanged()
|
call s:After_test_dirchanged()
|
||||||
endfunc
|
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
|
||||||
|
@@ -771,6 +771,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1494,
|
||||||
/**/
|
/**/
|
||||||
1493,
|
1493,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1337,8 +1337,11 @@ enum auto_event
|
|||||||
EVENT_TABCLOSED, /* after closing a tab page */
|
EVENT_TABCLOSED, /* after closing a tab page */
|
||||||
EVENT_SHELLCMDPOST, /* after ":!cmd" */
|
EVENT_SHELLCMDPOST, /* after ":!cmd" */
|
||||||
EVENT_SHELLFILTERPOST, /* after ":1,2!cmd", ":w !cmd", ":r !cmd". */
|
EVENT_SHELLFILTERPOST, /* after ":1,2!cmd", ":w !cmd", ":r !cmd". */
|
||||||
EVENT_TEXTCHANGED, /* text was modified */
|
EVENT_TEXTCHANGED, /* text was modified not in Insert mode */
|
||||||
EVENT_TEXTCHANGEDI, /* text was modified 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_CMDUNDEFINED, /* command undefined */
|
||||||
EVENT_OPTIONSET, /* option was set */
|
EVENT_OPTIONSET, /* option was set */
|
||||||
EVENT_TEXTYANKPOST, /* after some text was yanked */
|
EVENT_TEXTYANKPOST, /* after some text was yanked */
|
||||||
|
Reference in New Issue
Block a user