Commit Graph

69 Commits

Author SHA1 Message Date
Barrett Ruth
755abbc8d5 fix(zip): only refuse a cwd unzip on Windows 2026-08-03 15:35:30 -05:00
Barrett Ruth
886a270e7f refactor(zip)!: address entries with zip:// paths
Problem:
`zipfile://{archive}::{entry}` is ambiguous: `::` is legal in both an
archive path and an entry path, so the separator cannot be identified.
Splitting at the last `::` reads archives correctly but breaks entries
that contain it, and the plugin then emits buffer names it cannot read
back.

Solution:
Address entries as `zip://{archive}/{entry}`, joining the two paths.
Resolve the split by walking components: the first one that is a regular
file is the archive, because a regular file cannot have children on disk.
Entry paths may then contain any character, and no escaping is needed.

zipPlugin.vim keeps its own scheme, so the Java ftplugin emits whichever
form matches the active plugin until the legacy package is removed.
2026-08-03 15:22:25 -05:00
Barrett Ruth
8787b8b9b6 fix(zip): do not run unzip from the current directory
Problem:
Windows searches the current directory before $PATH, so opening an archive
in a directory that also contains an `unzip` executable runs that one. The
legacy plugin refused this; the port dropped the check.

Solution:
Refuse to run `unzip` when it resolves to the current directory.
2026-08-03 15:22:25 -05:00
Barrett Ruth
1e757a2feb fix(zip): do not warn when zip.lua is disabled 2026-08-03 11:53:20 -05:00
Barrett Ruth
d03b4cfb7a feat(zip): checkhealth and encrypted entries
Problem:
There is no health check. Encrypted entries cannot be read at all, since
Info-ZIP takes a password only from a terminal and `-P` would expose it
in the process arguments.

Solution:
Add `:checkhealth nvim.zip`, reporting the backend and which
implementation is handling archives. Prompt for the password on a pty,
extracting to a file so the entry's bytes stay off the terminal. Report
Info-ZIP's exit code rather than inferring a cause, so an archive using
AES is not reported as a failed decryption.
2026-08-03 11:53:20 -05:00
Justin M. Keyes
98d767cd53 docs: func/expr options, misc #41102 2026-08-01 17:48:32 -04:00
Barrett Ruth
3fdb74748a fix: review 2026-07-29 14:56:26 -05:00
Barrett Ruth
36204b4323 feat(zip): extract archive members 2026-07-29 14:32:37 -05:00
Barrett Ruth
f82cf8fd59 fix(zip): list a valid empty archive as empty 2026-07-29 14:32:36 -05:00
Barrett Ruth
e63cf57106 fix(zip): keep a leading dash from becoming a backend option 2026-07-29 14:32:36 -05:00
Barrett Ruth
e29af9c32f refactor(zip)!: builtin zip.lua plugin #40846
Problem:
The bundled `zip` plugin is implemented in Vimscript, making it harder to
maintain and build on with Nvim's Lua runtime infrastructure.

Solution:
Add an opt-out `zip.lua` browser backed by `nvim.dir`, and disable the legacy
Vimscript implementation by moving it to `pack/dist/opt/zip/`. Load it with
`:packadd zip`.
2026-07-29 12:54:43 -04:00
Barrett Ruth
0d36e61d70 fix(dir): "-" on a non-file buffer opens a bogus path #41034 2026-07-28 13:37:06 -04:00
Justin M. Keyes
6539bd6602 Merge #40910 from barrettruth/fix/dir-literal-env-paths 2026-07-26 06:11:01 -04:00
Barrett Ruth
1594ca2368 fix(dir): preserve environment variables in paths 2026-07-25 18:02:55 -05:00
Barrett Ruth
ce9cc43f23 fix(dir): open CWD from unnamed buffer with - mapping #40926 2026-07-24 06:45:13 -04:00
Barrett Ruth
ada2007453 feat(dir): provider framework #40738
Problem:
The core behaviors of `nvim.dir` cannot be reused by consumers
such as the archive plugin, ssh browser, etc.

Solution:
- Define a basic "provider" shape.
- Extract the filesystem provider.
2026-07-22 13:21:39 -04:00
Barrett Ruth
9edf57e665 fix(dir): custom 3P directory-browser #40725
Problem:
Third-party directory browsers do not have a documented way to take over local
directory buffers from nvim.dir.

Solution:
Document deleting the nvim.dir augroup and handling FileType directory as the
after-startup handoff, and avoid installing the built-in buffer-local "-" mapping
when "-" is already mapped.
2026-07-16 14:26:01 -04:00
Justin M. Keyes
9982f6e0e4 refactor(api): omit optional param 2026-07-13 19:44:15 +02:00
Barrett Ruth
3b88a8a65d fix(filetype): ensure directory bufname ends w/ slash sep #40552
Problem:
`vim.filetype.match()` needs a cheap way to recognize directory buffers
without doing filesystem stat work.

