aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustav Eikaas <46537983+GustavEikaas@users.noreply.github.com>2024-12-31 16:40:05 +0100
committerGitHub <noreply@github.com>2024-12-31 07:40:05 -0800
commit0bef3b911cc262a007fb4412d864c1832d1268ad (patch)
tree0f9e53d86a429388021931b7541250aa03f86986
parentb3bdba5cb10f9f0f1f2b40ff40e807f8a22f65c1 (diff)
downloadrneovim-0bef3b911cc262a007fb4412d864c1832d1268ad.tar.gz
rneovim-0bef3b911cc262a007fb4412d864c1832d1268ad.tar.bz2
rneovim-0bef3b911cc262a007fb4412d864c1832d1268ad.zip
fix(vim.fs): joinpath() does not normalize slashes on Windows #31782
-rw-r--r--runtime/doc/lua.txt7
-rw-r--r--runtime/lua/vim/fs.lua11
-rw-r--r--test/functional/lua/fs_spec.lua14
3 files changed, 27 insertions, 5 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index a2a83ef229..022adb3da7 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -3062,8 +3062,11 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
items
vim.fs.joinpath({...}) *vim.fs.joinpath()*
- Concatenate directories and/or file paths into a single path with
- normalization (e.g., `"foo/"` and `"bar"` get joined to `"foo/bar"`)
+ Concatenates partial paths into one path. Slashes are normalized
+ (redundant slashes are removed, and on Windows backslashes are replaced
+ with forward-slashes) (e.g., `"foo/"` and `"/bar"` get joined to
+ `"foo/bar"`) (windows: e.g `"a\foo\"` and `"\bar"` are joined to
+ `"a/foo/bar"`)
Attributes: ~
Since: 0.10.0
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index f2cd210cac..1b774d5cab 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -105,14 +105,19 @@ function M.basename(file)
return file:match('/$') and '' or (file:match('[^/]*$'))
end
---- Concatenate directories and/or file paths into a single path with normalization
---- (e.g., `"foo/"` and `"bar"` get joined to `"foo/bar"`)
+--- Concatenates partial paths into one path. Slashes are normalized (redundant slashes are removed, and on Windows backslashes are replaced with forward-slashes)
+--- (e.g., `"foo/"` and `"/bar"` get joined to `"foo/bar"`)
+--- (windows: e.g `"a\foo\"` and `"\bar"` are joined to `"a/foo/bar"`)
---
---@since 12
---@param ... string
---@return string
function M.joinpath(...)
- return (table.concat({ ... }, '/'):gsub('//+', '/'))
+ local path = table.concat({ ... }, '/')
+ if iswin then
+ path = path:gsub('\\', '/')
+ end
+ return (path:gsub('//+', '/'))
end
---@alias Iterator fun(): string?, string?
diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua
index 63444f5ba1..3c306e6824 100644
--- a/test/functional/lua/fs_spec.lua
+++ b/test/functional/lua/fs_spec.lua
@@ -323,6 +323,20 @@ describe('vim.fs', function()
eq('foo/bar/baz', vim.fs.joinpath('foo', 'bar', 'baz'))
eq('foo/bar/baz', vim.fs.joinpath('foo', '/bar/', '/baz'))
end)
+ it('rewrites backslashes on Windows', function()
+ if is_os('win') then
+ eq('foo/bar/baz/zub/', vim.fs.joinpath([[foo]], [[\\bar\\\\baz]], [[zub\]]))
+ else
+ eq([[foo/\\bar\\\\baz/zub\]], vim.fs.joinpath([[foo]], [[\\bar\\\\baz]], [[zub\]]))
+ end
+ end)
+ it('strips redundant slashes', function()
+ if is_os('win') then
+ eq('foo/bar/baz/zub/', vim.fs.joinpath([[foo//]], [[\\bar\\\\baz]], [[zub\]]))
+ else
+ eq('foo/bar/baz/zub/', vim.fs.joinpath([[foo]], [[//bar////baz]], [[zub/]]))
+ end
+ end)
end)
describe('normalize()', function()