local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local describe, it, before_each, after_each, setup, finally =
t.describe, t.it, t.before_each, t.after_each, t.setup, t.finally
local clear = n.clear
local exec_lua = n.exec_lua
local eq = t.eq
local eq_paths = t.eq_paths
local mkdir_p = n.mkdir_p
local rmdir = n.rmdir
local nvim_dir = n.nvim_dir
local command = n.command
local api = n.api
local fn = n.fn
local test_build_dir = t.paths.test_build_dir
local test_source_path = t.paths.test_source_path
local nvim_prog = n.nvim_prog
local is_os = t.is_os
local mkdir = t.mkdir
local nvim_prog_basename = is_os('win') and 'nvim.exe' or 'nvim'
local link_limit = is_os('win') and 64 or (is_os('mac') or is_os('bsd')) and 33 or 41
local test_basename_dirname_eq = {
'~/foo/',
'~/foo',
'~/foo/bar.lua',
'foo.lua',
' ',
'',
'.',
'..',
'../',
'~',
'/usr/bin',
'/usr/bin/gcc',
'/',
'/usr/',
'/usr',
'c:/usr',
'c:/',
'c:',
'c:/users/foo',
'c:/users/foo/bar.lua',
'c:/users/foo/bar/../',
'~/foo/bar\\baz',
}
local tests_windows_paths = {
'c:\\usr',
'c:\\',
'c:',
'c:\\users\\foo',
'c:\\users\\foo\\bar.lua',
'c:\\users\\foo\\bar\\..\\',
}
setup(clear)
describe('vim.fs', function()
describe('parents()', function()
it('works', function()
local test_dir = nvim_dir .. '/test'
mkdir_p(test_dir)
local dirs = {} --- @type string[]
for dir in vim.fs.parents(test_dir .. '/foo.txt') do
dirs[#dirs + 1] = dir
if dir == test_build_dir then
break
end
end
eq({ test_dir, nvim_dir, test_build_dir }, dirs)
rmdir(test_dir)
end)
end)
describe('dirname()', function()
it('works', function()
eq(test_build_dir, vim.fs.dirname(nvim_dir))
---@param paths string[]
---@param is_win? boolean
local function test_paths(paths, is_win)
local gsub = is_win and [[:gsub('\\', '/')]] or ''
local code = string.format(
[[
local path = ...
return vim.fn.fnamemodify(path,':h')%s
]],
gsub
)
for _, path in ipairs(paths) do
eq(exec_lua(code, path), vim.fs.dirname(path), path)
end
end
test_paths(test_basename_dirname_eq)
if is_os('win') then
test_paths(tests_windows_paths, true)
end
end)
it('trims redundant slashes #37698', function()
eq('/name', vim.fs.dirname('/name//////////'))
end)
end)
describe('basename()', function()
it('works', function()
eq(nvim_prog_basename, vim.fs.basename(nvim_prog))
---@param paths string[]
---@param is_win? boolean
local function test_paths(paths, is_win)
local gsub = is_win and [[:gsub('\\', '/')]] or ''
local code = string.format(
[[
local path = ...
return vim.fn.fnamemodify(path,':t')%s
]],
gsub
)
for _, path in ipairs(paths) do
eq(exec_lua(code, path), vim.fs.basename(path), path)
end
end
test_paths(test_basename_dirname_eq)
if is_os('win') then
test_paths(tests_windows_paths, true)
end
end)
it('trims redundant slashes #37698', function()
-- XXX: for better or worse, this matches python's `os.path.basename`.
-- https://github.com/neovim/neovim/issues/37698#issuecomment-3847866806
eq('', vim.fs.basename('/name//////////'))
end)
end)
describe('dir()', function()
before_each(function()
mkdir('testd')
mkdir('testd/a')
mkdir('testd/a/b')
mkdir('testd/a/b/c')
end)
after_each(function()
rmdir('testd')
end)
it('works', function()
eq(
true,
exec_lua(function()
for name, type in vim.fs.dir(nvim_dir) do
if name == nvim_prog_basename and type == 'file' then
return true
end
end
return false
end)
)
end)
it('works with opts.depth, opts.skip and opts.follow', function()
io.open('testd/a1', 'w'):close()
io.open('testd/b1', 'w'):close()
io.open('testd/c1', 'w'):close()
io.open('testd/a/a2', 'w'):close()
io.open('testd/a/b2', 'w'):close()
io.open('testd/a/c2', 'w'):close()
io.open('testd/a/b/a3', 'w'):close()
io.open('testd/a/b/b3', 'w'):close()
io.open('testd/a/b/c3', 'w'):close()
io.open('testd/a/b/c/a4', 'w'):close()
io.open('testd/a/b/c/b4', 'w'):close()
io.open('testd/a/b/c/c4', 'w'):close()
local function run(dir, depth, skip, follow)
return exec_lua(function(follow_)
local r = {} --- @type table<string, string>
local skip_f --- @type function
if skip then
skip_f = function(n0)
if vim.tbl_contains(skip or {}, n0) then
return false
end
end
end
for name, type_ in vim.fs.dir(
|