mirror of
https://github.com/neovim/neovim.git
synced 2024-09-17 20:58:20 -04:00
feat(lua): add vim.fs.abspath
Problem: There is currently no way to check if a given path is absolute or convert a relative path to an absolute path through the Lua stdlib. `vim.fs.joinpath` does not work when the path is absolute. There is also currently no way to resolve `C:foo\bar` style paths in Windows. Solution: Add `vim.fs.abspath`, which allows converting any path to an absolute path. This also allows checking if current path is absolute by doing `vim.fs.abspath(path) == path`. It also has support for `C:foo\bar` style paths in Windows.
This commit is contained in:
parent
2f371ad7d0
commit
a42314734e
@ -2854,6 +2854,20 @@ vim.keymap.set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
|
||||
==============================================================================
|
||||
Lua module: vim.fs *vim.fs*
|
||||
|
||||
vim.fs.abspath({path}) *vim.fs.abspath()*
|
||||
Convert path to an absolute path. A tilde (~) character at the beginning
|
||||
of the path is expanded to the user's home directory. Does not check if
|
||||
the path exists, normalize the path, resolve symlinks or hardlinks
|
||||
(including `.` and `..`), or expand environment variables. If the path is
|
||||
already absolute, it is returned unchanged. Also converts `\` path
|
||||
separators to `/`.
|
||||
|
||||
Parameters: ~
|
||||
• {path} (`string`) Path
|
||||
|
||||
Return: ~
|
||||
(`string`) Absolute path
|
||||
|
||||
vim.fs.basename({file}) *vim.fs.basename()*
|
||||
Return the basename of the given path
|
||||
|
||||
|
@ -353,6 +353,8 @@ The following new APIs and features were added.
|
||||
|
||||
• Added built-in |commenting| support.
|
||||
|
||||
• |vim.fs.abspath()| converts paths to absolute paths.
|
||||
|
||||
==============================================================================
|
||||
CHANGED FEATURES *news-changed*
|
||||
|
||||
|
@ -437,6 +437,24 @@ local function path_resolve_dot(path)
|
||||
return (is_path_absolute and '/' or '') .. table.concat(new_path_components, '/')
|
||||
end
|
||||
|
||||
--- Expand tilde (~) character at the beginning of the path to the user's home directory.
|
||||
---
|
||||
--- @param path string Path to expand.
|
||||
--- @return string Expanded path.
|
||||
local function expand_home(path)
|
||||
if vim.startswith(path, '~') then
|
||||
local home = vim.uv.os_homedir() or '~'
|
||||
|
||||
if home:sub(-1) == os_sep then
|
||||
home = home:sub(1, -2)
|
||||
end
|
||||
|
||||
path = home .. path:sub(2)
|
||||
end
|
||||
|
||||
return path
|
||||
end
|
||||
|
||||
--- @class vim.fs.normalize.Opts
|
||||
--- @inlinedoc
|
||||
---
|
||||
@ -497,14 +515,8 @@ function M.normalize(path, opts)
|
||||
return ''
|
||||
end
|
||||
|
||||
-- Expand ~ to users home directory
|
||||
if vim.startswith(path, '~') then
|
||||
local home = vim.uv.os_homedir() or '~'
|
||||
if home:sub(-1) == os_sep_local then
|
||||
home = home:sub(1, -2)
|
||||
end
|
||||
path = home .. path:sub(2)
|
||||
end
|
||||
-- Expand ~ to user's home directory
|
||||
path = expand_home(path)
|
||||
|
||||
-- Expand environment variables if `opts.expand_env` isn't `false`
|
||||
if opts.expand_env == nil or opts.expand_env then
|
||||
@ -545,4 +557,44 @@ function M.normalize(path, opts)
|
||||
return path
|
||||
end
|
||||
|
||||
--- Convert path to an absolute path. A tilde (~) character at the beginning of the path is expanded
|
||||
--- to the user's home directory. Does not check if the path exists, normalize the path, resolve
|
||||
--- symlinks or hardlinks (including `.` and `..`), or expand environment variables. If the path is
|
||||
--- already absolute, it is returned unchanged. Also converts `\` path separators to `/`.
|
||||
---
|
||||
--- @param path string Path
|
||||
--- @return string Absolute path
|
||||
function M.abspath(path)
|
||||
vim.validate({
|
||||
path = { path, { 'string' } },
|
||||
})
|
||||
|
||||
-- Expand ~ to user's home directory
|
||||
path = expand_home(path)
|
||||
|
||||
-- Convert path separator to `/`
|
||||
path = path:gsub(os_sep, '/')
|
||||
|
||||
local prefix = ''
|
||||
|
||||
if iswin then
|
||||
prefix, path = split_windows_path(path)
|
||||
end
|
||||
|
||||
if vim.startswith(path, '/') then
|
||||
-- Path is already absolute, do nothing
|
||||
return prefix .. path
|
||||
end
|
||||
|
||||
-- Windows allows paths like C:foo/bar, these paths are relative to the current working directory
|
||||
-- of the drive specified in the path
|
||||
local cwd = (iswin and prefix:match('^%w:$')) and vim.uv.fs_realpath(prefix) or vim.uv.cwd()
|
||||
assert(cwd ~= nil)
|
||||
-- Convert cwd path separator to `/`
|
||||
cwd = cwd:gsub(os_sep, '/')
|
||||
|
||||
-- Prefix is not needed for expanding relative paths, as `cwd` already contains it.
|
||||
return M.joinpath(cwd, path)
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -416,4 +416,46 @@ describe('vim.fs', function()
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('abspath', function()
|
||||
local cwd = vim.uv.cwd()
|
||||
local home = vim.uv.os_homedir()
|
||||
|
||||
assert(cwd ~= nil)
|
||||
assert(home ~= nil)
|
||||
|
||||
if is_os('win') then
|
||||
cwd = cwd:gsub('\\', '/')
|
||||
home = home:gsub('\\', '/')
|
||||
end
|
||||
|
||||
it('works', function()
|
||||
eq(cwd .. '/foo', vim.fs.abspath('foo'))
|
||||
eq(cwd .. '/././foo', vim.fs.abspath('././foo'))
|
||||
eq(cwd .. '/.././../foo', vim.fs.abspath('.././../foo'))
|
||||
end)
|
||||
|
||||
it('works with absolute paths', function()
|
||||
if is_os('win') then
|
||||
eq([[C:/foo]], vim.fs.abspath([[C:\foo]]))
|
||||
eq([[C:/foo/../.]], vim.fs.abspath([[C:\foo\..\.]]))
|
||||
else
|
||||
eq('/foo/../.', vim.fs.abspath('/foo/../.'))
|
||||
eq('/foo/bar', vim.fs.abspath('/foo/bar'))
|
||||
end
|
||||
end)
|
||||
|
||||
it('expands ~', function()
|
||||
eq(home .. '/foo', vim.fs.abspath('~/foo'))
|
||||
eq(home .. '/./.././foo', vim.fs.abspath('~/./.././foo'))
|
||||
end)
|
||||
|
||||
if is_os('win') then
|
||||
it('works with drive-specific cwd on Windows', function()
|
||||
local cwd_drive = cwd:match('^%w:')
|
||||
|
||||
eq(cwd .. '/foo', vim.fs.abspath(cwd_drive .. 'foo'))
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user