summaryrefslogtreecommitdiffstatshomepage
path: root/runtime/lua/vim/fs.lua
AgeCommit message (Collapse)AuthorFiles
2026-04-18docs: misc #39045Justin M. Keyes1
2026-03-28docs: news #38464Justin M. Keyes1
2026-03-20feat(stdlib): vim.fs.ext() returns file extension #36997Yochem van Rosmalen1
Problem: Checking the extension of a file is done often, e.g. in Nvim's codebase for differentiating Lua and Vimscript files in the runtime. The current way to do this in Lua is (1) a Lua pattern match, which has pitfalls such as not considering filenames starting with a dot, or (2) fnamemodify() which is both hard to discover and hard to use / read if not very familiar with the possible modifiers. vim.fs.ext() returns the file extension including the leading dot of the extension. Similar to the "file extension" implementation of many other stdlibs (including fnamemodify(file, ":e")), a leading dot doesn't indicate the start of the extension. E.g.: the .git folder in a repository doesn't have the extension .git, but it simply has no extension, similar to a folder named git or any other filename without dot(s).
2026-03-12refactor: integer functions, optimize asserts #34112Lewis Russell1
refactor(lua): add integer coercion helpers Add vim._tointeger() and vim._ensure_integer(), including optional base support, and switch integer-only tonumber()/assert call sites in the Lua runtime to use them. This also cleans up related integer parsing in LSP, health, loader, URI, tohtml, and Treesitter code. supported by AI
2026-02-27fix(vim.fs): joinpath() should ignore empty items #38077Yochem van Rosmalen1
Problem: vim.fs.joinpath treats empty string as a path segment (it adds a path separator for each empty item): print(vim.fs.joinpath('', 'after/lsp', '')) -- '/after/lsp/' print(vim.fs.joinpath('', '')) -- '/' Especially problematic if the empty segment is the first segment, as that converts the path to an absolute path. Solution: Ignore empty (length of 0) path segments. Benchmark: local function test(func) local t = vim.uv.hrtime() for _ = 1, 100000, 1 do func('', 'this/is', 'a/very/long/path', '', 'it', 'really', 'is') end print(math.floor((vim.uv.hrtime() - t) / 1e6), 'ms') end - with Iter():filter() --> 370 ms - building new segments table --> 208 ms - with vim.tbl_filter --> 232 ms - Instead of gsub split on `/` in all parts --> 1870 ms
2026-02-12docs: vim.fs path expansionJustin M. Keyes1
fix #37583
2026-02-10fix(vim.fs): make `rm()` work with symlink to a directoryEvgeni Chasnovski1
2026-01-27fix: misc typos #37471phanium1
2025-12-30fix(vim.fs): avoid fn.fnamemodify in fs.root #37162Jason Shipman1
Problem: vim.fs.root uses vim.fn.fnamemodify. vim.fn table isn't available from nvim -ll or thread contexts. Solution: Swap out vim.fn.fnamemodify for vim.fs.abspath. This is a temporary workaround and may be reverted since the long-term plan is to use more fast=true "fn" functions from vim.fs where possible.
2025-11-16fix(vim.fs): abspath(".") returns "/…/." #36583Justin M. Keyes1
2025-11-16fix(vim.fs): root() should always return absolute path #36466Cameron Ring1
2025-11-15docs: getpos, getregion, lspJustin M. Keyes1
2025-08-28refactor(lua): consistent use of local aliasesChristian Clason1
2025-06-17docs: vim.fs.dir.Opts type #34546phanium1
Follow the pattern of vim.fs.find.Opts
2025-06-13docs: vim.fs., diagnostics, lsp #34402Justin M. Keyes1
2025-06-09feat(vim.fs): root() can specify "equal priority" #34276Siddhant Agarwal1
2025-04-27docs: lsp, emoji, startup #33446Justin M. Keyes1
Co-authored-by: Maria José Solano <majosolano99@gmail.com>
2025-03-14fix(vim.fs): default to follow=false #32859Mike1
Problem: Following symlinks can have surprising behavior and slow performance. Solution: Do not set it by default.
2025-01-27fix: resolve all remaining LuaLS diagnosticsLewis Russell1
2025-01-14feat(vim.fs): find(), dir() can "follow" symlinks #31551Mike1
Problem: vim.fs.dir(), vim.fs.find() do not follow symlinks. Solution: - Add "follow" flag. - Enable it by default.
2025-01-13feat: add vim.fs.relpathdundargoc1
This is needed to replace the nvim-lspconfig function is_descendant that some lspconfg configurations still use.
2025-01-04fix(vim.fs.normalize): normalize case for windows drive letterdundargoc1
Also add tests for the current path casing behavior so it doesn't get accidentally changed.
2025-01-01fix(vim.fs.abspath): correctly handle UNC pathsdundargoc1
2025-01-01docs: misc #31479Justin M. Keyes1
2024-12-31fix(vim.fs): joinpath() does not normalize slashes on Windows #31782Gustav Eikaas1
2024-12-28feat(lua): add `vim.fs.abspath`Famiu Haque1
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.
2024-11-27docs: add tag `vim.fs.exists()` and document suggested replacementdundargoc1
2024-10-21feat(vim.validate): improve fast form and deprecate spec formLewis Russell1
Problem: `vim.validate()` takes two forms when it only needs one. Solution: - Teach the fast form all the features of the spec form. - Deprecate the spec form. - General optimizations for both forms. - Add a `message` argument which can be used alongside or in place of the `optional` argument.
2024-10-17perf(validate): use lighter versionLewis Russell1
- Also fix `vim.validate()` for PUC Lua when showing errors for values that aren't string or number.
2024-10-04docs: more `@since` annotations #30660Justin M. Keyes1
2024-09-23fix(vim.fs): dirname() returns "." on mingw/msys2 #30480Justin M. Keyes1
Problem: `vim.fs.dirname([[C:\User\XXX\AppData\Local]])` returns "." on mingw/msys2. Solution: - Check for "mingw" when deciding `iswin`. - Use `has("win32")` where possible, it works in "fast" contexts since b02eeb6a7281df0561a021d7ae595c84be9a01be.
2024-09-22feat(fs.lua): add vim.fs.rm()Lewis Russell1
Analogous to the shell `rm` command.
2024-05-24fix(fs): make vim.fs.root work for relative paths and unnamed buffers (#28964)Gregory Anders1
If a buffer does not have a backing file then fall back to the current working directory.
2024-05-15perf(vim.fs.normalize): use iteratorLewis Russell1
~10% faster.
2024-05-15perf(loader): use a quicker version of vim.fs.normalizeLewis Russell1
Problem: vim.fs.normalize() normalizes too much vim.loader and is slow. Solution: Make it faster by doing less. This reduces the times spent in vim.fs.normalize in vim.loader from ~13ms -> 1-2ms. Numbers from a relative benchmark: - Skipping `vim.validate()`: 285ms -> 230ms - Skipping `path_resolve_dot()`: 285ms -> 60ms - Skipping `double_slash`: 60ms -> 35ms
2024-05-14perf(fs): normalize path only once in fs.dirMathias Fussenegger1
Re-normalizing a path after a `joinpath` isn't necessary. Calling `normalize` on each child directory had quite a bit of impact when traversing a large directory. A simple test showed: Before: ~144ms After: ~80ms running the following logic against a dir with 4367 child folders and 25826 files: local files = {} local start = uv.hrtime() for name, type in vim.fs.dir(path, { depth = max_depth }) do table.insert(files, { name, type }) end local duration = uv.hrtime() - start Relates to https://github.com/neovim/neovim/issues/23291
2024-04-24feat(fs): add vim.fs.root (#28477)Gregory Anders1
vim.fs.root() is a function for finding a project root relative to a buffer using one or more "root markers". This is useful for LSP and could be useful for other "projects" designs, as well as for any plugins which work with a "projects" concept.
2024-04-16feat(lua): vim.fs.normalize() resolves ".", ".." #28203Famiu Haque1
Problem: `vim.fs.normalize` does not resolve `.` and `..` components. This makes no sense as the entire point of normalization is to remove redundancy from the path. The path normalization functions in several other languages (Java, Python, C++, etc.) also resolve `.` and `..` components. Reference: - Python: https://docs.python.org/3/library/os.path.html#os.path.normpath - Java: https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html#normalize-- - C++: https://en.cppreference.com/w/cpp/filesystem/path/lexically_normal Solution: Resolve "." and ".." in `vim.fs.normalize`. Before: "~/foo/bar/../baz/./" => "~/foo/bar/../baz/." After: "~/foo/bar/../baz/./" => "~/foo/baz"
2024-03-30fix: support UNC paths in vim.fs.normalizedundargoc1
Closes https://github.com/neovim/neovim/issues/27068.
2024-03-29fix(fs): allow backslash characters in unix pathsJames Trew1
Backslashes are valid characters in unix style paths. Fix the conversion of backslashes to forward slashes in several `vim.fs` functions when not on Windows. On Windows, backslashes will still be converted to forward slashes.
2024-03-06fix(fs): use generics for better typingaltermo1
2024-03-06refactor(types): more fixesLewis Russell1
2024-03-01docs: improve/add documentation of Lua typesLewis Russell1
- Added `@inlinedoc` so single use Lua types can be inlined into the functions docs. E.g. ```lua --- @class myopts --- @inlinedoc --- --- Documentation for some field --- @field somefield integer --- @param opts myOpts function foo(opts) end ``` Will be rendered as ``` foo(opts) Parameters: - {opts} (table) Object with the fields: - somefield (integer) Documentation for some field ``` - Marked many classes with with `@nodoc` or `(private)`. We can eventually introduce these when we want to.
2024-02-27feat(docs): replace lua2dox.luaLewis Russell1
Problem: The documentation flow (`gen_vimdoc.py`) has several issues: - it's not very versatile - depends on doxygen - doesn't work well with Lua code as it requires an awkward filter script to convert it into pseudo-C. - The intermediate XML files and filters makes it too much like a rube goldberg machine. Solution: Re-implement the flow using Lua, LPEG and treesitter. - `gen_vimdoc.py` is now replaced with `gen_vimdoc.lua` and replicates a portion of the logic. - `lua2dox.lua` is gone! - No more XML files. - Doxygen is now longer used and instead we now use: - LPEG for comment parsing (see `scripts/luacats_grammar.lua` and `scripts/cdoc_grammar.lua`). - LPEG for C parsing (see `scripts/cdoc_parser.lua`) - Lua patterns for Lua parsing (see `scripts/luacats_parser.lua`). - Treesitter for Markdown parsing (see `scripts/text_utils.lua`). - The generated `runtime/doc/*.mpack` files have been removed. - `scripts/gen_eval_files.lua` now instead uses `scripts/cdoc_parser.lua` directly. - Text wrapping is implemented in `scripts/text_utils.lua` and appears to produce more consistent results (the main contributer to the diff of this change).
2023-09-14docs: replace <pre> with ``` (#25136)Gregory Anders1
2023-08-08fix(lua): vim.fs typing (#24608)Lewis Russell1
2023-07-19docs(lua): clarify fs.find() documentation #24394futsuuu1
2023-07-18docs(lua): more improvements (#24387)Lewis Russell1
* docs(lua): teach lua2dox how to table * docs(lua): teach gen_vimdoc.py about local functions No more need to mark local functions with @private * docs(lua): mention @nodoc and @meta in dev-lua-doc * fixup! Co-authored-by: Justin M. Keyes <justinkz@gmail.com> --------- Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2023-07-18fix(fs.lua): normalize slash truncation (#23753)Mike1
Preserve last slash in windows' root drive directories
2023-07-10fix(lint): lint warnings #24226Raphael1