mirror of
https://github.com/folke/snacks.nvim
synced 2025-12-23 08:47:57 +00:00
fix(terminal): properly deal with args in vim.o.shell. Fixes #69
This commit is contained in:
parent
f704f7479f
commit
2ccb70fd3a
2 changed files with 59 additions and 1 deletions
|
|
@ -92,7 +92,7 @@ function M.open(cmd, opts)
|
|||
cwd = opts.cwd,
|
||||
env = opts.env,
|
||||
}
|
||||
vim.fn.termopen(cmd or { vim.o.shell }, vim.tbl_isempty(term_opts) and vim.empty_dict() or term_opts)
|
||||
vim.fn.termopen(cmd or M.parse(vim.o.shell), vim.tbl_isempty(term_opts) and vim.empty_dict() or term_opts)
|
||||
end)
|
||||
|
||||
if opts.interactive ~= false then
|
||||
|
|
@ -133,4 +133,37 @@ function M.toggle(cmd, opts)
|
|||
return terminals[id]
|
||||
end
|
||||
|
||||
--- Parses a shell command into a table of arguments.
|
||||
--- - spaces inside quotes (only double quotes are supported) are preserved
|
||||
--- - backslash
|
||||
---@param cmd string
|
||||
function M.parse(cmd)
|
||||
local args = {}
|
||||
local in_quotes, escape_next, current = false, false, ""
|
||||
local function add()
|
||||
if #current > 0 then
|
||||
table.insert(args, current)
|
||||
current = ""
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #cmd do
|
||||
local char = cmd:sub(i, i)
|
||||
if escape_next then
|
||||
current = current .. ((char == '"' or char == "\\") and "" or "\\") .. char
|
||||
escape_next = false
|
||||
elseif char == "\\" and in_quotes then
|
||||
escape_next = true
|
||||
elseif char == '"' then
|
||||
in_quotes = not in_quotes
|
||||
elseif char:find("[ \t]") and not in_quotes then
|
||||
add()
|
||||
else
|
||||
current = current .. char
|
||||
end
|
||||
end
|
||||
add()
|
||||
return args
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
25
tests/terminal_spec.lua
Normal file
25
tests/terminal_spec.lua
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---@module "luassert"
|
||||
|
||||
local terminal = require("snacks.terminal")
|
||||
|
||||
local tests = {
|
||||
{ "bash", { "bash" } },
|
||||
{ '"bash"', { "bash" } },
|
||||
{
|
||||
'"C:\\Program Files\\Git\\bin\\bash.exe" -c "echo hello"',
|
||||
{ "C:\\Program Files\\Git\\bin\\bash.exe", "-c", "echo hello" },
|
||||
},
|
||||
{ "pwsh -NoLogo", { "pwsh", "-NoLogo" } },
|
||||
{ 'echo "foo\tbar"', { "echo", "foo\tbar" } },
|
||||
{ "echo\tfoo", { "echo", "foo" } },
|
||||
{ 'this "is \\"a test"', { "this", 'is "a test' } },
|
||||
}
|
||||
|
||||
describe("terminal.parse", function()
|
||||
for _, test in ipairs(tests) do
|
||||
it("should parse " .. test[1], function()
|
||||
local result = terminal.parse(test[1])
|
||||
assert.are.same(test[2], result)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
Loading…
Add table
Add a link
Reference in a new issue