mirror of
https://github.com/neovim/neovim.git
synced 2026-08-28 01:51:52 +00:00
Merge pull request #39741 from zeertzjq/vim-9.2.0470
vim-patch:9.2.{0470,0473}: TextPut{Pre,Post}
This commit is contained in:
@@ -1266,6 +1266,46 @@ 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. For |nvim_put()|
|
||||
this is set to '_'.
|
||||
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|.
|
||||
|
||||
*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|.
|
||||
|
||||
*TextYankPost*
|
||||
TextYankPost Just after a |yank| or |deleting| command, but not
|
||||
if the black hole register |quote_| is used nor
|
||||
|
||||
@@ -144,6 +144,7 @@ EVENTS
|
||||
|
||||
• |:delmarks| now triggers the |MarkSet| autocommand with line==col==0, same
|
||||
as |nvim_buf_del_mark()|
|
||||
• |TextPutPre| and |TextPutPost| are triggered before/after putting text.
|
||||
|
||||
HIGHLIGHTS
|
||||
|
||||
|
||||
2
runtime/lua/vim/_meta/api_keysets.gen.lua
generated
2
runtime/lua/vim/_meta/api_keysets.gen.lua
generated
@@ -207,6 +207,8 @@ error('Cannot require a meta file')
|
||||
--- |'TextChangedI'
|
||||
--- |'TextChangedP'
|
||||
--- |'TextChangedT'
|
||||
--- |'TextPutPost'
|
||||
--- |'TextPutPre'
|
||||
--- |'TextYankPost'
|
||||
--- |'UIEnter'
|
||||
--- |'UILeave'
|
||||
|
||||
@@ -1462,7 +1462,7 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
|
||||
TRY_WRAP(err, {
|
||||
bool VIsual_was_active = VIsual_active;
|
||||
msg_silent++; // Avoid "N more lines" message.
|
||||
do_put(0, reg, after ? FORWARD : BACKWARD, 1, follow ? PUT_CURSEND : 0);
|
||||
do_put('_', reg, after ? FORWARD : BACKWARD, 1, follow ? PUT_CURSEND : 0);
|
||||
msg_silent--;
|
||||
VIsual_active = VIsual_was_active;
|
||||
});
|
||||
|
||||
@@ -126,6 +126,8 @@ return {
|
||||
TextChangedI = true, -- text was modified in Insert mode(no popup)
|
||||
TextChangedP = true, -- text was modified in Insert mode(popup)
|
||||
TextChangedT = true, -- text was modified in Terminal mode
|
||||
TextPutPost = true, -- after some text was put
|
||||
TextPutPre = true, -- before some text was put
|
||||
TextYankPost = true, -- after a yank or delete was done (y, d, c)
|
||||
UIEnter = false, -- after UI attaches
|
||||
UILeave = false, -- after UI detaches
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "nvim/os/os_defs.h"
|
||||
#include "nvim/plines.h"
|
||||
#include "nvim/pos_defs.h"
|
||||
#include "nvim/register.h"
|
||||
#include "nvim/state.h"
|
||||
#include "nvim/state_defs.h"
|
||||
#include "nvim/strings.h"
|
||||
@@ -661,6 +662,10 @@ void stuffRedoReadbuff(const char *s)
|
||||
|
||||
void stuffReadbuffLen(const char *s, ptrdiff_t len)
|
||||
{
|
||||
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);
|
||||
}
|
||||
add_buff(&readbuf1, s, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -1169,27 +1169,37 @@ void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
|
||||
/// @param reg_width The width, only used if "reg_type" is kMTBlockWise.
|
||||
/// @param[out] buf Buffer to store formatted string. The allocated size should
|
||||
/// be at least NUMBUFLEN+2 to always fit the value.
|
||||
/// @param buf_len The allocated size of the buffer.
|
||||
void format_reg_type(MotionType reg_type, colnr_T reg_width, char *buf, size_t buf_len)
|
||||
/// @param bufsize The allocated size of the buffer.
|
||||
///
|
||||
/// @return The length of the register type string.
|
||||
size_t format_reg_type(MotionType reg_type, colnr_T reg_width, char *buf, size_t bufsize)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
assert(buf_len > 1);
|
||||
assert(bufsize > 1);
|
||||
switch (reg_type) {
|
||||
case kMTLineWise:
|
||||
buf[0] = 'V';
|
||||
buf[1] = NUL;
|
||||
break;
|
||||
return 1;
|
||||
case kMTCharWise:
|
||||
buf[0] = 'v';
|
||||
buf[1] = NUL;
|
||||
break;
|
||||
return 1;
|
||||
case kMTBlockWise:
|
||||
snprintf(buf, buf_len, CTRL_V_STR "%" PRIdCOLNR, reg_width + 1);
|
||||
break;
|
||||
return vim_snprintf_safelen(buf, bufsize, CTRL_V_STR "%" PRIdCOLNR, reg_width + 1);
|
||||
case kMTUnknown:
|
||||
buf[0] = NUL;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
static void add_regtype_to_dict(yankreg_T *reg, dict_T *dict, char *buf, size_t bufsize)
|
||||
{
|
||||
// "reg" is NULL when pasting a special register, which is charwise.
|
||||
size_t len = format_reg_type(reg != NULL ? reg->y_type : kMTCharWise,
|
||||
reg != NULL ? reg->y_width : 0, buf, bufsize);
|
||||
tv_dict_add_str_len(dict, S_LEN("regtype"), buf, (int)len);
|
||||
}
|
||||
|
||||
/// Execute autocommands for TextYankPost.
|
||||
@@ -1222,8 +1232,7 @@ void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
|
||||
|
||||
// Register type.
|
||||
char buf[NUMBUFLEN + 2];
|
||||
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
|
||||
tv_dict_add_str(dict, S_LEN("regtype"), buf);
|
||||
add_regtype_to_dict(reg, dict, buf, ARRAY_SIZE(buf));
|
||||
|
||||
// Name of requested register, or empty string for unnamed operation.
|
||||
buf[0] = (char)oap->regname;
|
||||
@@ -1252,6 +1261,78 @@ void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
|
||||
recursive = false;
|
||||
}
|
||||
|
||||
/// Trigger TextPutPre or TextPutPost autocommand.
|
||||
///
|
||||
/// @param reg May be NULL, if special register
|
||||
/// @param insert Not NULL if special register, except '.'
|
||||
/// @param post If Post or Pre
|
||||
/// @param dir BACKWARD for 'P', FORWARD for 'p'
|
||||
static void put_do_autocmd(int regname, yankreg_T *reg, const String *insert, bool post,
|
||||
Direction dir)
|
||||
{
|
||||
static bool recursive = false;
|
||||
|
||||
if (recursive || (regname == '_' && reg == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
save_v_event_T save_v_event;
|
||||
dict_T *v_event = get_v_event(&save_v_event);
|
||||
|
||||
list_T *list = tv_list_alloc(reg != NULL ? (ptrdiff_t)reg->y_size : 1);
|
||||
|
||||
if (regname == '.') {
|
||||
if (last_insert_ga.ga_data != NULL) {
|
||||
// Get the last inserted text to place in "regcontents"
|
||||
tv_list_append_string(list, last_insert_ga.ga_data, last_insert_ga.ga_len);
|
||||
}
|
||||
} else if (insert != NULL) {
|
||||
tv_list_append_string(list, insert->data, (ssize_t)insert->size);
|
||||
} else {
|
||||
assert(reg != NULL);
|
||||
for (size_t n = 0; n < reg->y_size; n++) {
|
||||
tv_list_append_string(list, reg->y_array[n].data, (ssize_t)reg->y_array[n].size);
|
||||
}
|
||||
}
|
||||
|
||||
tv_list_set_lock(list, VAR_FIXED);
|
||||
tv_dict_add_list(v_event, S_LEN("regcontents"), list);
|
||||
|
||||
char buf[NUMBUFLEN + 2];
|
||||
|
||||
// register name or empty string for unnamed operation
|
||||
buf[0] = (char)regname;
|
||||
buf[1] = NUL;
|
||||
size_t buflen = (buf[0] == NUL) ? 0 : 1;
|
||||
tv_dict_add_str_len(v_event, S_LEN("regname"), buf, (int)buflen);
|
||||
|
||||
// kind of operation (P, p)
|
||||
buf[0] = dir == BACKWARD ? 'P' : 'p';
|
||||
buf[1] = NUL;
|
||||
buflen = 1;
|
||||
tv_dict_add_str_len(v_event, S_LEN("operator"), buf, (int)buflen);
|
||||
|
||||
add_regtype_to_dict(reg, v_event, buf, sizeof(buf));
|
||||
|
||||
tv_dict_add_bool(v_event, S_LEN("visual"), VIsual_active);
|
||||
|
||||
// Lock the dictionary and its keys
|
||||
tv_dict_set_keys_readonly(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);
|
||||
}
|
||||
|
||||
/// Yanks the text between "oap->start" and "oap->end" into a yank register.
|
||||
/// If we are to append (uppercase register), we first yank into a new yank
|
||||
/// register and then concatenate the old and the new one.
|
||||
@@ -1320,9 +1401,23 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
||||
? 'c'
|
||||
: (flags & PUT_LINE ? 'i' : (dir == FORWARD ? 'a' : 'i'));
|
||||
|
||||
bool has_textput_events = has_event(EVENT_TEXTPUTPRE) || has_event(EVENT_TEXTPUTPOST);
|
||||
if (has_textput_events) {
|
||||
add_last_insert++;
|
||||
}
|
||||
|
||||
// To avoid 'autoindent' on linewise puts, create a new line with `:put _`.
|
||||
if (flags & PUT_LINE) {
|
||||
do_put('_', NULL, dir, 1, PUT_LINE);
|
||||
const int save_add_last_insert = add_last_insert;
|
||||
add_last_insert = 0;
|
||||
stuffcharReadbuff(K_COMMAND);
|
||||
if (dir == FORWARD) {
|
||||
stuffReadbuffLen(S_LEN("put _"));
|
||||
} else {
|
||||
stuffReadbuffLen(S_LEN("put! _"));
|
||||
}
|
||||
stuffcharReadbuff(CAR);
|
||||
add_last_insert = save_add_last_insert;
|
||||
}
|
||||
|
||||
// If given a count when putting linewise, we stuff the readbuf with the
|
||||
@@ -1337,14 +1432,27 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
||||
// back to the previous line in the case of 'noautoindent' and
|
||||
// 'backspace' includes "eol". So we insert a dummy space for Ctrl_U
|
||||
// to consume.
|
||||
stuffReadbuff("\n ");
|
||||
stuffcharReadbuff(Ctrl_U);
|
||||
static const char s[] = { '\n', ' ', Ctrl_U, NUL };
|
||||
stuffReadbuffLen(S_LEN(s));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
stuff_inserted(command_start_char, count, false);
|
||||
}
|
||||
|
||||
// Since the text is not inserted into the buffer immediately, just call
|
||||
// TextPutPost after TextPutPre.
|
||||
if (has_event(EVENT_TEXTPUTPRE)) {
|
||||
put_do_autocmd('.', NULL, NULL, false, dir);
|
||||
}
|
||||
if (has_event(EVENT_TEXTPUTPOST)) {
|
||||
put_do_autocmd('.', NULL, NULL, true, dir);
|
||||
}
|
||||
|
||||
if (has_textput_events && --add_last_insert == 0) {
|
||||
ga_clear(&last_insert_ga);
|
||||
}
|
||||
|
||||
// Putting the text is done later, so can't move the cursor to the next
|
||||
// character. Simulate it with motion commands after the insert.
|
||||
if (flags & PUT_CURSEND) {
|
||||
@@ -1454,7 +1562,20 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
|
||||
y_size = 1; // use fake one-line yank register
|
||||
y_array = &insert_string;
|
||||
}
|
||||
if (has_event(EVENT_TEXTPUTPRE)) {
|
||||
put_do_autocmd(regname, NULL, &insert_string, false, dir);
|
||||
}
|
||||
} else {
|
||||
if (has_event(EVENT_TEXTPUTPRE)) {
|
||||
yankreg_T *const save_reg = reg;
|
||||
if (reg == NULL) {
|
||||
// Make sure to call this before we set the variables, as setreg()
|
||||
// may be called and invalidate them.
|
||||
reg = get_yank_register(regname, YREG_PASTE);
|
||||
}
|
||||
put_do_autocmd(regname, reg, NULL, false, dir);
|
||||
reg = save_reg;
|
||||
}
|
||||
// in case of replacing visually selected text
|
||||
// the yankreg might already have been saved to avoid
|
||||
// just restoring the deleted text.
|
||||
@@ -2069,6 +2190,15 @@ end:
|
||||
curbuf->b_op_start = orig_start;
|
||||
curbuf->b_op_end = orig_end;
|
||||
}
|
||||
|
||||
if (has_event(EVENT_TEXTPUTPOST)) {
|
||||
if (insert_string.data == NULL) {
|
||||
put_do_autocmd(regname, reg, NULL, true, dir);
|
||||
} else {
|
||||
put_do_autocmd(regname, NULL, &insert_string, true, dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (allocated) {
|
||||
xfree(insert_string.data);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "nvim/ascii_defs.h"
|
||||
#include "nvim/ex_cmds_defs.h"
|
||||
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
|
||||
#include "nvim/macros_defs.h"
|
||||
#include "nvim/register_defs.h"
|
||||
|
||||
/// 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 INIT( = { 0, 0, 1, 64, NULL });
|
||||
EXTERN int add_last_insert INIT( = 0);
|
||||
|
||||
#include "register.h.generated.h"
|
||||
#include "register.h.inline.generated.h"
|
||||
|
||||
|
||||
@@ -1555,29 +1555,53 @@ describe('API', function()
|
||||
)
|
||||
end)
|
||||
it('inserts text', function()
|
||||
exec([[
|
||||
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)
|
||||
]])
|
||||
-- linewise
|
||||
api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'l', true, true)
|
||||
local lines = { 'line 1', 'line 2', 'line 3' }
|
||||
local expected_event = {
|
||||
regcontents = lines,
|
||||
regname = '_',
|
||||
operator = 'p',
|
||||
regtype = 'V',
|
||||
visual = false,
|
||||
}
|
||||
api.nvim_put(lines, 'l', true, true)
|
||||
expect([[
|
||||
|
||||
line 1
|
||||
line 2
|
||||
line 3]])
|
||||
eq({ 0, 4, 1, 0 }, fn.getpos('.'))
|
||||
eq(expected_event, api.nvim_get_var('pre_event'))
|
||||
eq(expected_event, api.nvim_get_var('post_event'))
|
||||
command('%delete _')
|
||||
-- charwise
|
||||
expected_event.regtype = 'v'
|
||||
api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'c', true, false)
|
||||
expect([[
|
||||
line 1
|
||||
line 2
|
||||
line 3]])
|
||||
eq({ 0, 1, 1, 0 }, fn.getpos('.')) -- follow=false
|
||||
eq(expected_event, api.nvim_get_var('pre_event'))
|
||||
eq(expected_event, api.nvim_get_var('post_event'))
|
||||
-- blockwise
|
||||
api.nvim_put({ 'AA', 'BB' }, 'b', true, true)
|
||||
lines = { 'AA', 'BB' }
|
||||
expected_event.regcontents = lines
|
||||
expected_event.regtype = '\0222'
|
||||
api.nvim_put(lines, 'b', true, true)
|
||||
expect([[
|
||||
lAAine 1
|
||||
lBBine 2
|
||||
line 3]])
|
||||
eq({ 0, 2, 4, 0 }, fn.getpos('.'))
|
||||
eq(expected_event, api.nvim_get_var('pre_event'))
|
||||
eq(expected_event, api.nvim_get_var('post_event'))
|
||||
command('%delete _')
|
||||
-- Empty lines list.
|
||||
api.nvim_put({}, 'c', true, true)
|
||||
@@ -1590,19 +1614,27 @@ describe('API', function()
|
||||
]])
|
||||
api.nvim_put({ 'AB' }, 'c', true, true)
|
||||
-- after=false, follow=true
|
||||
api.nvim_put({ 'line 1', 'line 2' }, 'c', false, true)
|
||||
lines = { 'line 1', 'line 2' }
|
||||
expected_event.regcontents = lines
|
||||
expected_event.regtype = 'v'
|
||||
expected_event.operator = 'P'
|
||||
api.nvim_put(lines, 'c', false, true)
|
||||
expect([[
|
||||
Aline 1
|
||||
line 2B]])
|
||||
eq({ 0, 2, 7, 0 }, fn.getpos('.'))
|
||||
eq(expected_event, api.nvim_get_var('pre_event'))
|
||||
eq(expected_event, api.nvim_get_var('post_event'))
|
||||
command('%delete _')
|
||||
api.nvim_put({ 'AB' }, 'c', true, true)
|
||||
-- after=false, follow=false
|
||||
api.nvim_put({ 'line 1', 'line 2' }, 'c', false, false)
|
||||
api.nvim_put(lines, 'c', false, false)
|
||||
expect([[
|
||||
Aline 1
|
||||
line 2B]])
|
||||
eq({ 0, 1, 2, 0 }, fn.getpos('.'))
|
||||
eq(expected_event, api.nvim_get_var('pre_event'))
|
||||
eq(expected_event, api.nvim_get_var('post_event'))
|
||||
eq('', api.nvim_eval('v:errmsg'))
|
||||
end)
|
||||
|
||||
|
||||
@@ -5330,4 +5330,134 @@ func Test_SwapExists_b_nwindows()
|
||||
%bw!
|
||||
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 = []
|
||||
|
||||
for round in range(2)
|
||||
" 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
|
||||
|
||||
" Pasting ". register without TextPutPre/TextPutPost autocommands should
|
||||
" not interfere with these autocommands in the next round.
|
||||
norm! ".p
|
||||
endfor
|
||||
|
||||
unlet g:post_event
|
||||
unlet g:pre_event
|
||||
bwipe!
|
||||
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
Reference in New Issue
Block a user