Skip to content

fix(util): Path.parent now works on windows (#1168) #1179

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

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/luasnip.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*luasnip.txt* For NVIM v0.8.0 Last change: 2024 May 18
*luasnip.txt* For NVIM v0.8.0 Last change: 2024 May 21

==============================================================================
Table of Contents *luasnip-table-of-contents*
Expand Down
27 changes: 20 additions & 7 deletions lua/luasnip/util/path.lua
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,27 @@ function Path.components(path)
return vim.split(path, sep, { plain = true, trimempty = true })
end

function Path.parent(path)
local last_component = path:match("%" .. sep .. "[^" .. sep .. "]+$")
if not last_component then
return nil
end
Path.parent = (function()
if sep == "/" then
return function(path)
local last_component = path:match("[^/]+[/]*$")
if not last_component or #path == #last_component then
return nil
end

return path:sub(1, #path - #last_component)
end
return path:sub(1, #path - #last_component)
end
else
return function(path)
local last_component = path:match("[^/\\]+[/\\]*$")
if not last_component or #path == #last_component then
return nil
end

return path:sub(1, #path - #last_component)
end
end
end)()

-- returns nil if the file does not exist!
Path.normalize = uv.fs_realpath
Expand Down
116 changes: 116 additions & 0 deletions tests/unit/utils_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,119 @@ describe("luasnip.util.str:dedent", function()
check("2 and 1", " one\n two", " one\ntwo")
check("2 and 2", " one\n two", "one\ntwo")
end)

describe("luasnip.util.Path.parent", function()
local get_parent = require("luasnip.util.path").parent
local function assert_parents(examples)
for _, example in ipairs(examples) do
assert.are.same(example.expect, get_parent(example.path))
end
end

if jit and jit.os:lower() == "windows" then
describe("handles windows paths", function()
local examples = {
{
path = [[C:\Users\username\AppData\Local\nvim-data\log]],
expect = [[C:\Users\username\AppData\Local\nvim-data\]],
},
{
path = [[C:/Users/username/AppData/Local/nvim-data/log]],
expect = [[C:/Users/username/AppData/Local/nvim-data/]],
},
{
path = [[D:\Projects\project_folder\source_code.py]],
expect = [[D:\Projects\project_folder\]],
},
{
path = [[D:/Projects/project_folder/source_code.py]],
expect = [[D:/Projects/project_folder/]],
},
{ path = [[E:\Music\\\\]], expect = [[E:\]] },
{ path = [[E:/Music////]], expect = [[E:/]] },
{ path = [[E:\\Music\\\\]], expect = [[E:\\]] },
{ path = [[E://Music////]], expect = [[E://]] },
{ path = [[F:\]], expect = nil },
{ path = [[F:\\]], expect = nil },
{ path = [[F:/]], expect = nil },
{ path = [[F://]], expect = nil },
}

assert_parents(examples)
end)
elseif jit and jit.os:lower() == "linux" then
describe("handles linux paths", function()
local examples = {
{
path = [[/home/usuario/documents/archivo.txt]],
expect = [[/home/usuario/documents/]],
},
{
path = [[/var/www/html////index.html]],
expect = [[/var/www/html////]],
},
{
path = [[/mnt/backup/backup_file.tar.gz]],
expect = [[/mnt/backup/]],
},
{
path = [[/mnt/]],
expect = [[/]],
},
{
path = [[/mnt////]],
expect = [[/]],
},
{
path = [[/project/\backslash\is\legal\in\linux\filename.txt]],
expect = [[/project/]],
},
{
path = [[/\\\\]],
expect = [[/]],
},
{
path = [[/\\\\////]],
expect = [[/]],
},
{ path = [[/]], expect = nil },
}

assert_parents(examples)
end)
elseif jit and jit.os:lower() == "osx" then
describe("handles macos paths", function()
local examples = {
{
path = [[/Users/Usuario/Documents/archivo.txt]],
expect = [[/Users/Usuario/Documents/]],
},
{
path = [[/Applications/App.app/Contents/MacOS/app_executable]],
expect = [[/Applications/App.app/Contents/MacOS/]],
},
{
path = [[/Volumes/ExternalDrive/Data/file.xlsx]],
expect = [[/Volumes/ExternalDrive/Data/]],
},
{ path = [[/Volumes/]], expect = [[/]] },
{ path = [[/Volumes////]], expect = [[/]] },
{
path = [[/project/\backslash\is\legal\in\macos\filename.txt]],
expect = [[/project/]],
},
{
path = [[/\\\\]],
expect = [[/]],
},
{
path = [[/\\\\////]],
expect = [[/]],
},
{ path = [[/]], expect = nil },
}

assert_parents(examples)
end)
end
end)