refactor(vim.fs): deduplicate by using vim.fn #39782

Problem:
61e99217e6 replaced usages of `vim.fn`. This duplicates non-trivial
logic and may have introduced bugs like 38e38d1b40.

Later on, b02eeb6a72 graduated `fnamemodify` to `fast`, so avoiding it
in `vim.fs` is no longer necessary.

Solution:
Use `vim.fn` to deduplicate `vim.fs.dirname()` and `vim.fs.basename()`.

Note: the "nvim -l" test-runner switch from the original PR (#30483) is
already done by 9432e6c1e2 (#39676).
This commit is contained in:
Justin M. Keyes
2026-05-14 13:02:36 -04:00
committed by GitHub
parent 8b7b0a5cd6
commit c7f5f44b60
2 changed files with 10 additions and 26 deletions

View File

@@ -44,9 +44,7 @@ local uv = vim.uv
local M = {}
-- Can't use `has('win32')` because the `nvim -ll` test runner doesn't support `vim.fn` yet.
local sysname = uv.os_uname().sysname:lower()
local iswin = not not (sysname:find('windows') or sysname:find('mingw'))
local iswin = vim.fn.has('win32') == 1
local os_sep = iswin and '\\' or '/'
--- Iterate over all the parents of the given path (not expanded/resolved, the caller must do that).
@@ -90,27 +88,15 @@ end
---@since 10
---@generic T : string|nil
---@param file T Path
---@return T Parent directory of {file}
---@return T # Parent directory of `file`
function M.dirname(file)
if file == nil then
return nil
end
vim.validate('file', file, 'string')
local dir = vim.fn.fnamemodify(file, ':h')
if iswin then
file = file:gsub(os_sep, '/') --[[@as string]]
if file:match('^%w:/?$') then
return file
end
end
if not file:match('/') then
return '.'
elseif file == '/' or file:match('^/[^/]+$') then
return '/'
end
---@type string
local dir = file:match('/$') and file:sub(1, #file - 1) or file:match('^(/?.+)/')
if iswin and dir:match('^%w:$') then
return dir .. '/'
return (dir:gsub(os_sep, '/'))
end
return dir
end
@@ -120,19 +106,17 @@ end
---@since 10
---@generic T : string|nil
---@param file T Path
---@return T Basename of {file}
---@return T # Basename of `file`
function M.basename(file)
if file == nil then
return nil
end
vim.validate('file', file, 'string')
local name = vim.fn.fnamemodify(file, ':t')
if iswin then
file = file:gsub(os_sep, '/') --[[@as string]]
if file:match('^%w:/?$') then
return ''
end
return (name:gsub(os_sep, '/'))
end
return file:match('/$') and '' or (file:match('[^/]*$'))
return name
end
--- Concatenates partial paths (one absolute or relative path followed by zero or more relative