mirror of
https://github.com/neovim/neovim.git
synced 2026-05-06 08:26:45 -04:00
fix(terminal): forward streamed bracketed paste properly (#39152)
(cherry picked from commit 4eaf782bb6)
This commit is contained in:
committed by
github-actions[bot]
parent
501a4425e2
commit
d3ef77639a
@@ -1372,6 +1372,9 @@ Boolean nvim_paste(uint64_t channel_id, String data, Boolean crlf, Integer phase
|
||||
});
|
||||
if (phase == -1 || phase == 1) { // Start of paste-stream.
|
||||
cancelled = false;
|
||||
if (curbuf->terminal) {
|
||||
terminal_set_streamed_paste(curbuf->terminal, true);
|
||||
}
|
||||
} else if (cancelled) {
|
||||
// Skip remaining chunks. Report error only once per "stream".
|
||||
goto theend;
|
||||
@@ -1385,6 +1388,9 @@ Boolean nvim_paste(uint64_t channel_id, String data, Boolean crlf, Integer phase
|
||||
if (ERROR_SET(err) || (rv.type == kObjectTypeBoolean && !rv.data.boolean)) {
|
||||
cancelled = true;
|
||||
}
|
||||
if ((phase == -1 || phase == 3 || cancelled) && curbuf->terminal) {
|
||||
terminal_set_streamed_paste(curbuf->terminal, false);
|
||||
}
|
||||
if (!cancelled && (phase == -1 || phase == 1)) {
|
||||
paste_store(channel_id, kFalse, NULL_STRING, crlf);
|
||||
}
|
||||
|
||||
+20
-2
@@ -197,6 +197,7 @@ struct terminal {
|
||||
MultiQueue *events; ///< Events waiting for refresh.
|
||||
} pending;
|
||||
|
||||
bool streamed_paste; ///< Streamed pasting
|
||||
bool theme_updates; ///< Send a theme update notification when 'bg' changes
|
||||
bool synchronized_output; ///< Mode 2026: suppress redraws until end of synchronized update
|
||||
bool sync_flush_pending; ///< Set when mode 2026 ends; triggers immediate buffer refresh
|
||||
@@ -1282,12 +1283,27 @@ static bool is_filter_char(int c)
|
||||
return !!(tpf_flags & flag);
|
||||
}
|
||||
|
||||
void terminal_set_streamed_paste(Terminal *term, bool streamed)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (term->streamed_paste != streamed) {
|
||||
if (streamed) {
|
||||
vterm_keyboard_start_paste(curbuf->terminal->vt);
|
||||
} else {
|
||||
vterm_keyboard_end_paste(curbuf->terminal->vt);
|
||||
}
|
||||
}
|
||||
term->streamed_paste = streamed;
|
||||
}
|
||||
|
||||
void terminal_paste(int count, String *y_array, size_t y_size)
|
||||
{
|
||||
if (y_size == 0) {
|
||||
return;
|
||||
}
|
||||
vterm_keyboard_start_paste(curbuf->terminal->vt);
|
||||
if (!curbuf->terminal->streamed_paste) {
|
||||
vterm_keyboard_start_paste(curbuf->terminal->vt);
|
||||
}
|
||||
size_t buff_len = y_array[0].size;
|
||||
char *buff = xmalloc(buff_len);
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -1321,7 +1337,9 @@ void terminal_paste(int count, String *y_array, size_t y_size)
|
||||
}
|
||||
}
|
||||
xfree(buff);
|
||||
vterm_keyboard_end_paste(curbuf->terminal->vt);
|
||||
if (!curbuf->terminal->streamed_paste) {
|
||||
vterm_keyboard_end_paste(curbuf->terminal->vt);
|
||||
}
|
||||
}
|
||||
|
||||
static void terminal_send_key(Terminal *term, int c)
|
||||
|
||||
@@ -1228,6 +1228,67 @@ describe('API', function()
|
||||
end)
|
||||
run_streamed_paste_tests()
|
||||
end)
|
||||
describe('stream: terminal buffer', function()
|
||||
local eol = is_os('win') and '\r\n' or '\n'
|
||||
before_each(function()
|
||||
exec_lua(function()
|
||||
_G.input = {}
|
||||
_G.chan = vim.api.nvim_open_term(0, {
|
||||
on_input = function(_, _, _, data)
|
||||
if #data > 0 then
|
||||
table.insert(_G.input, data)
|
||||
end
|
||||
end,
|
||||
force_crlf = false,
|
||||
})
|
||||
end)
|
||||
end)
|
||||
local function run_terminal_streamed_paste_tests(check_dot_repeat)
|
||||
it('without bracketed paste mode in terminal', function()
|
||||
api.nvim_paste('AA\nBB\n', false, 1)
|
||||
eq({ 'AA', eol, 'BB', eol }, exec_lua('return _G.input'))
|
||||
api.nvim_paste('CC', false, 2)
|
||||
eq({ 'AA', eol, 'BB', eol, 'CC' }, exec_lua('return _G.input'))
|
||||
api.nvim_paste('\nDD', false, 3)
|
||||
eq({ 'AA', eol, 'BB', eol, 'CC', eol, 'DD' }, exec_lua('return _G.input'))
|
||||
if check_dot_repeat then
|
||||
exec_lua('_G.input = {}')
|
||||
feed('.')
|
||||
eq({ 'AA', eol, 'BB', eol, 'CC', eol, 'DD' }, exec_lua('return _G.input'))
|
||||
end
|
||||
end)
|
||||
it('with bracketed paste mode in terminal', function()
|
||||
exec_lua([[vim.api.nvim_chan_send(_G.chan, '\027[?2004h')]])
|
||||
api.nvim_paste('AA\nBB\n', false, 1)
|
||||
eq({ '\027[200~', 'AA', eol, 'BB', eol }, exec_lua('return _G.input'))
|
||||
api.nvim_paste('CC', false, 2)
|
||||
eq({ '\027[200~', 'AA', eol, 'BB', eol, 'CC' }, exec_lua('return _G.input'))
|
||||
api.nvim_paste('\nDD', false, 3)
|
||||
eq(
|
||||
{ '\027[200~', 'AA', eol, 'BB', eol, 'CC', eol, 'DD', '\027[201~' },
|
||||
exec_lua('return _G.input')
|
||||
)
|
||||
if check_dot_repeat then
|
||||
exec_lua('_G.input = {}')
|
||||
feed('.')
|
||||
eq(
|
||||
{ '\027[200~', 'AA', eol, 'BB', eol, 'CC', eol, 'DD', '\027[201~' },
|
||||
exec_lua('return _G.input')
|
||||
)
|
||||
end
|
||||
end)
|
||||
end
|
||||
describe('in Normal mode', function()
|
||||
run_terminal_streamed_paste_tests(true)
|
||||
end)
|
||||
describe('in Terminal mode', function()
|
||||
before_each(function()
|
||||
feed('i')
|
||||
eq({ mode = 't', blocking = false }, api.nvim_get_mode())
|
||||
end)
|
||||
run_terminal_streamed_paste_tests(false)
|
||||
end)
|
||||
end)
|
||||
it('non-streaming', function()
|
||||
-- With final "\n".
|
||||
api.nvim_paste('line 1\nline 2\nline 3\n', true, -1)
|
||||
@@ -1947,7 +2008,6 @@ describe('API', function()
|
||||
it('getting current buffer option does not adjust cursor #19381', function()
|
||||
command('new')
|
||||
local buf = api.nvim_get_current_buf()
|
||||
print(vim.inspect(api.nvim_get_current_buf()))
|
||||
local win = api.nvim_get_current_win()
|
||||
insert('some text')
|
||||
feed('0v$')
|
||||
|
||||
Reference in New Issue
Block a user