-
Notifications
You must be signed in to change notification settings - Fork 249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: handle more edge cases for Windows path escaping #1458
Conversation
For anyone who wants to verify/test the logic, the following script was ran in Neovim with local dpunc = {
"()",
"[]",
-- "{}",
"^",
"&",
";",
"`",
-- these are left out because this causes exponentially longer runtime.
-- they should have similar behavior to the above
-- "!", "#", "$", "%", "+", ",", "-", "=", "@", "_", "~"
}
local fpunc = [[!#$%&'()+,-;=@[]^_`{}~ ]]
-- testing implementation for this function
local function escape_path_for_cmd(path)
local escaped_path = vim.fn.fnameescape(path)
if true then -- assume is windows
local need_extra_esc = path:find("[%[%]`%$~]")
local esc = need_extra_esc and "\\\\" or "\\"
escaped_path = escaped_path:gsub("\\[%(%)%^&;]", esc .. "%1")
if need_extra_esc then
escaped_path = escaped_path:gsub("\\\\['` ]", "\\%1")
end
end
return escaped_path
end
-- makes a value like `[foo]` from part='foo' and p='[]'
local function make_part(part, p)
local open = p:sub(1, 1)
local close = p:sub(2, 2)
if close == "" then
close = open
end
return (open .. part .. close)
end
-- create nested directories with leading/trailing punctuation
local dirs = {}
for _, p1 in ipairs(dpunc) do
for _, p2 in ipairs(dpunc) do
local part1 = make_part("foo", p1)
local part2 = make_part("bar", p2)
local path = string.format(".\\tests\\%s\\%s", part1, part2)
vim.fn.mkdir(path, "p")
table.insert(dirs, path)
end
end
local files = { "baz.txt" }
for c in string.gmatch(fpunc, ".") do
table.insert(files, c .. "baz.txt")
end
-- try to write files with weird path
for _, d in ipairs(dirs) do
for _, f in ipairs(files) do
local p = escape_path_for_cmd(d .. "\\" .. f)
local ok, err = pcall(vim.cmd, "silent w " .. p)
if not ok then
print("fail:", p, "->", err)
end
end
end |
@pysan3 wanted to ping you on this one. I'm sure things are a bit hectic with the changeover in responsibilities so no rush, just a bump to keep on the radar :) |
Thanks mate, I totally forgot this one my bad. Merging! Thanks for your amazing work. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! And thanks for the comment to link to the PRs.
Happy to help, have a good weekend! |
Don't know why but still not working for me. |
@SuperSheykh It's not released as a version yet. Are you sure you are on the latest master branch? |
My bad it actually works fine. Thanks so much guys! |
This PR fixes #1448, among other edge cases that weren't previously handled.
Relevant notes were captured in the discussion for #1448, but the gist is that certain punctuation (
[
,]
, backticks,$
, etc.) causes Neovim to drop an escaped path separator on Windows. This requires us to use an additional\
(e.g.X:\[foo]\\\(bar)\baz.txt
).