Solution:
Ensure full buffer names for directories end in a trailing slash. Now
directory buffers can proceed through the normal 'filetype' path.

Note side-effects: session and ShaDa buffer-list restore behavior must
be compatible, so those + corresponding tests must be updated.
2026-07-10 12:40:13 -04:00
Barrett Ruth
7dccbfed10 fix(dir): select origin on parent navigation #40658 2026-07-09 17:47:56 -04:00
Barrett Ruth
a54a7f6a78 fix(dir): preserve alternate buffer #40659 2026-07-09 15:41:09 -04:00
Justin M. Keyes
1035a9fb5d refactor(dir): use vim.fs.dir() 2026-07-01 13:01:02 +02:00
Barrett Ruth
784ab9edfb fix(dir): reload listing on :edit #40496 2026-06-30 14:19:53 -04:00
Barrett Ruth
1b959ba485 fix(dir): remove loaded plugin guard #40489 2026-06-30 07:54:36 -04:00
Barrett Ruth
9202e2c80c fix(dir): respect directory buffer lifetime #40453
Problem:
dir.lua leaves previously-navigated directory buffers around.
This is fine by default, but users need a simple way to opt out.

Solution:
1. Respect `set hidden` (via `'bufhidden'`) as one way to make
   previously-navigated dir buffers from showing up.
2. Document a one-liner to hide these buffers
2026-06-27 14:08:28 -04:00
Barrett Ruth
bf917a503a feat(runtime): replace netrw with a very small script #39723
Problem:
`:edit <dir>` and `nvim <dir>` currently rely on netrw to show local directory
contents.

Solution:
- Provide `filetype=directory`.
- Introduce dir.lua, a small plugin that provides directory listing, opening
  items, parent navigation, and refresh.
- `netrw` remains available for `:Explore`, remote paths, archives, and file
  operations. To continue 

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-06-25 17:31:18 -04:00
Justin M. Keyes
4ed844be59 fix(autoread): 'autoread' error if file goes missing #40276
Problem:
'autoread' error if file goes missing.

    E211: File "runtime/lua/nvim/autoread.lua" no longer available
    vim.schedule callback: /usr/local/share/nvim/runtime/lua/nvim/autoread.lua:146:
    Vim:E211: File "test/functional/options/autoread_spec.lua" no longer available
    stack traceback:
    [C]: in function 'checktime'
    /usr/local/share/nvim/runtime/lua/nvim/autoread.lua:146:
    in function </usr/local/share/nvim/runtime/lua/nvim/autoread.lua:138>

Solution:
Ignore E211 thrown by `:checktime`.
2026-06-15 13:14:46 -04:00
Justin M. Keyes
d34cfe1cb8 fix(autoread): handle autocmd errors
Problem:
Any random ftplugin or other autocmd, can throw an error when
`:checktime` reloads a buffer. This causes a trace which makes it look
like an issue with `autoread.lua`.

    vim.schedule callback: …/runtime/lua/nvim/autoread.lua:146:
    FileType Autocommands for "*"..function <SNR>1_LoadFTPlugin[20] ..script
    …/runtime/ftplugin/help.lua: Vim(runtime):E5113: Lua chunk:
    …/runtime/lua/vim/treesitter.lua:216: Index out of bounds
    stack traceback:
    [C]: in function 'nvim_buf_get_text'
    …/runtime/lua/vim/treesitter.lua:216: in function 'get_node_text'
    …/runtime/lua/vim/treesitter/query.lua:558: in function 'handler'
    …/runtime/lua/vim/treesitter/query.lua:843: in function '_match_predicates'
    …/runtime/lua/vim/treesitter/query.lua:1082: in function '(for generator)'
    …/runtime/ftplugin/help.lua:91: in function 'runnables'
    …/runtime/ftplugin/help.lua:124: in main chunk
    [C]: in function 'checktime'
    …/runtime/lua/nvim/autoread.lua:146: in function <…/runtime/lua/nvim/autoread.lua:138>

Solution:
Use pcall() and surface the error via nvim_echo.
2026-06-14 22:00:38 +02:00
Justin M. Keyes
2abb9785d3 feat(autoread): surface autoread activity via 'busy' flag
Problem:
Old 'autoread' only did `:checktime` on focus-change and shell (":!")
commands, and only for non-hidden buffers. Since 'autoread' is now
driven by OS filewatcher events, buffers are updated much more eagerly.
This should be surfaced to the user somehow, either via a carefully
placed notification, or a minimal UI indicator.

A "notification" would be noisy, unless it is conditional on specific
circumstances (e.g. when "many" buffers are updated).

