aboutsummaryrefslogtreecommitdiff
path: root/test/functional/terminal/tui_spec.lua
Commit message (Collapse)AuthorAge
* feat(defaults): drop TAB from 'termpastefilter' #42433Justin M. Keyes3 days
| | | | | | | | Problem: By default, 'termpastefilter' removes TAB chars when pasting to a :terminal. Very annoying, and does not improve "security". Solution: Drop "HT" from the 'termpastefilter' default.
* fix(terminal): [Process exited] msg hides last line of full screen #42349Justin M. Keyes7 days
| | | | | | | | | Problem: If a job exits with cursor at last row, the `[Process exited]` message covers the text of that row. Solution: Start a new line before showing the message, like the old `\r\n[Process exited]` did.
* fix(channel): emit ChanInfo for :detach! #42295Sanzhar Kuandyk7 days
| | | | | | | | | Problem: :detach! changes the channel's detach property without emitting ChanInfo, so plugins watching channel updates cannot react to changes. Solution: Schedule ChanInfo after setting detach=true. Add a test covering emit on :detach!. AI-assisted
* feat(startup): --embed --listen waits for UI if stdin is not a pipeJustin M. Keyes11 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.
* feat(api): nvim_chan_set()Justin M. Keyes12 days
| | | | | | | | | | | | | | | | | | | Problem: Only the stdio channel can "own" a server (self-exit on close). After :restart the TUI reconnects over a socket, so the restarted server does not have "self-exit" behavior when the channel closes (e.g. by UI disconnect, host-terminal close, etc.), which leaves a dangling server. Solution: - Introduce `nvim_chan_set`. (`nvim_set_client_info` doesn't fit: exposing it to Lua would require a `channel` param, which is not backwards-compatible, plus it's awkward because it doesn't merge info.) - Broadcast per-channel properties in the "restart" UI event as an opaque dict (a potentially useful pattern for other UI-events in the future). - UIs are expected to restore the channel properties on restart. - `nvim_get_chan_info()` reports "detach". - Remove `nvim__chan_set_detach()`.
* fix(tabline): make TabLineFill base highlight group of default 'tabline'Sébastien Hoffmann2026-10-03
| | | | | | | | | | | | | | | | | | Follow-up to #41196 Problem: since #29976, the custom 'tabline' has a base highlight group TabLineFill that all %# highlights are automatically combined with. But the default C implementation still uses the TabLine and TabLineSel highlight groups uncombined, or rather effectively combined with Normal. Therefore, themes cannot depend on the base highlighting if they want to support both the default and custom tab lines. Solution: automatically combine TabLine and TabLineSel with TabLineFill in the default C implementation. fix https://github.com/neovim/neovim/issues/41173 ref https://github.com/neovim/neovim/pull/41196 ref https://github.com/neovim/neovim/pull/29976
* vim-patch:9.2.1114: Visual selection is not highlighted at the cursor ↵Takumi Katase2026-09-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | position #42105 vim-patch:9.2.1114: Visual selection is not highlighted at the cursor position Problem: In a terminal the character under the cursor is normally not shown as part of the visual selection. Solution: Don't set "noinvcur" in win_line() (Shane Harper). The problem did not occur in the GUI, only in a terminal. The name "noinvcur" ("don't invert the cursor") was misleading: the variable did not affect the cursor, but whether the character under the cursor could be displayed as part of the visual selection. The "noinvcur" handling may have been meant to help during a visual selection when Visual is shown in reverse video and the terminal draws the cursor by inverting the character under it, as otherwise the character under the cursor would not look highlighted like the rest of the selection. But Vim cannot know in general how a terminal draws the cursor, and when either the cursor is not drawn by inverting the character under it or Visual is not shown in reverse video, the handling just left a character of the visual selection unhighlighted. closes: vim/vim#21317 https://github.com/vim/vim/commit/d10aab4ba6602f8f2f2576d2d62ceb63869db6fb Co-authored-by: Shane Harper <shane@shaneharper.net> AI-assisted
* fix(tui): don't treat ESC preceding repeat/release as ALT (#41770)zeertzjq2026-09-08
|
* feat(multicursor): MC HAMMER #41587Justin M. Keyes2026-09-01
| | | | | | | | | | | | | | | | | | | | | Other (squashed) commits: fix(tui): emit ui_send output atomically with the frame Problem: tui_ui_send() writes directly to the TTY, bypassing the output buffer. Sequences sent via nvim_ui_send() (e.g. kitty multiple-cursors, or visual-dot-repeat) always arrive in a separate TTY write from the frame they were computed for. This manifests as "tearing", or e.g. in the case of multicursor the terminal renders text with stale cursor overlays. Solution: - tui_ui_send(): while a frame is being assembled (pending invalid regions or buffered output), buffer instead of writing directly. - Out-of-frame sends (tty queries, clear-on-disable) still write immediately. - mcursor.lua: emit the terminal-cursor update at the end of the redraw cycle (`on_end`, when screen positions are final) instead of vim.schedule().
* test(tui): unreliable "exits immediately when stdin is closed" #41547Justin M. Keyes2026-08-30
| | | | | | | | | Problem: 0c091cedc291 fixed the "immediate exit" but the 2s `nvim_get_proc()` check still fails on slow (ASAN) CI. Solution: Check the pid after the `screen:expect`. Anyway, `assert_nolog` is the "meaningful" part of the test since 0c091cedc291.
* test(tui): unreliable "TUI :detach % detaches other UIs"Justin M. Keyes2026-08-29
|
* revert: "fix(lifecycle): on Windows, CTRL_CLOSE kills Nvim mid-teardown"Justin M. Keyes2026-08-19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Revert commit 5a71131282010225745d94b068a95fc7eb4db2a9 That change seems good in theory, but it consistently causes 2 failures FAILED …/api/vim_spec.lua @ 3213: API nvim_list_chans, nvim_get_chan_info stream=job :terminal channel Expected values to be equal. Expected: { argv = { "D:/a/neovim/neovim/build/bin/nvim.exe", "-u", "NONE", "-i", "NONE" }, exitcode = 129, id = 4, mode = "terminal", pty = "?", stream = "job" ... } Actual: { argv = { "D:/a/neovim/neovim/build/bin/nvim.exe", "-u", "NONE", "-i", "NONE" }, exitcode = 143, id = 4, mode = "terminal", pty = "?", stream = "job", ... } stack traceback: …/api/vim_spec.lua:3257: in function <…/api/vim_spec.lua:3213> FAILED …/terminal/tui_spec.lua @ 3669: TUI exits immediately when stdin is closed …/terminal/tui_spec.lua:3669: retry() attempts: 69 Expected values to be equal. Expected: vim.NIL Actual: { name = "nvim.exe", pid = 2256, ppid = 8200, } stack traceback: …/testutil.lua:98: in function 'retry' …/terminal/tui_spec.lua:3669: in function <…/terminal/tui_spec.lua:3656>
* fix(lifecycle): on Windows, CTRL_CLOSE kills Nvim mid-teardownJustin M. Keyes2026-08-19
| | | | | | | | | | | | | | | Problem: `signal_ignore_deadly` doesn't work for Windows, where the console still may terminate Nvim during teardown (after `signal_teardown`), while it is already trying to exit. Besides interrupting any housekeeping we are doing, it results in an unpredictable exit code (flaky tests). [Process exited -1073741510] // 0xC000013A STATUS_CONTROL_C_EXIT Solution: Register our own CTRL_CLOSE_EVENT handler which "blocks" the signal. Note: if exit takes longer than 5s, Windows will consider the process "hung" and kill it anyway.
* fix(lifecycle): late signal kills Nvim mid-teardownJustin M. Keyes2026-08-19
| | | | | | | | | | | | | | | | | | | | Problem: A deadly signal arriving during teardown can kill Nvim while it is preserving swapfiles. `os_exit()` ignores deadly signals via `signal_reject_deadly()`, but `signal_teardown()` => `uv_signal_stop()` resets them to the default behavior, so SIGHUP arriving after that kills the process: [Process exited 129] // 128 + SIGHUP This is a race when closing a pty: kernel sends SIGHUP to foreground process group *and* the reads return EOF, so `chanclose()` on a TUI job prepares to exit twice. This means it is unpredictable whether Nvim exits 1 or is terminated. Solution: Ignore deadly signals once the watchers are closed. Only SIGKILL interrupts it now.
* test(tui): unreliable "TUI exits immediately when stdin is closed" #41367Justin M. Keyes2026-08-18
| | | | | | | | | | | | | | | | Problem: Unreliable test on slow CI (ASAN/TSAN): FAILED .../tui_spec.lua @ 3054: TUI exits immediately when stdin is closed retry() attempts: 1 Expected: vim.NIL Actual: { name = "nvim", pid = 33201, ppid = -1 } The test asserts "immediate" exit of the Nvim process, but this may be subject to OS delays outside of our control. Solution: Make the "timed out waiting for DA1" log conditional on the actual timeout, and assert the logs in the test.
* fix(defaults): emit events on automatic background change #41242Kyle2026-08-10
| | | | | | | | | | | | | | | | Problem: After #40270, events are no longer emitted from the automatic background detection. This applies not just during startup, but also if the user manually changes the background of their terminal. Solution: Set the background as normal, assuming that a normal terminal will respond within 100 ms. Change test to match expected behavior: - BG set during startup won't trigger user autocmds since it runs before any user config - If the terminal takes longer than 100 ms to respond to initial OSC 11, it does trigger the OptionSet, but it is triggered through the normal path to ensure values like v:option_new are set #38551 - BG change after startup still triggers autocmds #41146
* Merge #41114 from epithet/default-ruler-as-expressionJustin M. Keyes2026-08-04
|\
| * fix(ruler)!: consistent width in last line and statuslineSébastien Hoffmann2026-08-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Traditionally, the ruler in the last line is one cell shorter than in the statusline, leaving the last cell of the screen blank. According to code comments, this is in order to prevent unwanted scrolling on "some" (unspecified, but presumably ancient) terminals. Berkeley vi is more specific in its `vs_modeline` function: dumb terminals with hardware scroll, SunOS 4.1.1 and Ultrix 4.2 curses. (n)curses still has a similar limitation in `(w)addstr`, but apparently only for historical reasons. Maintaining the different widths leads to awkward inconsistencies when the ruler is configured with 'rulerformat', except for the special case where it contains a top-level `%=`. Shifting the ruler in the last line to the left would be a solution, but the empty cell at the end doesn't seem to be relevant anymore. Solution: extend the ruler in the last line all the way to the right edge of the screen, just like in the statusline. The exact same amount of place will be available to the rest of the UI as before. BREAKING CHANGE: - the default ruler width is now 18 cells - the last cell of the screen is no longer empty Closes #41076
* | feat(detach): opt-in to "server keeps running" #41133Justin M. Keyes2026-08-04
|/ | | | | | | | | | Problem: By default, `nvim` does not survive if its host terminal dies. This is inconvenient if you want to use Nvim as a "session manager" (like tmux). Solution: Let users opt-in to the "survive" behavior via `:detach!` (bang "!"). This marks the current UI as "detachable", so the server will not self-exit if the UI channel closes.
* 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.
* test(harness): migrate away from magic globalsJustin M. Keyes2026-07-21
| | | | | | | | | | | | | | | | | | | | | Problem: The magic globals `it`, `describe`, etc., are more trouble than they are worth. - Hooking into `after_each` requires `getfenv()` hacks. - They confuse luals/emmylua, because the top-level `.luarc.json` isn't merged with `test/.luarc.json` (apparently a luals limitation?) - They totally defeat discoverability because the user just has to "know" about the various magic symbols. So they harm DX, which means they serve no purpose at all. Solution: - Expose the test API from `testutil`, so tests can call `t.it()`, `t.describe()`, etc., in the conventional way. - Drop `getfenv()` hacks. - Drop the `setfenv()` injection in `load_chunk`. - Drop `test/_meta.lua`.
* test(tui): avoid "Screen test succeeded immediately" warningJustin M. Keyes2026-07-18
|
* test(tui): failures if build lacks terminfoJustin M. Keyes2026-07-18
|
* fix(restart): distinguish v:exitreason for :restart! #40801Barrett Ruth2026-07-18
|
* feat(ui): ":%detach!" detaches all other UIs #39216Jason Woodland2026-07-17
| | | | | | | Problem: Not easy for one UI to kick the others off a shared Nvim server. Solution: Treat `:%detach` as detach-other-UIs.
* fix(restart): messages EXX error codes #40759Olivia Kinnear2026-07-17
|
* fix(restart): keep :restart error message concise #40746Olivia Kinnear2026-07-15
|
* 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.
* test: unreliable "TUI split sequences within 'ttimeoutlen'"Justin M. Keyes2026-07-11
| | | | | | | | | | | | | | | | | | | | | FAILED ...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua @ 1200: TUI split sequences work within 'ttimeoutlen' time .../runner/work/neovim/neovim/test/functional/ui/screen.lua:774: Row 1 did not match. Expected: |*^ | |{100:~ }| |{100:~ }| |{100:~ }| |*{3:[No Name] }| |{5:-- INSERT --} | |{5:-- TERMINAL --} | Actual: |*�^ | |{100:~ }| |{100:~ }| |{100:~ }| |*{3:[No Name] [+] }| |{5:-- INSERT --} | |{5:-- TERMINAL --} |
* feat(restart)!: ZR restores session #40498Nathan Zeng2026-07-09
|
* fix(:restart): remove `-S [file]` from v:argv #40521Nathan Zeng2026-07-05
| | | | | | | | | | Problem: Session files specified at startup `-S [file]`, logically conflict with `:restart`. Solution: Remove `-S [file]` from `v:argv` when doing :restart. Also for the "bang" variant `:restart!`, just because it's simpler (if anyone reports a use-case later, we can revisit).
* feat(:restart)!: ":restart" (no bang) saves/restores session #40321Nathan Zeng2026-06-29
| | | | | | | | | | | Problem: `:restart` does not preserve window layout, etc. Solution: - Change `:restart` to save/restore a session automatically. - Introduce "bang" variant `:restart!` to restart *without* session save/restore. - Introduce `v:startreason`. - `ZR` maps to `:restart!`.
* fix(process): avoid inherited stdio for Windows jobs #40074Sanzhar Kuandyk2026-06-29
| | | | | | | | | | | Problem: On Windows, channel jobs inherit Nvim's stdio, so a background job writing to CON (e.g. gutentags) draws onto the TUI and stays until redraw. Solution: Give Windows job stdin/stderr libuv-created pipes (UV_CREATE_PIPE) instead of inherited fds, so libuv spawns the child with CREATE_NO_WINDOW and CON writes no longer leak onto the TUI.
* fix(tui): attribute `TermResponse` to source channel #40330Barrett Ruth2026-06-23
| | | | | | | Problem: Attach-time terminal probes cannot distinguish responses from different attached UIs. Solution: Identify the UI by RPC channel id in `TermResponse` and make `vim.tty.request()` filter responses by channel.
* fix(defaults): detect `'background'`/`'termguicolors'` on UI attach #40175Barrett Ruth2026-06-20
| | | | | | | | Problem: Terminal background and truecolor detection runs only at startup, gated on a UI being attached. A headless server has no UI then, so `'background'` and `'termguicolors'` are never detected and remote UIs ignore the terminal's theme. Solution: Also (re)detect on UIEnter. The most recently attached terminal wins; an explicit user value is preserved.
* test(tui_spec): remove unnecessary job_opts variable (#40334)zeertzjq2026-06-20
| | | | | | | | | This was initially added so that the __NVIM_DETACH environment variable can be added to the jobs started in this test. That environment variable is no longer needed, and there is also vim.tbl_extend() that can be used to add an environment variable to a job anyway. Also, make a shallow copy of opts.env in setup_child_nvim(), as mutating the opts.env passed in may mask problems in other tests.
* fix(tui): keep synchronized output active across partial flushesRiccardo Mazzarini2026-06-02
| | | | | | | | | Problem: when the TUI output buffer is filled during a redraw, flushing it to the terminal also causes `CSI ? 2026 l` to be emitted, which ends synchronized output. This causes visible flickering with large redraws. Solution: track whether a synchronized output is currently active, and only emit the end sequence on the final flush.
* feat(tui): $NVIM_TERMDEFS can override builtin terminfo #39555Kyle2026-05-17
| | | | | | | | | | | | | Problem: - Windows users can't use terminfo to configure their terminal capabilities. #37274 - Terminfo definitions sometimes get out of date or are simply inaccurate. - Eventually, we may want to drop terminfo, relying primarily on built-in definitions. Users will still need some flexibility. Solution: Support $NVIM_TERMDEFS environment variable, which is JSON data that defines "terminfo" definitions that override our builtin terminfo.
* fix(startup): emitting useless OptionSet #39830Puneet Dixit2026-05-17
| | | | | | | | | | | Problem: During startup, we manually trigger a useless and misleading `OptionSet` event, which doesn't set `v:option_*` values (this is a limitation of `nvim_exec_autocmds`). https://github.com/neovim/neovim/blob/ad4bc2d90c5109c24bf6f0119ad31276f1518c6f/runtime/lua/vim/_core/defaults.lua#L939. Solution: The `nvim_exec_autocmds('OptionSet',…)` call does not serve any purpose since 5cbb9d613bf6d8983b5effd7e20343a4ef497c06, so just drop it.
* 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
* docs: misc #39256Justin M. Keyes2026-04-25
|
* feat(tui): restore 'ttyfast' to control tty requests #38699Kyle2026-04-24
| | | | | | | | | | | | 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.
* 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`
* fix(options): default 'titlestring' shows CWD #39233Nick Krichevsky2026-04-22
| | | | | | | Problem: In the default 'titlestring', if the containing directory is the CWD, it renders as "." Solution: Add `:p` to the titlestring.
* test(tui_spec): fix "Uncau