aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/main.c
Commit message (Collapse)AuthorAge
* [feat] extregistersJosh Rahm40 hours
| | | | | | | | | | | | | | | | | | | | | Implements "extended registers" Extended registers provide access to a separate namespace of registers backed by custom lua callback functions. A new special register ("~) is introduced, which prompts the user for the name of an extregistr to yank or paste from. This enables file-backed or cloud-synced or other arbitrary register behavior. One can now use: `"~file_extreg<cr>yy` to yank into the "file_extreg" register. AI-assisted: Qwen3-Coder
* fix(startup): respect --noplugin when used with --clean #42362Max Coplan4 days
| | | | | | | | | | | | | | | Problem: When starting Nvim with both `--clean` and `--noplugin` (in either order), `--noplugin` is silently ignored and built-in runtime plugins are loaded anyway. `command_line_scan()` sets `p_lpl = false` for `--noplugin`, and `--clean` sets `params.use_vimrc = "NONE"` and `params.clean = true`, which later overwrites `p_lpl` back to `true` via `p_lpl = vimrc_none ? params.clean : p_lpl`. Solution: Only reset `p_lpl = false` when `vimrc_none && !params.clean`, preserving `p_lpl = false` if `--noplugin` was passed. AI-assisted
* feat(startup): --embed --listen waits for UI if stdin is not a pipeJustin M. Keyes10 days
| | | | | | | | | | | | | | | | | | | | | | Problem: `nvim --embed --listen addr` always treats stdin as an RPC channel. If stdin is /dev/null (e.g. backgrounded over ssh), the channel closes before a UI can attach, so Nvim exits (detach=false behavior). If stdin is a tty, keystrokes are read as RPC. Solution: With `--embed --listen`, open the stdio RPC channel only if stdin is a pipe or socket. Else wait for a UI at the `--listen` address. $ nvim --embed --listen ./nvim.sock Nvim server (pid: 71984) waiting for UI, listening on: "./nvim.sock" Note: - No change when stdin is a pipe. So the test harness, TUI, and :restart all behave exactly as before. - The #29634 use-case of configuring a UI that attaches *after* startup (a second UI, or reattach) still requires #25377 (reliable UIEnter). Not affected by this change.
* refactor(ui): remove "stop" UI eventJustin M. Keyes10 days
| | | | | | | | | Problem: "stop" has been a no-op since the TUI moved out-of-process. Remote UIs only see EOF, and nothing implements it. Solution: Remove it.
* refactor(multicursor)!: drop nvim_mcursor #42156Justin M. Keyes2026-09-30
| | | | | | | | | | | | | | Problem: `nvim_mcursor` is not fully baked, and not strongly motivated, currently. The main programmatic interface for cursors is the "nvim.multicursor" extmarks namespace. Solution: Drop `nvim_mcursor`. Add an internal hook so that multicursor can react when extmarks are added to the "nvim.multicursor" namespace. TODO: If extmarks/namespaces are clumsy to work with, we should _fix that_ rather than adding wrappers.
* feat(api): add ev.win to autocmd callback args #39826glepnir2026-09-09
| | | | | | | | Problem: Autocmd callbacks currently have to rely on curwin, which may already have changed by the time they run. This is especially noticeable for WinNew, WinClosed, WinResized and WinScrolled. Solution: Track the window in the autocmd context and expose it as ev.win. Pass it explicitly for the window events that need it.
* fix(mappings): replaying a deleted Lua mapping is UBJustin M. Keyes2026-08-31
| | | | | | | | | | | | | | | | | | | | | | | | | Problem: Replaying a deleted Lua mapping, may call an arbitrary function. RHS of a Lua mapping embeds its LuaRef (`<K_LUA><ref><CR>`). The raw keys may outlive the ref (redobuff ".", CmdAtom `keys`). If the mapping is deleted, replaying it either (1) dereferences a freed registry slot, or (2) calls whatever callback reused the slot (autocmd, timer, other mapping). Solution: Assign a monotonic (never recycled) id to Lua mappings and encode the mapping keys as `<K_LUA><id><CR>`. Note: in the case of Vimscript, a deleted function raises E117, but if the function is redefined with the same name, the mapping will find it. Alternatives?: - Globally ensure `LuaRef` ids are not recycled. - Problem: could exhaust `int` in a long-lived Nvim session? Also, difficult to impl bc the "recycling" is done by `luaL_ref` itself. ref: 5ac2e47acc999472042df4f10f8f7b5ffa72ba3e
* fix(lifecycle): json_create_config leakJustin M. Keyes2026-08-18
| | | | | | | | | | | | | | | | | | | | | | | | Problem: As it turns out, when you have 17 different ways to "exit", you need to plug 17 different holes. Leak still reported by ASAN CI, even after 1eae512285e7 f238788601eb. ERROR: LeakSanitizer: detected memory leaks strbuf_init src/cjson/strbuf.c:62:22 json_create_config src/cjson/lua_cjson.c:635:5 lua_cjson_new src/cjson/lua_cjson.c:2060:5 nlua_state_add_stdlib src/nvim/lua/stdlib.c:840:3 nlua_state_init src/nvim/lua/executor.c:973:3 Analysis: `os_breakcheck()` may process a `exit_event` placed by `exit_on_closed_chan()` during shutdown. This would re-enter `preserve_exit()`, which then skips everything because it sees `really_exiting=true`. Solution: Set `exiting` in `preserve_exit()`, not only in `getout()`.
* fix(lifecycle): ignore signals during os_exitJustin M. Keyes2026-08-18
| | | | | | | | | | | | | | | | | | Problem: SIGTERM received during `os_exit()` can cause it to "nest": os_exit src/nvim/main.c:720 preserve_exit src/nvim/main.c:910 deadly_signal src/nvim/os/signal.c:205 on_signal src/nvim/os/signal.c:240 signal_event src/nvim/event/signal.c:45 multiqueue_process_events src/nvim/event/multiqueue.c:159 event_teardown src/nvim/main.c:178 os_exit src/nvim/main.c:720 Solution: Call `signal_reject_deadly()` at the start of `os_exit()` like `preserve_exit()` already does.
* refactor(path): pathcmp() #41035tao2026-08-07
| | | | | | | | | | | | | | | | | | | | | | Problem: Redudant code Solution: Add `path_fold_char()` to normalize path sep. Refactor `pathcmp()` and `path_fnamencmp()` into `path_cmp`. | feature | pathcmp | path_fnamencmp | path_cmp(now) | | ------------------------ | -------------- | -------------- | ------------- | | case folding | `mb_toupper()` | `utf_fold()` | `utf_fold()` | | consults fileignorecase | ✅ | ✅ | `ic` param | | `maxlen` | ✅ | ✅ | ✅ | | `/` == `\` | ✅ | ✅ | ✅ | | MSWIN drive letter | ❌ | ✅ | ✅ | | sep affects sorting | ✅ | ❌ | ✅ | | ignores a trailing slash | ✅ | ❌ | ✅ | Refactor `path_fnamecmp` and `path_full_compare` into `path_equal`, with flags controlling "no filesystem" comparison (i.e. `path_cmp`), env variables expansion, absolute path resolution and filesystem access.
* refactor(options): drop OptVal, use ObjectJustin M. Keyes2026-07-29
| | | | | | | | | | | | | Problem: The object subsystem has an intermediate representation for no real reason. Besides the code cost, this also adds an extra (api <=> OptVal) conversion step, which is a (small) perf cost. Solution: We already have `Object`, so use it instead. - drop `OptVal`, `OptValData`, `OptValType`, and related boilerplate. - add `kObjectTypeUnset`.
* feat(exmode): "1q:", :exmode #41010Justin M. Keyes2026-07-27
| | | | | | | | | Problem: Want `gQ` for _le multicursor_. Solution: - Don't use `gQ` for exmode. - Introduce `:exmode`. - Introduce `[count]q:` as an alias to `:exmode`.
* refactor(exmode): Ex-mode as cmdwin + Lua #40991Justin M. Keyes2026-07-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: POSIX-compatible Ex-mode requires special-cases all over the codebase to match various quirks that don't actually matter to users. - The main utility of *interactive* Ex-mode is its REPL behavior, and that can be achieved with `cmdwin`, which also gains extra UX benefits. - The main utility of *non-interactive* `nvim -es` is for shell scripting, where Ex-mode quirks are mostly unhelpful (e.g. the "Entering Ex mode" message). Solution: - Reimplement *interactive* Ex-mode as a "persistent, insert-mode cmdwin" in Lua. - "nvim -e/-E" is simply an alias to "gQ". - Reframe *non-interactive* Ex-mode (`nvim -es`) as "script mode". - Drop POSIX Ex-mode quirks. Improvements: - "nvim -V1 -es" output ends with a final newline! - "nvim -V1 -es" no longer shows the "Entering Ex mode" msg. (This was pointless noise, unwanted for scripting purposes.) - stdin is no longer typeahead. Scripts (":lua io.read()") can read stdin as data. - Empty line is a no-op: a stray blank line no longer moves the cursor (deviates from POSIX ex "+1"), no longer exits 1 at EOF (E501). Preserved behavior: - cursor starts at "$" - mode()=="cv" (for non-interactive) - multiline commands (:append/:function/heredoc pull continuation lines) - bare-range print - :print=>stdout - -V1=>stderr - CRLF input - continue-after-error and exit codes Dropped (regressed) POSIX behavior (non-interactive): - Event loop only ticks while/between commands, not while blocked waiting for a stdin line. - ":g/pat/visual...Q" - input()/getchar()/":s/x/y/c" no longer consume stdin lines as answers: Nvim stops at end-of-input, skipping the rest of the script, exit 0. Use ":lua io.read()" instead. - If users care about this they should use interactive Ex-mode (`gQ`). - ":@r" stops at end of the register instead of continuing to read cmdline input from stdin.
* fix(path): normalize separators (slashes) #39155tao2026-07-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Continue separators normalization, and try to keep it at the nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx` Solution: some key changes - normalize `$HOME-windows` - normalize entry points of changing directory - `nvim_set_current_dir()`, `chdir()` - normalize the named pipe - `--listen` arg, `--server` arg, `:restart` - `serverstart()`, `sockconnect()`, `serverstop()` - make `expand()` respect 'shellslash' again - clean up `did_set_shellslash` - replace `forward_slash` with `TO_SLASH` - remove obsolete `TMP_PATHSEPSTR` - remove `slash_adjust` in `do_autocmd_dirchanged`? - make `fnamemodify()` always return `/` (except when substituting separators via `:s`, `:gs` ?) Note: - these funcs still apply `slash_adjust` on return, as before: `:pwd`, `chdir()`, `exepath()`, `getcwd()` - these funcs alwarys return `/`, unlike before the normalization PRs - `getcompletion()`, `finddir()`, `findfile()` Also - clean up code, comments, formatting and tests - move `TO_SLASH` from `f_chdir` to `changedir_func` - move `TO_SLASH` from `f_bufadd` to `buflist_new` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(startup): respect enter for windows created in startup scripts #37287glepnir2026-07-12
| | | | | | | | | Problem: When a split window is created from the init script using nvim_open_win() with enter=false, the current window focus is not preserved. The cursor incorrectly moves into the newly created split during startup. Solution: Save curwin before the iteration loop in create_windows(), and restore it after the loop. also update edit_buffers() to use curwin instead of firstwin.
* refactor(input): rename getchar.c => input.c #40698Justin M. Keyes2026-07-12
| | | | | | | | | | | | Problem: `getchar.c` is a quirky name and doesn't align with our existing `os/input.c` and `tui/input.c` modules, which encompass the same topic at different layers. Solution: Rename `getchar.c` => `input.c` for discoverability. Introduce `dialog.c` for functionality related to showing confirm prompts, dialogs, etc.
* refactor: unify context-switching conceptsJustin M. Keyes2026-07-10
|
* refactor(lua): rename nlua_call_typvalJustin M. Keyes2026-07-06
|
* refactor(os): deduplicate console/fd boilerplate #40509Justin M. Keyes2026-06-30
| | | | | | | | | Problem: Scattered, redundant boilerplate for Windows console/fd plumbing. Solution: - Add os_dup_cloexec() - Add os_reattach_console_stdio(). - Use os_open_conin_fd().
* feat(cmdwin): implement cmdwin as a normal buf+winJustin M. Keyes2026-06-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: cmdwin (the `:q` cmdline buffer) has various limitations which require special-casing all over the codebase. Besides complicating the code, it also breaks async plugins if they try to create buffers/windows after some work is done, if the user happens to open cmdwin at the wrong the moment: Lua callback: …/guh.nvim/lua/guh/util.lua:531: E11: Invalid in command-line window; <CR> executes, CTRL-C quits stack traceback: [C]: in function 'nvim_buf_delete' …/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526> Solution: Just say no to "inception". Reimplement cmdwin as a normal buffer+window. All of the cmdwin contortions (in both core, and innocent plugins) exist literally only to support "inception": recursive cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute, `:input()`, etc. So we just won't support that (though I have a potential plan for that later, which I call "modal parking lot"). The benefit is that plugins, and core, no longer have to care about cmdwin. BONUS: - mouse-drag on vertical separators works (it only worked for horizontal/statusline before) - inccommand-in-cmdwin now works correctly, for free (thus don't need #40077). POTENTIAL FOLLOWUPS - Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos. - Unify `BUFLOCK_OK` / `LOCK_OK` ? DESIGN: - Eliminate lots of C globals, `EX_CMDWIN`, etc. - `text_locked()` no longer reports true for cmdwin. - cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe', 'buftype=nofile'. Invariants come from those options rather than special cases throughout the codebase. - `nv_record` for q:/q//q? calls Lua `nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN` / cmdline-reader detour. - `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls `vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so the in-flight cmdline cancels. Reader state is not serialized; instead the captured `(type, line, col)` is replayed via `nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms. - On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the window and re-feeds the cmdline. BREAKING CHANGES: - Expression-register cmdline (`<C-R>=` from insert-mode) no longer supports cmdwin. Same applies to `input()` / `inputlist()` (already covered by `text_locked`). - Usage of cmdwin in macros/mappings will probably break (assuming they ever worked).
* feat(startup)!: "standalone" mode -ll is killbfredl2026-06-04
| | | | | | | | | | | | | | This was originally used because we needed a lua interpreter to run the standalone _busted_ lua application (except we used fuckery behind the scenes to fake its binary dependencies with our own binary dependencies). Now we longer do that, we instead run `test.harness` as a standard nvim -l script. as this mode is no longer used in tests it risks going to bitrot anyway. NB: -ll mode still had some theoretical benefits like quicker initialization and more "native" printing behavior, etc. But we can incrementally work on "nvim -l" mode instead of maintaining a separate special thing.
* test: run Lua harness with nvim -lLewis Russell2026-05-13
| | | | | | | | | | | | | | | | | | Problem: The Lua test harness still ran through standalone -ll mode, so tests depended on the low-level Lua path instead of the regular Nvim Lua environment. That also meant os.exit() coverage had to carry an ASAN workaround because Lua's raw process exit skipped Nvim teardown and let LeakSanitizer interfere with the observed exit code. Solution: Run the harness and related fixtures with nvim -l. Patch os.exit() in the main Lua state to exit through getout(), so scripts observe normal Nvim shutdown while standalone -ll remains available for generator-style scripts. As a consequence, the startup test can assert os.exit() without disabling leak detection. AI-assisted: Codex
* refactor(main.c): unused "cwd" variable #39751li2026-05-12
|
* feat(ui): use vim.ui.select for :oldfiles, :recoverJustin M. Keyes2026-04-30
| | | | | | | | | | | | Problem: followup to 55ceb314ca96 #39478 `:oldfiles` and swapfile `:recover` do not delegate to `vim.ui.select`. Solution: - Delegate to `vim.ui.select`. - Fix a long-standing `recover_names` bug where `concat_fnames(dir_name, files[i], true)` produced malformed `<dir>//<dir>/<file>` paths (also fixes `swapfilelist()`).
* fix(excmd): use realtime for v:starttime, :uptime #39425Till Bungert2026-04-27
| | | | | | | | | | | Problem: `v:starttime`, `:uptime` use a monotonic high-resolution timer. This only works as long as the timer keeps running (if the computer is suspended the timer is paused). This is somewhat unintuitive, and doesn't match the behavior of the `uptime` shell command. Solution: Implement `os_realtime` to get the real time since the epoch in nanoseconds.
* fix(path): normalize path slashes on Windows #37729tao2026-04-24
| | | | | | | | | | | | | | | | | | | | Problem: On Windows, path separators may become inconsistent for various reasons, which makes normalization quite painful. Solution: Normalize paths to `/` at the entry boundaries and always use it internally, converting back only in rare cases where `\` is really needed (e.g. cmd.exe/bat scripts?). This is the first commit in a series of incremental steps. Note: * some funcs won't respect shellslash. e.g. `expand/fnamemodify` * some funcs still respect shellslash, but will be updated in a follow PR. e.g. `ex_pwd/f_chdir/f_getcwd` * uv's built-in funcs always return `\`. e.g. `uv.cwd/uv.exepath` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* feat(:restart): v:starttime, v:exitreason #39282Justin M. Keyes2026-04-22
| | | | | | | | | | | | 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`
* vim-patch:9.2.0291: too many strlen() callszeertzjq2026-04-06
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: too many strlen() calls Solution: refactor concat_fname() and remove calls to strlen() (John Marriott) Function `concat_fnames()` can make up to 5 calls to `STRLEN()` (either directly or indirectly via `STRCAT()`). In many cases the lengths of arguments `fname1` and/or `fname2` are either known or can simply be calculated. This Commit refactors this function to accept the lengths of arguments `fname1` and `fname2` as arguments. It also adds new argument `ret` to return the resulting string as a `string_T`. Additionally: - function `add_pack_dir_to_rtp()` in `scriptfile.c`: Use a `string_T` to store local variables `new_rtp` and `afterdir`. Replace calls to `STRCAT()` with calls to `STRCPY()`. Change type of variable `keep` to `size_t` for consistency with other lengths. - function `qf_get_fnum()` in `quickfix.c`: Use a `string_T` to store local variables `ptr` and `bufname` - function `qf_push_dir()` in `quickfix.c`: Use a `string_T` to store local variable `dirname`. Replace call to `vim_strsave()` with `vim_strnsave()`. - function `qf_guess_filepath()` in `quickfix.c`: Use a `string_T` to store local variable `fullname`. - function `make_percent_swname()` in `memline.c`: Rename some variables to better reflect their use. Use a `string_T` to store local variables `d` and `fixed_name`. Slightly refactor to remove need to create an extra string. - function `get_file_in_dir()` in `memline.c`: Use a `string_T` to store local variables `tail` and `retval`. Move some variables closer to where they are used. - function `cs_resolve_file()` in `if_cscope.c`: Use a `string_T` to store local variable `csdir`. Remove one call to `STRLEN()`. - function `add_pathsep()` in `filepath.c`: Refactor and remove 1 call to `STRLEN()` - function `set_init_xdg_rtp()` in `option.c`: Use a `string_T` to store local variable `vimrc_xdg`. closes: vim/vim#19854 https://github.com/vim/vim/commit/cb51add7ae400a47407fb7fb7b7a54e238d4fdf4 Co-authored-by: John Marriott <basilisk@internode.on.net> Co-authored-by: Christian Brabandt <cb@256bit.org>
* fix(:restart): only pass --headless when there is no UI (#38580)zeertzjq2026-03-31
| | | | Change --embed so that the first UI can be on non-stdio channel even if neither --headless nor --listen is passed.
* refactor(ui_client.c): remove unused variable (#38552)zeertzjq2026-03-29
| | | It's been unused since #36319.
* fix(:restart): formalize restart event #35223Sathya Pramodh2026-03-28
| | | | | | | | | | | | | | | | | | | Problem: The "restart" event has some problems: - all UI clients must implement a somewhat complex set of setups - UI must be on the same machine as the server - only works for the "current" UI - race/edge case: If the user config has errors / waiting for input, are all UIs able to attach while Nvim is waiting for input? Solution: - Perform the restart on the server, not the client. - Pass listen address (instead of CLI args) in the UI event. - Simplifies UI logic: they only need to attach to new address. - Opens the door for more enhancements in the future, such as allowing all UIs to reattach instead of only the "current" UI. Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(exit): stop listening before closing channels (#38480)zeertzjq2026-03-25
| | | | | | | | | | | | | | | | | | | | | | Fixes the following flaky test on FreeBSD: FAILED test/functional/terminal/tui_spec.lua @ 218: TUI :restart works test/functional/testterm.lua:223: Row 1 did not match. Expected: |*^ | |*{100:~ }| |*{100:~ }| |*{100:~ }| |*{3:[No Name] }| |*{MATCH:%d+ +}| |{5:-- TERMINAL --} | Actual: |*nvim: Failed to --listen: address already in use: | |*"/tmp/cirrus-ci-build/build/Xtest_tmpdir_terminal/| |*nvim.cirrus/LLdBdg/nvim.18878.1" | |* More info with "nv| |*im -h" | |*[Proce^ss exited 1] | |{5:-- TERMINAL --} |
* vim-patch:partial:9.2.0126: String handling can be improved (#38214)zeertzjq2026-03-10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: String handling can be improved Solution: Pass string length where it is known to avoid strlen() calls, do a few minor refactors (John Marriott). This commit changes some calls to function `set_vim_var_string()` to pass the string length where it is known or can be easily calculated. In addition: In `evalvars.c`: * In function `set_reg_var()` turn variable `regname` into a C string because that is how it used. * Small cosmetics. In `option.c`: * Slightly refactor function `apply_optionset_autocmd()` to move some variables closer to where they are used. In `getchar.c`: * Slightly refactor function `do_key_input_pre()`: -> change call to `dict_add_string()` to `dict_add_string_len()` and pass it the length of `buf`. -> only call `get_vim_var_string()` once. In `message.c`: * Use a `string_T` to store local variable `p`. In `normal.c`: * Move some variables closer to where they are used. closes: vim/vim#19618 https://github.com/vim/vim/commit/727f6e2686fb1d06b9591e6de689763a479cc664 Co-authored-by: John Marriott <basilisk@internode.on.net>
* revert: "fix(tui): server --listen error sometimes not visible (#38027)" ↵zeertzjq2026-03-06
| | | | | | | | (#38175) This reverts commit ab8371a26cf47a40d26af637455ea71da0d5a59d. Need to think of a different solution, which may require adding new flags to nvim_ui_attach() (e.g. passing stdout or stderr fd).
* fix(tui): call tcdrain() on stdout and stderr on exit (#38154)zeertzjq2026-03-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: On FreeBSD, output written to TTY may be lost on exit. Example test failure: FAILED test/functional/terminal/tui_spec.lua @ 2521: TUI no assert failure on deadly signal #21896 test/functional/terminal/tui_spec.lua:2523: Row 1 did not match. Expected: |*Nvim: Caught deadly signal 'SIGTERM' | |* | |*[Process exited 1]^ | |* | |* | | | |{5:-- TERMINAL --} | Actual: |* | |*[Process exited 1]{100:^ }| |*{100:~ }| |*{100:~ }| |*{3:[No Name] }| | | |{5:-- TERMINAL --} | To print the expect() call that would assert the current screen state, use screen:snapshot_util(). In case of non-deterministic failures, use screen:redraw_debug() to show all intermediate screen states. Snapshot: screen:expect([[ | [Process exited 1]{100:^ }| {100:~ }|*2 {3:[No Name] }| | {5:-- TERMINAL --} | ]]) stack traceback: test/functional/ui/screen.lua:909: in function '_wait' test/functional/ui/screen.lua:537: in function 'expect' test/functional/terminal/tui_spec.lua:2523: in function <test/functional/terminal/tui_spec.lua:2521> Solution: Call tcdrain() on stdout and stderr on exit. This problem is only observed on FreeBSD, but it probably doesn't hurt to do this on all platforms with termios.h. In fact using tcdrain() on PTY slave is no-op on Linux according to Linux kernel source code.
* fix(tui): server --listen error sometimes not visible (#38027)zeertzjq2026-03-02
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |