diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-11-19 22:57:13 +0000 |
commit | 9be89f131f87608f224f0ee06d199fcd09d32176 (patch) | |
tree | 11022dcfa9e08cb4ac5581b16734196128688d48 /runtime/lua/vim/fs.lua | |
parent | ff7ed8f586589d620a806c3758fac4a47a8e7e15 (diff) | |
parent | 88085c2e80a7e3ac29aabb6b5420377eed99b8b6 (diff) | |
download | rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.gz rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.tar.bz2 rneovim-9be89f131f87608f224f0ee06d199fcd09d32176.zip |
Merge remote-tracking branch 'upstream/master' into mix_20240309
Diffstat (limited to 'runtime/lua/vim/fs.lua')
-rw-r--r-- | runtime/lua/vim/fs.lua | 84 |
1 files changed, 74 insertions, 10 deletions
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index b05220ee2c..ccddf826f7 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -1,6 +1,10 @@ +local uv = vim.uv + local M = {} -local iswin = vim.uv.os_uname().sysname == 'Windows_NT' +-- 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 os_sep = iswin and '\\' or '/' --- Iterate over all the parents of the given path. @@ -21,6 +25,7 @@ local os_sep = iswin and '\\' or '/' --- end --- ``` --- +---@since 10 ---@param start (string) Initial path. ---@return fun(_, dir: string): string? # Iterator ---@return nil @@ -40,6 +45,7 @@ end --- Return the parent directory of the given path --- +---@since 10 ---@generic T : string|nil ---@param file T Path ---@return T Parent directory of {file} @@ -69,6 +75,7 @@ end --- Return the basename of the given path --- +---@since 10 ---@generic T : string|nil ---@param file T Path ---@return T Basename of {file} @@ -89,6 +96,7 @@ end --- Concatenate directories and/or file paths into a single path with normalization --- (e.g., `"foo/"` and `"bar"` get joined to `"foo/bar"`) --- +---@since 12 ---@param ... string ---@return string function M.joinpath(...) @@ -99,6 +107,7 @@ end --- Return an iterator over the items located in {path} --- +---@since 10 ---@param path (string) An absolute or relative path to the directory to iterate --- over. The path is first normalized |vim.fs.normalize()|. --- @param opts table|nil Optional keyword arguments: @@ -122,12 +131,12 @@ function M.dir(path, opts) path = M.normalize(path) if not opts.depth or opts.depth == 1 then - local fs = vim.uv.fs_scandir(path) + local fs = uv.fs_scandir(path) return function() if not fs then return end - return vim.uv.fs_scandir_next(fs) + return uv.fs_scandir_next(fs) end end @@ -138,9 +147,9 @@ function M.dir(path, opts) --- @type string, integer local dir0, level = unpack(table.remove(dirs, 1)) local dir = level == 1 and dir0 or M.joinpath(path, dir0) - local fs = vim.uv.fs_scandir(dir) + local fs = uv.fs_scandir(dir) while fs do - local name, t = vim.uv.fs_scandir_next(fs) + local name, t = uv.fs_scandir_next(fs) if not name then break end @@ -210,6 +219,7 @@ end --- end, {limit = math.huge, type = 'file'}) --- ``` --- +---@since 10 ---@param names (string|string[]|fun(name: string, path: string): boolean) Names of the items to find. --- Must be base names, paths and globs are not supported when {names} is a string or a table. --- If {names} is a function, it is called for each traversed item with args: @@ -234,7 +244,7 @@ function M.find(names, opts) names = { names } end - local path = opts.path or assert(vim.uv.cwd()) + local path = opts.path or assert(uv.cwd()) local stop = opts.stop local limit = opts.limit or 1 @@ -265,7 +275,7 @@ function M.find(names, opts) local t = {} --- @type string[] for _, name in ipairs(names) do local f = M.joinpath(p, name) - local stat = vim.uv.fs_stat(f) + local stat = uv.fs_stat(f) if stat and (not opts.type or opts.type == stat.type) then t[#t + 1] = f end @@ -349,6 +359,7 @@ end --- end) --- ``` --- +--- @since 12 --- @param source integer|string Buffer number (0 for current buffer) or file path (absolute or --- relative to the |current-directory|) to begin the search from. --- @param marker (string|string[]|fun(name: string, path: string): boolean) A marker, or list @@ -365,7 +376,7 @@ function M.root(source, marker) path = source elseif type(source) == 'number' then if vim.bo[source].buftype ~= '' then - path = assert(vim.uv.cwd()) + path = assert(uv.cwd()) else path = vim.api.nvim_buf_get_name(source) end @@ -528,6 +539,7 @@ end --- [[\\?\UNC\server\share\foo\..\..\..\bar]] => "//?/UNC/server/share/bar" --- ``` --- +---@since 10 ---@param path (string) Path to normalize ---@param opts? vim.fs.normalize.Opts ---@return (string) : Normalized path @@ -552,7 +564,7 @@ function M.normalize(path, opts) -- Expand ~ to users home directory if vim.startswith(path, '~') then - local home = vim.uv.os_homedir() or '~' + local home = uv.os_homedir() or '~' if home:sub(-1) == os_sep_local then home = home:sub(1, -2) end @@ -561,7 +573,7 @@ function M.normalize(path, opts) -- Expand environment variables if `opts.expand_env` isn't `false` if opts.expand_env == nil or opts.expand_env then - path = path:gsub('%$([%w_]+)', vim.uv.os_getenv) + path = path:gsub('%$([%w_]+)', uv.os_getenv) end if win then @@ -609,4 +621,56 @@ function M.normalize(path, opts) return path end +--- @param path string Path to remove +--- @param ty string type of path +--- @param recursive? boolean +--- @param force? boolean +local function rm(path, ty, recursive, force) + --- @diagnostic disable-next-line:no-unknown + local rm_fn + + if ty == 'directory' then + if recursive then + for file, fty in vim.fs.dir(path) do + rm(M.joinpath(path, file), fty, true, force) + end + elseif not force then + error(string.format('%s is a directory', path)) + end + + rm_fn = uv.fs_rmdir + else + rm_fn = uv.fs_unlink + end + + local ret, err, errnm = rm_fn(path) + if ret == nil and (not force or errnm ~= 'ENOENT') then + error(err) + end +end + +--- @class vim.fs.rm.Opts +--- @inlinedoc +--- +--- Remove directories and their contents recursively +--- @field recursive? boolean +--- +--- Ignore nonexistent files and arguments +--- @field force? boolean + +--- Remove files or directories +--- @since 13 +--- @param path string Path to remove +--- @param opts? vim.fs.rm.Opts +function M.rm(path, opts) + opts = opts or {} + + local stat, err, errnm = uv.fs_stat(path) + if stat then + rm(path, stat.type, opts.recursive, opts.force) + elseif not opts.force or errnm ~= 'ENOENT' then + error(err) + end +end + return M |