From fc79a5a01cff7d85cc188714f512d3bc8f88fc86 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 3 Jul 2024 00:22:09 +1000 Subject: [PATCH 1/4] add bracketed paste support --- CHANGELOG.md | 6 ++++++ lua/toggleterm.lua | 11 ++++++----- lua/toggleterm/terminal.lua | 8 ++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51024ae2..27d6da3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [2.12.0](https://github.com/akinsho/toggleterm.nvim/compare/... + +### Features + +* add bracketed paste support to `send_lines_to_terminal` and Terminal:send. + ## [2.11.0](https://github.com/akinsho/toggleterm.nvim/compare/v2.10.0...v2.11.0) (2024-04-22) diff --git a/lua/toggleterm.lua b/lua/toggleterm.lua index 09310dce..4cb112de 100644 --- a/lua/toggleterm.lua +++ b/lua/toggleterm.lua @@ -175,7 +175,7 @@ end --- @param name string? --- @param go_back boolean? whether or not to return to original window --- @param open boolean? whether or not to open terminal window -function M.exec(cmd, num, size, dir, direction, name, go_back, open) +function M.exec(cmd, num, size, dir, direction, name, go_back, open, use_bracketed_paste) vim.validate({ cmd = { cmd, "string" }, num = { num, "number", true }, @@ -197,13 +197,14 @@ function M.exec(cmd, num, size, dir, direction, name, go_back, open) term:close() go_back = false end - term:send(cmd, go_back) + term:send(cmd, go_back, use_bracketed_paste) end --- @param selection_type string --- @param trim_spaces boolean --- @param cmd_data table -function M.send_lines_to_terminal(selection_type, trim_spaces, cmd_data) +--- @param use_bracketed_paste boolean? +function M.send_lines_to_terminal(selection_type, trim_spaces, cmd_data, use_bracketed_paste) local id = tonumber(cmd_data.args) or 1 trim_spaces = trim_spaces == nil or trim_spaces @@ -244,11 +245,11 @@ function M.send_lines_to_terminal(selection_type, trim_spaces, cmd_data) if not lines or not next(lines) then return end if not trim_spaces then - M.exec(table.concat(lines, "\n"), id) + M.exec(table.concat(lines, "\n"), id, nil, nil, nil, nil, nil, nil, use_bracketed_paste) else for _, line in ipairs(lines) do local l = trim_spaces and line:gsub("^%s+", ""):gsub("%s+$", "") or line - M.exec(l, id) + M.exec(l, id, nil, nil, nil, nil, nil, nil, use_bracketed_paste) end end diff --git a/lua/toggleterm/terminal.lua b/lua/toggleterm/terminal.lua index 904eb340..bc48578a 100644 --- a/lua/toggleterm/terminal.lua +++ b/lua/toggleterm/terminal.lua @@ -322,10 +322,14 @@ end ---Send a command to a running terminal ---@param cmd string|string[] ---@param go_back boolean? whether or not to return to original window -function Terminal:send(cmd, go_back) +---@param use_bracketed_paste boolean? Whether or not to add bracketed paste characters to send sequence +function Terminal:send(cmd, go_back, use_bracketed_paste) + local start_seq = use_bracketed_paste and "\x1b[200~" or "" + local end_seq = use_bracketed_paste and "\x1b[201~" or "" + cmd = type(cmd) == "table" and with_cr(self.newline_chr, unpack(cmd)) or with_cr(self.newline_chr, cmd --[[@as string]]) - fn.chansend(self.job_id, cmd) + fn.chansend(self.job_id, start_seq .. cmd .. end_seq) self:scroll_bottom() if go_back and self:is_focused() then ui.goto_previous() From 22fbdb448750ae30d8a1d7858888041d1360467d Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 3 Jul 2024 00:56:07 +1000 Subject: [PATCH 2/4] fix failing tests --- tests/terminal_spec.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/terminal_spec.lua b/tests/terminal_spec.lua index 488c807d..8683c824 100644 --- a/tests/terminal_spec.lua +++ b/tests/terminal_spec.lua @@ -307,7 +307,7 @@ describe("ToggleTerm tests:", function() spy.on(test1, "send") toggleterm.exec('echo "hello world"', 1) assert.spy(test1.send).was_called() - assert.spy(test1.send).was_called_with(_, 'echo "hello world"', true) + assert.spy(test1.send).was_called_with(_, 'echo "hello world"', true, match.is_nil()) assert.is_true(vim.tbl_contains(api.nvim_list_wins(), test1.window)) end) @@ -316,7 +316,7 @@ describe("ToggleTerm tests:", function() test1:close() spy.on(test1, "send") toggleterm.exec_command("cmd='echo \"hello world\"' open=0", 1) - assert.spy(test1.send).was_called_with(test1, 'echo "hello world"', false) + assert.spy(test1.send).was_called_with(test1, 'echo "hello world"', false, match.is_nil()) assert.is_false(vim.tbl_contains(api.nvim_list_wins(), test1.window)) end) @@ -327,7 +327,7 @@ describe("ToggleTerm tests:", function() spy.on(test1, "send") toggleterm.exec('echo "hello world"', 1) assert.spy(test1.send).was_called() - assert.spy(test1.send).was_called_with(_, 'echo "hello world"', true) + assert.spy(test1.send).was_called_with(_, 'echo "hello world"', true, match.is_nil()) assert.is_true(vim.tbl_contains(api.nvim_list_wins(), test1.window)) end) @@ -338,7 +338,7 @@ describe("ToggleTerm tests:", function() vim.cmd("wincmd w") spy.on(test1, "send") toggleterm.exec_command("cmd='echo %'", 1) - assert.spy(test1.send).was_called_with(test1, fmt("echo %s", file), true) + assert.spy(test1.send).was_called_with(test1, fmt("echo %s", file), true, match.is_nil()) end) it("should handle nested quotes in cmd args", function() @@ -348,7 +348,7 @@ describe("ToggleTerm tests:", function() vim.cmd("wincmd w") spy.on(test1, "send") toggleterm.exec_command("cmd='g++ -std=c++17 % -o run'", 1) - assert.spy(test1.send).was_called_with(test1, fmt("g++ -std=c++17 %s -o run", file), true) + assert.spy(test1.send).was_called_with(test1, fmt("g++ -std=c++17 %s -o run", file), true, match.is_nil()) end) end) From b2dd7dc9887ca4196de356315f255eb803b3c482 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 3 Jul 2024 01:01:29 +1000 Subject: [PATCH 3/4] add newline character to send --- lua/toggleterm/terminal.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/toggleterm/terminal.lua b/lua/toggleterm/terminal.lua index bc48578a..407ca540 100644 --- a/lua/toggleterm/terminal.lua +++ b/lua/toggleterm/terminal.lua @@ -329,7 +329,7 @@ function Terminal:send(cmd, go_back, use_bracketed_paste) cmd = type(cmd) == "table" and with_cr(self.newline_chr, unpack(cmd)) or with_cr(self.newline_chr, cmd --[[@as string]]) - fn.chansend(self.job_id, start_seq .. cmd .. end_seq) + fn.chansend(self.job_id, start_seq .. cmd .. end_seq .. self.newline_chr) self:scroll_bottom() if go_back and self:is_focused() then ui.goto_previous() From a4a76b6a62838ca534887258975d26d0fd838ed0 Mon Sep 17 00:00:00 2001 From: ben Date: Sun, 7 Jul 2024 12:36:59 +1000 Subject: [PATCH 4/4] add tests for bracketed paste, don't modify current send behaviour --- lua/toggleterm.lua | 2 ++ lua/toggleterm/terminal.lua | 6 +++--- tests/terminal_spec.lua | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lua/toggleterm.lua b/lua/toggleterm.lua index 4cb112de..4acd7c06 100644 --- a/lua/toggleterm.lua +++ b/lua/toggleterm.lua @@ -175,6 +175,7 @@ end --- @param name string? --- @param go_back boolean? whether or not to return to original window --- @param open boolean? whether or not to open terminal window +--- @param use_bracketed_paste boolean? whether or not to use bracketed paste mode for send function M.exec(cmd, num, size, dir, direction, name, go_back, open, use_bracketed_paste) vim.validate({ cmd = { cmd, "string" }, @@ -185,6 +186,7 @@ function M.exec(cmd, num, size, dir, direction, name, go_back, open, use_bracket name = { name, "string", true }, go_back = { go_back, "boolean", true }, open = { open, "boolean", true }, + use_bracketed_paste = { use_bracketed_paste, "boolean", true }, }) num = (num and num >= 1) and num or terms.get_toggled_id() open = open == nil or open diff --git a/lua/toggleterm/terminal.lua b/lua/toggleterm/terminal.lua index 407ca540..354e046f 100644 --- a/lua/toggleterm/terminal.lua +++ b/lua/toggleterm/terminal.lua @@ -325,11 +325,11 @@ end ---@param use_bracketed_paste boolean? Whether or not to add bracketed paste characters to send sequence function Terminal:send(cmd, go_back, use_bracketed_paste) local start_seq = use_bracketed_paste and "\x1b[200~" or "" - local end_seq = use_bracketed_paste and "\x1b[201~" or "" - + local end_seq = use_bracketed_paste and "\x1b[201~" .. self.newline_chr or "" + cmd = type(cmd) == "table" and with_cr(self.newline_chr, unpack(cmd)) or with_cr(self.newline_chr, cmd --[[@as string]]) - fn.chansend(self.job_id, start_seq .. cmd .. end_seq .. self.newline_chr) + fn.chansend(self.job_id, start_seq .. cmd .. end_seq) self:scroll_bottom() if go_back and self:is_focused() then ui.goto_previous() diff --git a/tests/terminal_spec.lua b/tests/terminal_spec.lua index 8683c824..aa3e4d53 100644 --- a/tests/terminal_spec.lua +++ b/tests/terminal_spec.lua @@ -305,9 +305,25 @@ describe("ToggleTerm tests:", function() local test1 = Terminal:new():toggle() local _ = match._ spy.on(test1, "send") + spy.on(vim.fn, "chansend") toggleterm.exec('echo "hello world"', 1) assert.spy(test1.send).was_called() assert.spy(test1.send).was_called_with(_, 'echo "hello world"', true, match.is_nil()) + assert.spy(vim.fn.chansend).was_called_with(test1.job_id, 'echo "hello world"\n') + assert.is_true(vim.tbl_contains(api.nvim_list_wins(), test1.window)) + end) + + it("should send commands to a terminal with bracketed paste characters when specified", function() + local start_seq = "\x1b[200~" + local end_seq = "\x1b[201~" + local test1 = Terminal:new():toggle() + local _ = match._ + spy.on(test1, "send") + spy.on(vim.fn, "chansend") + toggleterm.exec("def hello():\n print('foo')", 1, nil, nil, nil, nil, nil, nil, true) + assert.spy(test1.send).was_called() + assert.spy(test1.send).was_called_with(_, "def hello():\n print('foo')", true, true) + assert.spy(vim.fn.chansend).was_called_with(test1.job_id, start_seq .. "def hello():\n print('foo')\n" .. end_seq .. "\n") assert.is_true(vim.tbl_contains(api.nvim_list_wins(), test1.window)) end)