Solution:
Use the existing 'busy' buffer-local option as a subtle hint about
activity.
2026-06-14 22:00:38 +02:00
Justin M. Keyes
aeea633deb test(autoread): make "debounce" test actually valid 2026-06-13 20:55:49 +02:00
Oleksandr Chekhovskyi
400f247397 feat(autoread): use filewatchers for OS-driven change detection #37971
Problem:
The 'autoread' option only checks for file changes reactively — on
FocusGained, :checktime, CmdlineEnter, etc. — by polling timestamps.
External changes are not detected until the user interacts with Neovim.

Solution:
Add a core module (runtime/lua/nvim/autoread.lua) enabled from
runtime/plugin/autoread.lua that watches each buffer's file using
vim._watch.watch() (libuv fs_event). On change detection it calls
:checktime, which invokes the existing buf_check_timestamp() logic
for reload/prompt handling. Watchers are managed via autocmds tied
to buffer lifecycle events and respect the 'autoread' option (global
and buffer-local).
2026-06-12 18:25:15 -04:00
Justin M. Keyes
9aa4608401 refactor: introduce nvim_on internally #39883
Problem:
`nvim_create_autocmd` is too verbose and its `callback` requires extra
"nesting".

Solution:
Introduce `nvim_on`. Start using it internally. Then we can get a feel
for how it should look before making it public.
2026-05-20 17:33:01 -04:00
Olivia Kinnear
ea8f1463dd fix(lua): fields of nvim.spellfile.Opts are optional #39902 2026-05-20 02:47:35 -04:00
Evgeni Chasnovski
db0682fe50 feat(ui): vim.ui.input(opts.scope) #39570
Problem: There is no way for a `vim.ui.input` caller to indicate for
  which scope the input is. As in "This input is for something at cursor
  scope". This information can be useful for `vim.ui.input`
  implementation to tweak its behavior and presentation:
  - Show different floating window depending on the scope. For example:
    - Near cursor for "cursor" scope.
    - At line start for "line" scope.
    - In window corner for "buffer" and "window" scopes.
    - In whole editor corner for "tabpage", "editor", "project" scopes.
  - Navigate through history only for inputs with the same scope.

Solution: Document new `opts.scope` for `vim.ui.input`. Use it in the
  codebase.
2026-05-17 11:34:06 -04:00
Nathan Zeng
dbdd73e846 refactor(tutor): use inline comments instead of json file #39714
Problem: Expected text for interactive marks is in a separate json file
from the tutor file. When the tutor file is updated, line numbers
(potentially many) have to be updated in the json file. This is a
burden for maintenance and automatic testing.

Solution: Put the expected text inline in the tutor file, marked
with `[[]]`. Parse and remove the comments before opening the tutor
file so extmarks can be applied.
2026-05-13 07:31:17 -04:00
Yi Ming
f0f6753f30 refactor(matchparen): parameterize win instead of always using the current
AI-assisted: Codex
2026-05-08 17:17:03 +08:00
Yi Ming
523e679ead refactor(matchparen): rewrite matchparen plugin in Lua
AI-assisted: Codex
2026-05-08 17:17:03 +08:00
Justin M. Keyes
017d8aa298 refactor: rename _ensure_integer => _assert_integer 2026-03-13 20:32:01 +01:00
Lewis Russell
ce1154048b refactor: integer functions, optimize asserts #34112
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-03-12 11:04:05 -04:00
Yochem van Rosmalen
f7041625f1 refactor(lua): use vim.fs instead of fnamemodify
Although powerful -- especially with chained modifiers --, the
readability (and therefore maintainability) of `fnamemodify()` and its
modifiers is often worse than a function name, giving less context and
having to rely on `:h filename-modifiers`. However, it is used plenty in
the Lua stdlib:

- 16x for the basename: `fnamemodify(path, ':t')`
- 7x for the parents: `fnamemodify(path, ':h')`
- 7x for the stem (filename w/o extension): `fnamemodify(path, ':r')`
- 6x for the absolute path: `fnamemodify(path, ':p')`
- 2x for the suffix: `fnamemodify(path, ':e')`
- 2x relative to the home directory: `fnamemodify(path, ':~')`
- 1x relative to the cwd: `fnamemodify(path, ':.')`

The `fs` module in the stdlib provides a cleaner interface for most of
these path operations: `vim.fs.basename` instead of `':t'`,
`vim.fs.dirname` instead of `':h'`, `vim.fs.abspath` instead of `':p'`.
This commit refactors the runtime to use these instead of fnamemodify.

Not all fnamemodify calls are removed; some have intrinsic differences
in behavior with the `vim.fs` replacement or do not yet have a
replacement in the Lua module, i.e. `:~`, `:.`, `:e` and `:r`.
2026-01-28 10:57:39 +00:00
Olivia Kinnear
4e1644d4d3 feat(spell): opt-out of confirm when downloading spellfiles #36836 2025-12-06 17:20:02 -05:00
Yochem van Rosmalen
9bdb011a50 refactor(spellfile): config() interface, docs #36481
Problem:
- Exposing the raw config as table is a pattern not seen anywhere else
  in the Nvim codebase.
