mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
fix(paste): only record a paste when it's from RPC (#30491)
Problem: When using nvim_paste in a mapping during a macro recording, both the mapping and the paste are recorded, causing the paste to be performed twice when replaying the macro. Solution: Only record a paste when it is from RPC. Unfortunately this means there is no way for a script to make a recorded paste. A way to enable that can be discussed later if there is need.
This commit is contained in:
parent
3f6bc34e66
commit
052875b9dc
@ -1248,7 +1248,8 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
|
||||
/// @return
|
||||
/// - true: Client may continue pasting.
|
||||
/// - false: Client should cancel the paste.
|
||||
Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error *err)
|
||||
Boolean nvim_paste(uint64_t channel_id, String data, Boolean crlf, Integer phase, Arena *arena,
|
||||
Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
|
||||
{
|
||||
@ -1273,13 +1274,13 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error
|
||||
cancelled = true;
|
||||
}
|
||||
if (!cancelled && (phase == -1 || phase == 1)) {
|
||||
paste_store(kFalse, NULL_STRING, crlf);
|
||||
paste_store(channel_id, kFalse, NULL_STRING, crlf);
|
||||
}
|
||||
if (!cancelled) {
|
||||
paste_store(kNone, data, crlf);
|
||||
paste_store(channel_id, kNone, data, crlf);
|
||||
}
|
||||
if (phase == 3 || phase == (cancelled ? 2 : -1)) {
|
||||
paste_store(kTrue, NULL_STRING, crlf);
|
||||
paste_store(channel_id, kTrue, NULL_STRING, crlf);
|
||||
}
|
||||
theend:
|
||||
;
|
||||
|
@ -3190,8 +3190,6 @@ bool map_execute_lua(bool may_repeat)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool paste_repeat_active = false; ///< true when paste_repeat() is pasting
|
||||
|
||||
/// Wraps pasted text stream with K_PASTE_START and K_PASTE_END, and
|
||||
/// appends to redo buffer and/or record buffer if needed.
|
||||
/// Escapes all K_SPECIAL and NUL bytes in the content.
|
||||
@ -3200,14 +3198,14 @@ static bool paste_repeat_active = false; ///< true when paste_repeat() is pasti
|
||||
/// kTrue for the end of a paste
|
||||
/// kNone for the content of a paste
|
||||
/// @param str the content of the paste (only used when state is kNone)
|
||||
void paste_store(const TriState state, const String str, const bool crlf)
|
||||
void paste_store(const uint64_t channel_id, const TriState state, const String str, const bool crlf)
|
||||
{
|
||||
if (State & MODE_CMDLINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool need_redo = !block_redo;
|
||||
const bool need_record = reg_recording != 0 && !paste_repeat_active;
|
||||
const bool need_record = reg_recording != 0 && !is_internal_call(channel_id);
|
||||
|
||||
if (!need_redo && !need_record) {
|
||||
return;
|
||||
@ -3302,12 +3300,10 @@ void paste_repeat(int count)
|
||||
String str = cbuf_as_string(ga.ga_data, (size_t)ga.ga_len);
|
||||
Arena arena = ARENA_EMPTY;
|
||||
Error err = ERROR_INIT;
|
||||
paste_repeat_active = true;
|
||||
for (int i = 0; !aborted && i < count; i++) {
|
||||
nvim_paste(str, false, -1, &arena, &err);
|
||||
nvim_paste(LUA_INTERNAL_CALL, str, false, -1, &arena, &err);
|
||||
aborted = ERROR_SET(&err);
|
||||
}
|
||||
paste_repeat_active = false;
|
||||
api_clear_error(&err);
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
ga_clear(&ga);
|
||||
|
@ -1358,6 +1358,13 @@ describe('API', function()
|
||||
test_paste_repeat_visual_select(true)
|
||||
end)
|
||||
end)
|
||||
it('in a mapping recorded in a macro', function()
|
||||
command([[nnoremap <F2> <Cmd>call nvim_paste('foo', v:false, -1)<CR>]])
|
||||
feed('qr<F2>$q')
|
||||
expect('foo')
|
||||
feed('@r') -- repeating a macro containing the mapping should only paste once
|
||||
expect('foofoo')
|
||||
end)
|
||||
local function test_paste_cancel_error(is_error)
|
||||
before_each(function()
|
||||
exec_lua(([[
|
||||
|
Loading…
Reference in New Issue
Block a user