mirror of
https://github.com/vim/vim.git
synced 2026-05-30 14:07:27 +02:00
patch 9.2.0470: No way to hook into put commands
Problem: No way to hook into put commands
(yochem)
Solution: Introduce TextPutPre and TextPutPost autocommands
(Foxe Chen).
fixes: #18701
closes: #20144
Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
e3d9929109
commit
e0781bd5bf
+42
-1
@@ -1,4 +1,4 @@
|
||||
*autocmd.txt* For Vim version 9.2. Last change: 2026 Feb 25
|
||||
*autocmd.txt* For Vim version 9.2. Last change: 2026 May 10
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -421,6 +421,8 @@ Name triggered by ~
|
||||
|TextChangedP| after a change was made to the text in Insert mode
|
||||
when popup menu visible
|
||||
|TextChangedT| after a change was made to the text in Terminal mode
|
||||
|TextPutPost| after text has been put
|
||||
|TextPutPre| before text is put
|
||||
|TextYankPost| after text has been yanked or deleted
|
||||
|
||||
|SafeState| nothing pending, going to wait for the user to type a
|
||||
@@ -1359,6 +1361,45 @@ TextChangedP After a change was made to the text in the
|
||||
TextChangedT After a change was made to the text in the
|
||||
current buffer in Terminal mode.
|
||||
Otherwise the same as TextChanged.
|
||||
*TextPutPost*
|
||||
TextPutPost After text has been put in the current buffer.
|
||||
The following values in |v:event| are mostly
|
||||
the same as |TextYankPost|:
|
||||
operator The operation performed,
|
||||
either 'p' or 'P'.
|
||||
regcontents Text that was put. For
|
||||
|quote_=|, this is the result
|
||||
of the expression.
|
||||
regname Name of the register or empty
|
||||
string for the unnamed
|
||||
register.
|
||||
regtype Type of the register, see
|
||||
|getregtype()|.
|
||||
visual True if the operation is
|
||||
performed in |Visual| mode.
|
||||
Not triggered when |quote_| is used nor when
|
||||
called recursively.
|
||||
It is not allowed to change the buffer text,
|
||||
see |textlock|.
|
||||
Note that for the |quote_.| register, since
|
||||
the last inserted text is buffered into the
|
||||
input buffer (buffer isn't modified directly),
|
||||
this autocommand is called directly after
|
||||
|TextPutPre|.
|
||||
{only when compiled with the +eval feature}
|
||||
*TextPutPre*
|
||||
TextPutPre Before text has been put in the current buffer.
|
||||
Same values as |TextPutPost| in |v:event|. It
|
||||
is valid to call |setreg()| in this
|
||||
autocommand, allowing you to process and
|
||||
modify the text in "regcontents" before it is
|
||||
put. However this does not apply to |quote_#|,
|
||||
|quote_=|, |quote_%|, |quote_:|, |quote_/| or |quote_.|.
|
||||
Not triggered when |quote_| is used nor when
|
||||
called recursively.
|
||||
It is not allowed to change the buffer text,
|
||||
see |textlock|.
|
||||
{only when compiled with the +eval feature}
|
||||
*TextYankPost*
|
||||
TextYankPost After text has been yanked or deleted in the
|
||||
current buffer. The following values of
|
||||
|
||||
@@ -5969,6 +5969,8 @@ TextChanged autocmd.txt /*TextChanged*
|
||||
TextChangedI autocmd.txt /*TextChangedI*
|
||||
TextChangedP autocmd.txt /*TextChangedP*
|
||||
TextChangedT autocmd.txt /*TextChangedT*
|
||||
TextPutPost autocmd.txt /*TextPutPost*
|
||||
TextPutPre autocmd.txt /*TextPutPre*
|
||||
TextYankPost autocmd.txt /*TextYankPost*
|
||||
Transact-SQL ft_sql.txt /*Transact-SQL*
|
||||
Tuple eval.txt /*Tuple*
|
||||
|
||||
@@ -52669,6 +52669,8 @@ Functions: ~
|
||||
Autocommands: ~
|
||||
|
||||
|SessionLoadPre| before loading a |Session| file
|
||||
|TextPutPost| after putting text
|
||||
|TextPutPre| before putting text
|
||||
|
||||
Options: ~
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
" Language: Vim script
|
||||
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
|
||||
" Doug Kearns <dougkearns@gmail.com>
|
||||
" Last Change: 2026 May 08
|
||||
" Last Change: 2026 May 10
|
||||
" Former Maintainer: Charles E. Campbell
|
||||
|
||||
" DO NOT CHANGE DIRECTLY.
|
||||
@@ -134,8 +134,8 @@ syn keyword vimErrSetting contained invakm invaltkeymap invanti invantialias inv
|
||||
syn case ignore
|
||||
" GEN_SYN_VIM: vimAutoEvent, START_STR='syn keyword vimAutoEvent contained', END_STR='skipwhite nextgroup=vimAutoEventSep,@vimAutocmdPattern'
|
||||
syn keyword vimAutoEvent contained BufAdd BufCreate BufDelete BufEnter BufFilePost BufFilePre BufHidden BufLeave BufNew BufNewFile BufRead BufReadCmd BufReadPost BufReadPre BufUnload BufWinEnter BufWinLeave BufWipeout BufWrite BufWriteCmd BufWritePost BufWritePre CmdlineChanged CmdlineEnter CmdlineLeave CmdlineLeavePre CmdUndefined CmdwinEnter CmdwinLeave ColorScheme ColorSchemePre CompleteChanged CompleteDone CompleteDonePre CursorHold CursorHoldI CursorMoved CursorMovedC CursorMovedI DiffUpdated DirChanged DirChangedPre EncodingChanged ExitPre FileAppendCmd FileAppendPost FileAppendPre FileChangedRO FileChangedShell FileChangedShellPost FileEncoding FileReadCmd FileReadPost FileReadPre FileType FileWriteCmd FileWritePost FileWritePre FilterReadPost FilterReadPre skipwhite nextgroup=vimAutoEventSep,@vimAutocmdPattern
|
||||
syn keyword vimAutoEvent contained FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave InsertLeavePre KeyInputPre MenuPopup ModeChanged OptionSet QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SafeState SafeStateAgain SessionLoadPost SessionLoadPre SessionWritePost ShellCmdPost ShellFilterPost SigUSR1 SourceCmd SourcePost SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabClosed TabClosedPre TabEnter TabLeave TabNew TermChanged TerminalOpen TerminalWinOpen TermResponse TermResponseAll TextChanged TextChangedI TextChangedP TextChangedT TextYankPost VimEnter VimLeave VimLeavePre VimResized VimResume VimSuspend WinClosed WinEnter WinLeave WinNew WinNewPre skipwhite nextgroup=vimAutoEventSep,@vimAutocmdPattern
|
||||
syn keyword vimAutoEvent contained WinResized WinScrolled skipwhite nextgroup=vimAutoEventSep,@vimAutocmdPattern
|
||||
syn keyword vimAutoEvent contained FilterWritePost FilterWritePre FocusGained FocusLost FuncUndefined GUIEnter GUIFailed InsertChange InsertCharPre InsertEnter InsertLeave InsertLeavePre KeyInputPre MenuPopup ModeChanged OptionSet QuickFixCmdPost QuickFixCmdPre QuitPre RemoteReply SafeState SafeStateAgain SessionLoadPost SessionLoadPre SessionWritePost ShellCmdPost ShellFilterPost SigUSR1 SourceCmd SourcePost SourcePre SpellFileMissing StdinReadPost StdinReadPre SwapExists Syntax TabClosed TabClosedPre TabEnter TabLeave TabNew TermChanged TerminalOpen TerminalWinOpen TermResponse TermResponseAll TextChanged TextChangedI TextChangedP TextChangedT TextPutPost TextPutPre TextYankPost VimEnter VimLeave VimLeavePre VimResized VimResume VimSuspend WinClosed WinEnter skipwhite nextgroup=vimAutoEventSep,@vimAutocmdPattern
|
||||
syn keyword vimAutoEvent contained WinLeave WinNew WinNewPre WinResized WinScrolled skipwhite nextgroup=vimAutoEventSep,@vimAutocmdPattern
|
||||
|
||||
syn keyword vimAutoEvent contained User skipwhite nextgroup=vimUserAutoEvent
|
||||
syn match vimUserAutoEvent contained "\<\h\w*\>" skipwhite nextgroup=vimUserAutoEventSep,vimAutocmdMod,vimAutocmdBlock
|
||||
|
||||
@@ -195,6 +195,8 @@ static keyvalue_T event_tab[NUM_EVENTS] = {
|
||||
KEYVALUE_ENTRY(-EVENT_TEXTCHANGEDI, "TextChangedI"),
|
||||
KEYVALUE_ENTRY(-EVENT_TEXTCHANGEDP, "TextChangedP"),
|
||||
KEYVALUE_ENTRY(-EVENT_TEXTCHANGEDT, "TextChangedT"),
|
||||
KEYVALUE_ENTRY(-EVENT_TEXTPUTPOST, "TextPutPost"),
|
||||
KEYVALUE_ENTRY(-EVENT_TEXTPUTPRE, "TextPutPre"),
|
||||
KEYVALUE_ENTRY(-EVENT_TEXTYANKPOST, "TextYankPost"),
|
||||
KEYVALUE_ENTRY(EVENT_USER, "User"),
|
||||
KEYVALUE_ENTRY(EVENT_VIMENTER, "VimEnter"),
|
||||
@@ -2023,6 +2025,25 @@ has_cmdundefined(void)
|
||||
}
|
||||
|
||||
#if defined(FEAT_EVAL)
|
||||
|
||||
/*
|
||||
* Return TRUE when there is a TextPutPost autocommand defined.
|
||||
*/
|
||||
int
|
||||
has_textputpost(void)
|
||||
{
|
||||
return (first_autopat[(int)EVENT_TEXTPUTPOST] != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when there is a TextPutPre autocommand defined.
|
||||
*/
|
||||
int
|
||||
has_textputpre(void)
|
||||
{
|
||||
return (first_autopat[(int)EVENT_TEXTPUTPRE] != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE when there is a TextYankPost autocommand defined.
|
||||
*/
|
||||
|
||||
@@ -714,6 +714,11 @@ stuffRedoReadbuff(char_u *s)
|
||||
void
|
||||
stuffReadbuffLen(char_u *s, long len)
|
||||
{
|
||||
#ifdef FEAT_EVAL
|
||||
if (add_last_insert == 1) // Only add if this is the first call, for
|
||||
// recursive calls, ignore.
|
||||
ga_concat_len(&last_insert_ga, s, (size_t)len);
|
||||
#endif
|
||||
add_buff(&readbuf1, s, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -2165,3 +2165,11 @@ EXTERN bool inside_redraw_on_start_cb INIT(= false);
|
||||
|
||||
// If greater than zero, then silence the W23/W24 warning.
|
||||
EXTERN int silence_w23_w24_msg INIT( = 0);
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
// Used by TextPutPost/TextPutPre autocommands for the '.' register. If
|
||||
// "add_last_insert" is == 1, then "stuff_inserted" will add the last inserted
|
||||
// text to "last_insert_ga".
|
||||
EXTERN garray_T last_insert_ga INIT5(0, 0, 1, 64, NULL);
|
||||
EXTERN int add_last_insert INIT(= 0);
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,8 @@ int has_textchangedP(void);
|
||||
int has_insertcharpre(void);
|
||||
int has_keyinputpre(void);
|
||||
int has_cmdundefined(void);
|
||||
int has_textputpost(void);
|
||||
int has_textputpre(void);
|
||||
int has_textyankpost(void);
|
||||
int has_completechanged(void);
|
||||
int has_modechanged(void);
|
||||
|
||||
+154
-24
@@ -1081,6 +1081,36 @@ shift_delete_registers(void)
|
||||
}
|
||||
|
||||
#if defined(FEAT_EVAL)
|
||||
static void
|
||||
add_regtype_to_dict(int regname, dict_T *dict, char_u *buf, int bufsize)
|
||||
{
|
||||
size_t buflen;
|
||||
long reglen;
|
||||
// Register type
|
||||
switch (get_reg_type(regname, ®len))
|
||||
{
|
||||
case MLINE:
|
||||
buf[0] = 'V';
|
||||
buf[1] = NUL;
|
||||
buflen = 1;
|
||||
break;
|
||||
case MCHAR:
|
||||
buf[0] = 'v';
|
||||
buf[1] = NUL;
|
||||
buflen = 1;
|
||||
break;
|
||||
case MBLOCK:
|
||||
buflen = vim_snprintf_safelen((char *)buf, bufsize,
|
||||
"%c%ld", Ctrl_V, reglen + 1);
|
||||
break;
|
||||
default:
|
||||
buf[0] = NUL;
|
||||
buflen = 0;
|
||||
break;
|
||||
}
|
||||
(void)dict_add_string_len(dict, "regtype", buf, (int)buflen);
|
||||
}
|
||||
|
||||
void
|
||||
yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
||||
{
|
||||
@@ -1090,7 +1120,6 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
||||
int n;
|
||||
char_u buf[NUMBUFLEN + 2];
|
||||
size_t buflen;
|
||||
long reglen = 0;
|
||||
save_v_event_T save_v_event;
|
||||
|
||||
if (recursive)
|
||||
@@ -1124,29 +1153,7 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
||||
buflen = (buf[0] == NUL) ? 0 : (buf[1] == NUL) ? 1 : 2;
|
||||
(void)dict_add_string_len(v_event, "operator", buf, (int)buflen);
|
||||
|
||||
// register type
|
||||
switch (get_reg_type(oap->regname, ®len))
|
||||
{
|
||||
case MLINE:
|
||||
buf[0] = 'V';
|
||||
buf[1] = NUL;
|
||||
buflen = 1;
|
||||
break;
|
||||
case MCHAR:
|
||||
buf[0] = 'v';
|
||||
buf[1] = NUL;
|
||||
buflen = 1;
|
||||
break;
|
||||
case MBLOCK:
|
||||
buflen = vim_snprintf_safelen((char *)buf, sizeof(buf),
|
||||
"%c%ld", Ctrl_V, reglen + 1);
|
||||
break;
|
||||
default:
|
||||
buf[0] = NUL;
|
||||
buflen = 0;
|
||||
break;
|
||||
}
|
||||
(void)dict_add_string_len(v_event, "regtype", buf, (int)buflen);
|
||||
add_regtype_to_dict(oap->regname, v_event, buf, sizeof(buf));
|
||||
|
||||
// selection type - visual or not
|
||||
(void)dict_add_bool(v_event, "visual", oap->is_VIsual);
|
||||
@@ -1163,6 +1170,85 @@ yank_do_autocmd(oparg_T *oap, yankreg_T *reg)
|
||||
// Empty the dictionary, v:event is still valid
|
||||
restore_v_event(v_event, &save_v_event);
|
||||
}
|
||||
|
||||
static void
|
||||
put_do_autocmd(
|
||||
int regname,
|
||||
yankreg_T *reg, // May be NULL, if special register
|
||||
string_T *insert, // Not NULL if special register, except '.'
|
||||
bool post, // If Post or Pre
|
||||
int dir) // BACKWARD for 'P', FORWARD for 'p'
|
||||
{
|
||||
static bool recursive = false;
|
||||
dict_T *v_event;
|
||||
list_T *list;
|
||||
int n;
|
||||
char_u buf[NUMBUFLEN + 2];
|
||||
size_t buflen;
|
||||
save_v_event_T save_v_event;
|
||||
|
||||
if (recursive || regname == '_')
|
||||
return;
|
||||
|
||||
v_event = get_v_event(&save_v_event);
|
||||
|
||||
list = list_alloc();
|
||||
if (list == NULL)
|
||||
return;
|
||||
|
||||
if (regname == '.')
|
||||
{
|
||||
if (last_insert_ga.ga_data != NULL)
|
||||
// Get the last inserted text to place in "regcontents"
|
||||
list_append_string(list, last_insert_ga.ga_data,
|
||||
(int)last_insert_ga.ga_len);
|
||||
}
|
||||
else if (insert != NULL)
|
||||
{
|
||||
list_append_string(list, insert->string, (int)insert->length);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(reg != NULL);
|
||||
for (n = 0; n < reg->y_size; n++)
|
||||
list_append_string(list, reg->y_array[n].string,
|
||||
(int)reg->y_array[n].length);
|
||||
}
|
||||
|
||||
list->lv_lock = VAR_FIXED;
|
||||
(void)dict_add_list(v_event, "regcontents", list);
|
||||
|
||||
// register name or empty string for unnamed operation
|
||||
buf[0] = (char_u)regname;
|
||||
buf[1] = NUL;
|
||||
buflen = (buf[0] == NUL) ? 0 : 1;
|
||||
(void)dict_add_string_len(v_event, "regname", buf, (int)buflen);
|
||||
|
||||
// kind of operation (P, p)
|
||||
buf[0] = dir == BACKWARD ? 'P' : 'p';
|
||||
buf[1] = NUL;
|
||||
buflen = 1;
|
||||
(void)dict_add_string_len(v_event, "operator", buf, (int)buflen);
|
||||
|
||||
add_regtype_to_dict(regname, v_event, buf, sizeof(buf));
|
||||
|
||||
(void)dict_add_bool(v_event, "visual", VIsual_active);
|
||||
|
||||
// Lock the dictionary and its keys
|
||||
dict_set_items_ro(v_event);
|
||||
|
||||
recursive = true;
|
||||
textlock++;
|
||||
if (post)
|
||||
apply_autocmds(EVENT_TEXTPUTPOST, NULL, NULL, FALSE, curbuf);
|
||||
else
|
||||
apply_autocmds(EVENT_TEXTPUTPRE, NULL, NULL, FALSE, curbuf);
|
||||
textlock--;
|
||||
recursive = false;
|
||||
|
||||
// Empty the dictionary, v:event is still valid
|
||||
restore_v_event(v_event, &save_v_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1648,8 +1734,28 @@ do_put(
|
||||
{
|
||||
if (VIsual_active)
|
||||
stuffcharReadbuff(VIsual_mode);
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
if (has_textputpre() || has_textputpost())
|
||||
add_last_insert++;
|
||||
#endif
|
||||
|
||||
(void)stuff_inserted((dir == FORWARD ? (count == -1 ? 'o' : 'a') :
|
||||
(count == -1 ? 'O' : 'i')), count, FALSE);
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
// Since the text is not inserted into the buffer immediately, just call
|
||||
// TextPutPost after TextPutPre.
|
||||
if (has_textputpre())
|
||||
put_do_autocmd('.', NULL, NULL, false, dir);
|
||||
|
||||
if (has_textputpost())
|
||||
put_do_autocmd('.', NULL, NULL, true, dir);
|
||||
|
||||
if (--add_last_insert == 0)
|
||||
ga_clear(&last_insert_ga);
|
||||
#endif
|
||||
|
||||
// Putting the text is done later, so can't really move the cursor to
|
||||
// the next character. Use "l" to simulate it.
|
||||
if ((flags & PUT_CURSEND) && gchar_cursor() != NUL)
|
||||
@@ -1733,9 +1839,22 @@ do_put(
|
||||
y_size = 1; // use fake one-line yank register
|
||||
y_array = &insert_string;
|
||||
}
|
||||
#ifdef FEAT_EVAL
|
||||
if (has_textputpre())
|
||||
put_do_autocmd(regname, NULL, &insert_string, false, dir);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef FEAT_EVAL
|
||||
if (has_textputpre())
|
||||
{
|
||||
// Make sure to call this before we set the variables, as setreg()
|
||||
// may be called and invalidate them.
|
||||
get_yank_register(regname, FALSE);
|
||||
put_do_autocmd(regname, y_current, NULL, false, dir);
|
||||
}
|
||||
#endif
|
||||
get_yank_register(regname, FALSE);
|
||||
|
||||
y_type = y_current->y_type;
|
||||
@@ -2401,6 +2520,17 @@ end:
|
||||
curbuf->b_op_start = orig_start;
|
||||
curbuf->b_op_end = orig_end;
|
||||
}
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
if (has_textputpost())
|
||||
{
|
||||
if (insert_string.string == NULL)
|
||||
put_do_autocmd(regname, y_current, NULL, true, dir);
|
||||
else
|
||||
put_do_autocmd(regname, NULL, &insert_string, true, dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (allocated)
|
||||
vim_free(insert_string.string);
|
||||
if (regname == '=')
|
||||
|
||||
@@ -5967,4 +5967,129 @@ func Test_autocmd_add_secure()
|
||||
call assert_fails('sandbox call autocmd_delete([{"event": "BufRead"}])', 'E48:')
|
||||
endfunc
|
||||
|
||||
func Test_TextPutX()
|
||||
enew!
|
||||
|
||||
let g:pre_event = []
|
||||
let g:post_event = []
|
||||
au TextPutPre * let g:pre_event = copy(v:event)
|
||||
au TextPutPost * let g:post_event = copy(v:event)
|
||||
|
||||
call setreg('a', ['foo'], 'v')
|
||||
norm "ap
|
||||
call assert_equal(
|
||||
\ #{regcontents: ['foo'], regname: 'a', operator: 'p',
|
||||
\ visual: v:false, regtype: 'v'},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
|
||||
call setreg('', ['hello'], 'V')
|
||||
norm P
|
||||
call assert_equal(
|
||||
\ #{regcontents: ['hello'], regname: '', operator: 'P',
|
||||
\ visual: v:false, regtype: 'V'},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
|
||||
call setreg('', ['maybe', 'true'], 'V')
|
||||
norm Vp
|
||||
call assert_equal(
|
||||
\ #{regcontents: ['maybe', 'true'], regname: '', operator: 'P',
|
||||
\ regtype: 'V', visual: v:true},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
call assert_equal({}, v:event)
|
||||
|
||||
call feedkeys("iinserted text\<CR>below\<Esc>", 'x')
|
||||
norm ".p
|
||||
call assert_equal(
|
||||
\ #{regcontents: ["inserted text\nbelow"], regname: '.',
|
||||
\ operator: 'p', regtype: 'v', visual: v:false},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
|
||||
call feedkeys("\"=201\<CR>p", 'x')
|
||||
call assert_equal(
|
||||
\ #{regcontents: ["201"], regname: '=',
|
||||
\ operator: 'p', regtype: 'v', visual: v:false},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
|
||||
vsplit some.txt
|
||||
wincmd l
|
||||
norm "#p
|
||||
call assert_equal(
|
||||
\ #{regcontents: ["some.txt"], regname: '#',
|
||||
\ operator: 'p', regtype: 'v', visual: v:false},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
wincmd h
|
||||
bw!
|
||||
|
||||
if has('clipboard_working')
|
||||
let @+ = 'clipboard'
|
||||
|
||||
norm "+p
|
||||
call assert_equal(
|
||||
\ #{regcontents: ["clipboard"], regname: '+',
|
||||
\ operator: 'p', regtype: 'v', visual: v:false},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
endif
|
||||
|
||||
%delete " Clear buffer
|
||||
|
||||
au! TextPutPre
|
||||
au! TextPutPost
|
||||
let g:pre_event = []
|
||||
let g:post_event = []
|
||||
|
||||
au TextPutPre * call setreg(v:event['regname'],
|
||||
\ getreg('', 0, v:true) + ['!']) " Unnamed register should be same as regname
|
||||
|
||||
call setreg('', ['hello', 'world'])
|
||||
norm p
|
||||
call assert_equal(['', 'hello', 'world', '!'], getline(1, '$'))
|
||||
|
||||
au! TextPutPre
|
||||
|
||||
" Test that special registers cannot be modified
|
||||
%delete
|
||||
au TextPutPre * call setreg('=', '"modified"') | let g:pre_event = copy(v:event)
|
||||
|
||||
" Set up the expression register to evaluate to a known value.
|
||||
call feedkeys("\"=\"original\"\<CR>p", 'x')
|
||||
|
||||
" The original value is what got put, not the modified one.
|
||||
call assert_equal(['original'], getline(1, '$'))
|
||||
|
||||
" v:event still reports the original value.
|
||||
call assert_equal(['original'], g:pre_event['regcontents'])
|
||||
|
||||
au! TextPutPre
|
||||
let g:pre_event = []
|
||||
|
||||
" Test that recursive ". register calls have the same contents for post and
|
||||
" pre
|
||||
au TextPutPre * put . | let g:pre_event = copy(v:event)
|
||||
au TextPutPost * let g:post_event = copy(v:event)
|
||||
|
||||
call feedkeys("iinserted\<Esc>", 'x')
|
||||
norm! ".p
|
||||
|
||||
call assert_equal(
|
||||
\ #{regcontents: ["inserted"], regname: '.',
|
||||
\ operator: 'p', regtype: 'v', visual: v:false},
|
||||
\ g:pre_event)
|
||||
call assert_equal(g:pre_event, g:post_event)
|
||||
|
||||
au! TextPutPre
|
||||
au! TextPutPost
|
||||
|
||||
unlet g:post_event
|
||||
unlet g:pre_event
|
||||
bwipe!
|
||||
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
470,
|
||||
/**/
|
||||
469,
|
||||
/**/
|
||||
|
||||
@@ -1484,6 +1484,8 @@ enum auto_event
|
||||
EVENT_TEXTCHANGEDI, // text was modified in Insert mode
|
||||
EVENT_TEXTCHANGEDP, // TextChangedI with popup menu visible
|
||||
EVENT_TEXTCHANGEDT, // text was modified in Terminal mode
|
||||
EVENT_TEXTPUTPOST, // after some text was put
|
||||
EVENT_TEXTPUTPRE, // before some text was put
|
||||
EVENT_TEXTYANKPOST, // after some text was yanked
|
||||
EVENT_USER, // user defined autocommand
|
||||
EVENT_VIMENTER, // after starting Vim
|
||||
|
||||
Reference in New Issue
Block a user