- Old spellfile.vim docs still available, no new documentation

Solution:
- Exposing a `config()` function that both acts as "getter" and "setter"
  is a much more common idiom (e.g. vim.lsp, vim.diagnostic).
- Add new documentation and link old docs to |spellfile.lua| instead of
  |spellfile.vim|.
2025-11-09 21:51:39 -08:00
Justin M. Keyes
4d501c93bb refactor(spell): cleanup
- prefer `stdpath(data)/site/spell` instead of looking for random dirs in 'runtimepath'.
- drop unused functions `choose_directory`, `setup`, etc.
2025-10-26 01:28:37 +02:00
Tom Ampuero
7c5ff99e8a refactor(spell): migrate to Lua, drop netrw dependency
Problem:
Spell file downloads relied on Vimscript and netrw (:Nread). If netrw is
disabled, downloads fail.

Solution:
Port the logic to Lua as `nvim.spellfile` and wire it via a Lua plugin that
handles `SpellFileMissing`. Use `vim.net.request()` with a timeout for HTTP,
prompt via `vim.fn.input` and report via `vim.notify`.

Closes #7189
2025-10-26 00:33:41 +02:00
Phạm Bình An
f2691199fa fix(tutor): use invalidate field in nvim_buf_set_extmark() #34989
Problem:
If users delete a line containing extmark, it will move to the next
line, which could highlight the next line in an unwanted way.

Solution:
- Use `invalidate` field in `nvim_buf_set_extmark()` to prevent the
extmark from moving.
- Also save from "priority" hacking, since we can check if the extmark
  is valid in `nvim_buf_get_extmarks()` now.
2025-07-18 13:02:09 -07:00
brianhuster
1255a8d88d refactor(tutor): reimplement interactive marks as extmark in Lua
Problem:
From https://matrix.to/#/!cylwlNXSwagQmZSkzs:matrix.org/$Ofj-TFIsEMbp0O9OhE8xuZSNi-nhRLtZTOgs6JRLNrs?via=matrix.org&via=gitter.im&via=mozilla.org

In lesson 2.6, users are asked to remove the second, forth and fifth
lines with `dd` command, then they are asked to undo twice to make the
text go back to original state. But after that, the mark ✗ appears
again, which confuses the user because they think they do something
wrong. This is a limitation with the current implementation, which is
based on line number only.

Solution:
Reimplement interactive marks as extmarks in Lua. This also make the
feature less fragile, as users can remove, add some arbitrary lines
without breaking the interactive marks.

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2025-07-18 10:04:20 +07:00
dundargoc
0f4f7d32ce refactor!: remove nvim and provider module for checkhealth
The namespacing for healthchecks for neovim modules is inconsistent and
confusing. The completion for `:checkhealth` with `--clean` gives

```
nvim
provider.clipboard
provider.node
provider.perl
provider.python
provider.ruby
vim.lsp
vim.treesitter
```

There are now three top-level module names for nvim: `nvim`, `provider`
and `vim` with no signs of stopping. The `nvim` name is especially
confusing as it does not contain all neovim checkhealths, which makes it
almost a decoy healthcheck.

The confusion only worsens if you add plugins to the mix:

```
lazy
mason
nvim
nvim-treesitter
provider.clipboard
provider.node
provider.perl
provider.python
provider.ruby
telescope
vim.lsp
vim.treesitter
```

Another problem with the current approach is that it's not easy to run
nvim-only healthchecks since they don't share the same namespace. The
current approach would be to run `:che nvim vim.* provider.*` and would
also require the user to know these are the neovim modules.

Instead, use this alternative structure:

```
vim.health
vim.lsp
vim.provider.clipboard
vim.provider.node
vim.provider.perl
vim.provider.python
vim.provider.ruby
vim.treesitter
```

and

```
lazy
mason
nvim-treesitter
telescope
vim.health
vim.lsp
vim.provider.clipboard
vim.provider.node
vim.provider.perl
vim.provider.python
vim.provider.ruby
vim.treesitter
```

Now, the entries are properly sorted and running nvim-only healthchecks
requires running only `:che vim.*`.
2024-05-19 11:46:34 +02:00
Michael
96d0c709b6 fix(healthcheck): expand vimrc variable (#28379) 2024-04-17 14:31:13 +08:00
Luna Saphie Mittelbach
20b38677c2 feat(defaults): use ripgrep (rg) for 'grepprg' if available 2024-04-16 19:21:02 +02:00
Barrett Ruth
f6dcc464f2 fix(health): check unmatching python_glob as empty table (#28215) 2024-04-07 11:50:45 +08:00