summaryrefslogtreecommitdiffstatshomepage
path: root/runtime/lua/vim/_core
AgeCommit message (Collapse)AuthorFiles
2026-04-24feat(tui): restore 'ttyfast' to control tty requests #38699Kyle1
Problem: When running nvim on a remote machine over SSH, if there is high ping, then bg detection may not complete in time. This results in a warning every time nvim is started. #38648 Solution: Restore 'ttyfast' option and allow it to control whether or not bg detection is performed. Because this is during startup and before any user config or commands, we use the environment variable `NVIM_NOTTYFAST` to allow disabling `ttyfast` during initialization.
2026-04-24feat(api): nvim_echo(percent=nil) means "unknown" progress #39029Peter Cardenas1
Problem: No way to signal "unknown" or "indeterminate" progress percentage. Solution: Treat percent=nil as "indeterminate" percent.
2026-04-23feat(excmd): add :uptime command #39331Olivia Kinnear2
Problem Nvim marks its v:starttime, but there is no user-friendly way to get Nvim's uptime. Solution Add :uptime (based loosely on uptime(1)).
2026-04-22feat(treesitter): expand selection to sibling node #38938altermo1
Problem: Can't expand treesitter-incremental-selection to the next and previous sibling nodes. Solution: Pressing `]N` in visual mode will expand the selection to the next sibling node, and `[N` will do the same with the previous node.
2026-04-22feat(:restart): v:starttime, v:exitreason #39282Justin M. Keyes1
Problem: - The `ZR` feature makes it more obvious that we need some sort of flag so that an `ExitPre` / `QuitPre` / `VimLeave` handler can handle restarts differently than a normal exit. For example, it's common that users want `:mksession` on restart, but perhaps not on a normal exit. - Nvim has no way to report its "uptime". Solution: - Introduce `v:starttime` - Introduce `v:exitreason`
2026-04-22perf(lsp): clear table by table.clear() #39222Yi Ming1
benchmark: https://gist.github.com/ofseed/6224529d77c016c36f7ab2f977059848 local rounds = tonumber(arg[1]) or 1000 local count = tonumber(arg[2]) or 1000 -- Load the table.clear function. local clear = require("table.clear") local function fill(t, n) for i = 1, n do t[i] = i end end local function bench_reassign(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} collectgarbage("collect") fill(t, n_items) end return os.clock() - start end local function bench_reassign_no_gc(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} fill(t, n_items) end return os.clock() - start end local function bench_clear(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do clear(t) fill(t, n_items) end return os.clock() - start end -- Warm up LuaJIT before the real benchmark. do local t = {} for _ = 1, 2000 do clear(t) fill(t, count) end end collectgarbage("collect") local reassign_time = bench_reassign(rounds, count) collectgarbage("collect") local reassign_no_gc_time = bench_reassign_no_gc(rounds, count) collectgarbage("collect") local clear_time = bench_clear(rounds, count) print(string.format("rounds=%d count=%d", rounds, count)) print(string.format("t = {} + GC : %.6f s", reassign_time)) print(string.format("t = {} : %.6f s", reassign_no_gc_time)) print(string.format("table.clear : %.6f s", clear_time)) print(string.format("vs + GC : %.2fx", reassign_time / clear_time)) print(string.format("vs no GC : %.2fx", reassign_no_gc_time / clear_time)) benchmark result: rounds=1000 count=1000 t = {} + GC : 0.022469 s t = {} : 0.002570 s table.clear : 0.000387 s vs + GC : 58.06x vs no GC : 6.64x `count` is how many items the table has, and `round` is how many rounds we fill the table, clear, and then refill it. `table = {}` is clear the table by resigning a new empty one, because this script does not run persistently like nvim so GC is not triggered, so I added another extreme control group that manually triggers GC.
2026-04-22fix(:restart): avoid ERR/WRN logging on Windows with --listen (#39287)zeertzjq1
Problem: :restart leads to ERR/WRN logging on Windows with --listen. Solution: Add a log_level flag to vim._with() and use it to suppress logging from serverstart()/serverstop() during restart.
2026-04-21fix(:restart): reuse --listen addr on Windows #38539Sanzhar Kuandyk1
Problem: On Windows, :restart cannot immediately reuse the canonical --listen address because named pipe release is asynchronous. Solution: Start the new Nvim server on a temporary address; in the new Nvim, retry serverstart() with the original ("canonical") address until it succeeds.
2026-04-21feat(normal): normal-mode ZR does :restartJustin M. Keyes1
Make it a normal-mode command instead of a default mapping.
2026-04-21feat(defaults): map ZR to restartMike J. McGuirk1
Problem: No default mapping for :restart. Solution: Map to ZR in defaults. Closes: https://github.com/neovim/neovim/issues/38942
2026-04-20fix(ui2): don't dismiss expanded messages for non-typed key #39247luukvbaal2
Problem: Invalid check for non-typed key to dismiss expanded cmdline. Unable to delay the timer that removes a message from the msg window. Solution: Check for empty string instead of nil to determine whether a key is typed. Restart the timer if it expires while the user is in the msg window. Allow entering the msg window with a mouse click.
2026-04-20fix(ui2): ensure msg window is visible after closing tabLuuk van Baal1
Problem: After closing a tabpage while the msg window is showing a message, it is hidden while the msg window still contains a message. Solution: Unhide the msg window after entering a tabpage and it still contains a message. Co-authored-by: Linykq <yukunlin590@gmail.com>
2026-04-20Merge #39194 from justinmk/luavimfnJustin M. Keyes1
2026-04-19feat(options): add 'winpinned' to pin a window #39157luukvbaal1
Problem: - Unable to "pin" a window to prevent closing without specifically being targeted. - :fclose closes hidden windows (even before visible windows). Solution: - Add 'winpinned' window-local option. When set, window is skipped by :fclose and :only. Pin the ui2 cmdline window (which should always be visible), so that it is not closed by :only/fclose. - Skip over hidden (and pinned) windows with :fclose. Co-authored-by: glepnir <glephunter@gmail.com>
2026-04-20refactor(excmd): migrate ex_terminal to LuaJustin M. Keyes1
2026-04-19feat(excmd): add EXX error codes for :lsp, :log #39135Olivia Kinnear1
Also remove the `--add-comments` flag from `xgettext` because it dumped a bunch of comments from Lua files into the `.pot` files.
2026-04-18docs: misc #39045Justin M. Keyes1
2026-04-18fix(lua): make `vim._with()` work with `buf=0` and `win=0` context #39151Evgeni Chasnovski1
Problem: Using `buf=0`/`win=0` context in `vim._with` should be equivalent to using explicit buffer/window identifier respectively. Solution: Explicitly adjust context in case of `buf=0` or `win=0`.
2026-04-18refactor(vimfn): full-Lua impl of vim.fn.environ()Justin M. Keyes1
2026-04-18feat(vimfn): use Lua for more excmds/vimfnsJustin M. Keyes3
Problem: Too much boilerplate needed to use Lua to impl an excmd or f_xx function. Solution: - Add `nlua_call_vimfn` which takes the args typval, executes Lua, and returns a typval. - refactor(excmd): lua impl for :log, :lsp
2026-04-17perf(vim.fn): call Lua-implemented vim.fn.xx() directly #39166Justin M. Keyes1
Problem: - Builtin "Vimscript" functions (f_xx) are mostly implemented in C. Partly that's because there is some boilerplate required to call out to Lua. - Calls to `vim.fn.foo()` always marshall over the Lua <=> Vimscript ("typval") bridge, even if `fn.foo()` is implemented entirely in Lua: ``` Lua => typval => Object => Lua => Object => typval => Lua. ``` Solution: Functions declared in eval.lua with `func_lua` are implemented in entirely in Lua (`_core/vimfn.lua`). - `gen_eval.lua` wires `func_lua` entries to `lua_wrapper`, which handles the typval conversion for Vimscript callers (slow path). - `nlua_call()` detects `func_lua` functions and calls the Lua implementation directly. This eliminates all conversion overhead for Lua callers (fast path). - Validate at build-time that `func`, `func_float`, and `func_lua` are mutually exclusive. - Migrate `hostname()` as a toy example, to show the idea.
2026-04-16fix(ui2): dialog paging is inconsistent #39128luukvbaal1
Problem: - Paging keys in the dialog window consume input when the user may not expect it. The dismissable title hint intended to mitigate that results in having to press Escape twice to abandon the prompt. - Mimicked "msgsep" float border is taking up unnecessary space when window takes up the entire screen. Solution: - Use (conventional, albeit less convenient) keys intended for scrolling to page the dialog window: <(Mousewheel/Page)Up/Down>, <Home/End>. - Only set the float top border when separation is actually necessary, i.e. window does not reach the first row.
2026-04-16test: lint naming conventions #39117Justin M. Keyes1
Problem: Naming conventions are not automatically checked. Solution: Add a check to the doc generator. Eventually we should extract this somehow, but that will require refactoring the doc generator... Note: this also checks non-public functions, basically anything that passes through `gen_eval_files.lua` and `gen_vimdoc.lua`. And that's a good thing.
2026-04-15refactor: update usages of deprecated "buffer" param #39089Justin M. Keyes1
2026-04-15test: replace busted with local harnessLewis Russell1
Replace the busted-based Lua test runner with a repo-local harness. The new harness runs spec files directly under `nvim -ll`, ships its own reporter and lightweight `luassert` shim, and keeps the helper/preload flow used by the functional and unit test suites. Keep the file boundary model shallow and busted-like by restoring `_G`, `package.loaded`, `package.preload`, `arg`, and the process environment between files, without carrying extra reset APIs or custom assertion machinery. Update the build and test entrypoints to use the new runner, add black-box coverage for the harness itself, and drop the bundled busted/luacheck dependency path. AI-assisted: Codex
2026-04-15fix(lua): make vim.deep_equal cycle-safeLewis Russell1
AI-assisted: Codex
2026-04-10feat(ex): add `:log` commandOlivia Kinnear2
2026-04-09fix(messages): truncate warning messages only in display (#38901)zeertzjq2
For now, add a private "_truncate" flag to nvim_echo, using a truncation method similar to showmode().
2026-04-05feat(defaults): :Open without args opens current file #38776Olivia Kinnear1
Problem: Running `:Open` on an open buffer does not run `vim.ui.open()` on that file, requiring the user to type `:Open %`. This is inconsistent with most other vim commands which accept files, which default to the current buffer's file. Solution: Default to the current file when `:Open` is used without arguments.
2026-04-05fix(ui2): update spill indicator when appending to expanded cmdline #38715luukvbaal1
Problem: When messages are appended to an already expanded cmdline, the spilled lines indicator is not updated. Solution: Remove early return for updating virtual text while cmdline is expanded, guard updating "msg" virt_text at callsite instead.
2026-04-01docs: misc #38584Justin M. Keyes1
2026-04-01fix(ui2): vim.on_key should return nil instead of false (#38668)phanium1
2026-03-31fix(ui2): flicker when entering pager from expanded cmdline #38639luukvbaal2
Problem: 'showcmd' causes flickering when pressing "g<" to enter the pager when the cmdline is expanded for messages. Initial keypress for an incomplete mapping is not giving 'showcmd' feedback while cmdline is expanded for messages (which is only dismissed upon the vim.on_key callback after 'timeoutlen'). Solution: Delay dismissing expanded cmdline when vim.on_key() callback receives "g". Place 'showcmd' "last" virtual text during expanded cmdline.
2026-03-31fix(cmdline): redraw cmdline after empty message (#38485)luukvbaal1
Problem: Cmdline is not redrawn after an empty message clears it. Remembered last drawn cursor position may be outdated but equal to the current cmdline content with UI2. Solution: Ensure cmdline is redrawn after an empty message clears it. Compare wanted cursor position with actual cursor position.
2026-03-31fix(defaults): check for TUI on non-stdio channel on startup (#38581)zeertzjq1
2026-03-30fix(ui2): allow empty argument for enable() #38605Christian Clason1
Problem: `vim._core.ui2.enable` requires passing an empty table for default options, unlike other (native) Lua API. Solution: Initialize `opts` with empty table if `nil` is passed.
2026-03-30fix(ui2): correct buffer reference in msg:start_timer() (#38600)Ayush Goyal1
Problem: Mixing "buf" and "M.bufs.msg" in M.msg:start_timer(). Cannot run `require("vim._core.ui2").enable(nil)`. Solution: Replace "M.bufs.msg" with "buf". Allow `opts == nil`. Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
2026-03-28docs: news #38464Justin M. Keyes2
2026-03-26fix(ui2): ENTER may focus pager in insert/terminal mode #38497phanium2
fix(ui2): prevent <CR> from focusing pager in insert/terminal mode Problem: <CR> in insert/terminal mode can focus pager unexpectedly. Solution: Don't enter the pager when <CR> is pressed during expanded cmdline in insert/terminal mode.
2026-03-26fix(ui2): no paging in dialog below expanded cmdline #38489luukvbaal1
Problem: When entering the cmdline below expanded messages, those messages are moved to the dialog window. The dialog window supports paging but that is unexpected in this situation where it just serves to keep (some of, exactly those that were visible before the cmdline was entered) the messages visible. Wrong highlight group for dialog "more" message. Solution: Don't create the `vim.on_key()` dialog pager callback after entering the cmdline below expanded messages. Use the MsgMore highlight group for the paging hint title.
2026-03-24fix(ui2): show messages in dialog window when entering expanded cmdline #38465luukvbaal2
Problem: - With expanded messages exceeding cfg.msg.cmd.height, entering the cmdline scrolls to the bottom and expands to the full "cmd" buffer text height. - Cursor in the pager is not always at the last message and at the bottom of the window when appending to the pager. - unreliable test: messages2_spec: "closed msg window timer removes empty lines". Solution: - Achieve separation of the cmdline and message text by moving messages to the dialog window when entering the cmdline below expanded messages. - Set cursor to start of the first message only when first entering the pager. Use `norm! zb` to position last message at the bottom of the window (which shouldn't crash anymore since 911337eb). - Increase cfg.msg.msg.timeout used in the test file.
2026-03-24docs: api, plugins, ui2Justin M. Keyes2
2026-03-23refactor: rename termcap.lua -> tty.lua #38437Justin M. Keyes1
Problem: The `termcap.lua` module is too narrowly named. We may need a place for tty-related functionality in the future. https://github.com/neovim/neovim/pull/31399#discussion_r1882598297 Solution: This isn't a public/documented interface, so just rename it.
2026-03-22docs: starting.txt new layoutJustin M. Keyes1
2026-03-21feat(lua): replace `buffer` with `buf` in vim.keymap.set/del #38360skewb1k1
The `buffer` option remains functional but is now undocumented. Providing both will raise an error. Since providing `buf` was disallowed before, there is no code that will break due to using `buffer` alongside `buf`.
2026-03-21feat(ui2): configure maximum window heights #38392luukvbaal2
Problem: - Window height is set dynamically to match the text height, making it difficult for the user to use a different height. - Cmdwin is closed to enter the pager but still taken into account for the pager position, and not restored when the pager is closed. - Dialog pager handler may unnecessarily consume <Esc>. Solution: - Add maximum height config fields for each of the UI2 windows, where a number smaller than one is a fraction of 'lines', absolute height otherwise (i.e. `cfg.msg.pager.height = 0.5`). - If the cmdwin will be closed to enter the pager, don't try to position the pager above it. Re-enter the cmdwin when the pager is closed. - Only add vim.on_key() handler for the dialog paging is actually possible.
2026-03-20docs: miscJustin M. Keyes1
2026-03-19feat(defaults): map "grx" to vim.lsp.codelens.run() #37689Yi Ming1
Problem Unlike inlay hints, code lenses are closely related to running commands; a significant number of code lenses are used to execute a command (such as running tests). Therefore, it is necessary to provide a default mapping for them. Solution Add a new default mapping "grx" (mnemonic: "eXecute", like "gx").
2026-03-19fix(ui2): wrong condition used to detect active pagerLuuk van Baal1
Problem: Entering the pager is scheduled to avoid errors while in the cmdwin. Meanwhile the current window is used as a condition to detect an active pager. Solution: Keep track of when the user is in the pager (or entered the cmdwin while the pager was open).
2026-03-19fix(ui2): move windows to current tabpageLuuk van Baal1
Problem: Windows are closed and re-opened after changing tabpage (and might be removed from the current tabpage after 094b297a). Solution: Ensure windows are on the current tabpage by moving them.