mirror of
https://github.com/L3MON4D3/LuaSnip
synced 2024-09-16 21:54:03 +02:00
On Windows, both forward slash `/` and backslash `\\` work as the path separator. Linux and MacOS can have backslash as a valid filename character. Unit tests are also provided for each platform because `Path.parent` depends on the local variable `sep` which depends on `jit.os`. Fixes #1168
This commit is contained in:
parent
de1a287c9c
commit
d890d6d6b9
3 changed files with 175 additions and 7 deletions
|
@ -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 22
|
||||
|
||||
==============================================================================
|
||||
Table of Contents *luasnip-table-of-contents*
|
||||
|
|
|
@ -193,14 +193,72 @@ 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
|
||||
---Get parent of a path, without trailing separator
|
||||
---if path is a directory or does not have a parent, returns nil
|
||||
---Example:
|
||||
--- On platforms that use "\\" backslash as path separator, e.g., Windows:
|
||||
--- Path.parent("C:/project_root/file.txt") -- returns "C:/project_root"
|
||||
--- Path.parent([[C:\project_root\file.txt]]) -- returns [[C:\project_root]]
|
||||
---
|
||||
--- -- the followings return `nil`s
|
||||
--- Path.parent("C:/")
|
||||
--- Path.parent([[C:\]])
|
||||
--- Path.parent([[C:\project_root\]])
|
||||
---
|
||||
--- -- WARN: although it's unlikely that we will reach the driver's root
|
||||
--- -- level, Path.parent("C:\file.txt") returns "C:", and please be
|
||||
--- -- cautious when passing the parent path to some vim functions because
|
||||
--- -- some vim functions on Windows treat "C:" as a file instead:
|
||||
--- -- vim.fn.fnamemodify("C:", ":p") -- returns $CWD .. sep .. "C:"
|
||||
--- -- To get the desired result, use vim.fn.fnamemodify("C:" .. sep, ":p")
|
||||
---
|
||||
--- On platforms that use "/" forward slash as path separator, e.g., linux:
|
||||
--- Path.parent("/project_root/file.txt") returns "/project_root"
|
||||
--- Path.parent("/file.txt") returns ""
|
||||
---
|
||||
--- -- the followings return `nil`s
|
||||
--- Path.parent("/")
|
||||
--- Path.parent("/project_root/")
|
||||
---
|
||||
--- -- backslash in a valid filename character in linux:
|
||||
--- Path.parent([[/project_root/\valid\file\name.txt]]) returns "/project_root"
|
||||
Path.parent = (function()
|
||||
---@alias PathSeparator "/" | "\\"
|
||||
---@param os_sep PathSeparator
|
||||
---@return fun(string): string | nil
|
||||
local function generate_parent(os_sep)
|
||||
if os_sep == "/" then
|
||||
---@param path string
|
||||
---@return string | nil
|
||||
return function(path)
|
||||
local last_component = path:match("[/]+[^/]+$")
|
||||
if not last_component then
|
||||
return nil
|
||||
end
|
||||
|
||||
return path:sub(1, #path - #last_component)
|
||||
end
|
||||
else
|
||||
---@param path string
|
||||
---@return string | nil
|
||||
return function(path)
|
||||
local last_component = path:match("[/\\]+[^/\\]+$")
|
||||
if not last_component then
|
||||
return nil
|
||||
end
|
||||
|
||||
return path:sub(1, #path - #last_component)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return path:sub(1, #path - #last_component)
|
||||
end
|
||||
-- for test only
|
||||
if __LUASNIP_TEST_SEP_OVERRIDE then
|
||||
return generate_parent
|
||||
else
|
||||
return generate_parent(sep)
|
||||
end
|
||||
end)()
|
||||
|
||||
-- returns nil if the file does not exist!
|
||||
Path.normalize = uv.fs_realpath
|
||||
|
|
|
@ -23,3 +23,113 @@ 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 function assert_parents(separator, examples)
|
||||
for _, example in ipairs(examples) do
|
||||
if example.expect then
|
||||
it(example.path, function()
|
||||
assert.are.same(
|
||||
example.expect,
|
||||
exec_lua(
|
||||
"__LUASNIP_TEST_SEP_OVERRIDE = [["
|
||||
.. separator
|
||||
.. "]] "
|
||||
.. 'return require("luasnip.util.path").parent([['
|
||||
.. separator
|
||||
.. "]])([["
|
||||
.. example.path
|
||||
.. "]])"
|
||||
)
|
||||
)
|
||||
end)
|
||||
else
|
||||
it(example.path .. " to be nil", function()
|
||||
assert.is_true(
|
||||
exec_lua(
|
||||
"__LUASNIP_TEST_SEP_OVERRIDE = [["
|
||||
.. separator
|
||||
.. "]] "
|
||||
.. 'return require("luasnip.util.path").parent([['
|
||||
.. separator
|
||||
.. "]])([["
|
||||
.. example.path
|
||||
.. "]]) == nil"
|
||||
)
|
||||
)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe("backslash as the path separator", 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 = nil },
|
||||
{ path = [[E:/Music////]], expect = nil },
|
||||
{ path = [[E:\\Music\\\\]], expect = nil },
|
||||
{ path = [[E://Music////]], expect = nil },
|
||||
{ path = [[F:\]], expect = nil },
|
||||
{ path = [[F:\\]], expect = nil },
|
||||
{ path = [[F:/]], expect = nil },
|
||||
{ path = [[F://]], expect = nil },
|
||||
}
|
||||
|
||||
assert_parents("\\", examples)
|
||||
end)
|
||||
|
||||
describe("forward slash as the path separator", 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 = nil,
|
||||
},
|
||||
{
|
||||
path = [[/mnt////]],
|
||||
expect = nil,
|
||||
},
|
||||
{
|
||||
path = [[/project/\backslash\is\legal\in\linux\filename.txt]],
|
||||
expect = [[/project]],
|
||||
},
|
||||
{
|
||||
path = [[/\\\\]],
|
||||
expect = "",
|
||||
},
|
||||
{
|
||||
path = [[/\\\\////]],
|
||||
expect = nil,
|
||||
},
|
||||
{ path = [[/]], expect = nil },
|
||||
}
|
||||
|
||||
assert_parents("/", examples)
|
||||
end)
|
||||
end)
|
||||
|
|
Loading…
Reference in a new issue