Commit Graph

588 Commits

Author SHA1 Message Date
zeertzjq
97d9b85bf9 fix(terminal): wrong scrollback with BufFile* autocommand (#37601)
Problem:  Wrong terminal scrollback if BufFile* autocommand drains PTY
          output but doesn't process the pending refresh.
Solution: Refresh scrollback before refreshing screen in terminal_open()
          if scrollback has been allocated.
2026-01-28 23:32:58 +08:00
zeertzjq
1f0dbfea2f fix(tui): log chdir failure properly #37591 2026-01-28 05:44:17 -05:00
zeertzjq
df21ac729c fix(terminal): losing output if BufFile* poll for events (#37580)
Problem:  Terminal loses output if a BufFilePre or BufFilePost autocmd
          polls for events.
Solution: Rename the buffer after allocating the terminal instance. Also
          fix buffer getting wrong name if BufFilePre uses NameBuff.
2026-01-28 06:21:28 +08:00
zeertzjq
b88b7f9591 fix(terminal): wrong colors with nvim_open_term() in non-curbuf (#37579)
Problem:  Wrong colors with nvim_open_term() in non-current buffer.
Solution: Pass the buffer to get_config_string().
2026-01-27 06:59:23 +00:00
zeertzjq
9540e7470b fix(terminal): possible heap-use-after-free during Nvim exit
Usually, terminal_close() calls refresh_terminal(), which allocates the
scrollback buffer, and term_may_alloc_scrollback() in terminal_open()
won't dereference the buffer. However, refresh_terminal() is not called
during Nvim exit, in which case a heap-use-after-free may happen if
TermOpen wipes buffer. Check for non-NULL buf_handle to avoid that.
2026-01-27 13:12:15 +08:00
zeertzjq
b4039ec0b0 fix(terminal): don't allow b:term_title watcher to delete buffer 2026-01-27 12:45:49 +08:00
zeertzjq
b6befc7b03 fix(terminal): losing scrollback when TermOpen polls for events (#37573)
Problem:  When TermOpen polls for enough events to use the scrollback
          buffer, scrollback is lost until the next terminal refresh.
Solution: Allocate the scrollback buffer when it's needed.
2026-01-27 03:46:54 +00:00
zeertzjq
196df35cca fix(terminal): <Ignore> should be no-op (#37494) 2026-01-22 09:26:22 +08:00
zeertzjq
25ce44845d fix(terminal): restore options properly when switching buffer (#37485) 2026-01-21 18:42:47 +08:00
zeertzjq
1883fe39bd test: fix some type warnings (#37483) 2026-01-21 15:11:47 +08:00
zeertzjq
1949452bd3 fix(tui): avoid using uv_pipe_t as uv_tty_t (#37479)
Check tui->out_isatty before accessing tui->output_handle.tty.
2026-01-21 11:53:18 +08:00
zeertzjq
15b9118ac0 test: fail CI if .nvimlog is not empty (#37470)
This will prevent adding passing tests which logs errors in .nvimlog.

Close #28323
Related: https://github.com/neovim/neovim/pull/27660#issuecomment-2035738597

Co-authored-by: dundargoc <gocdundar@gmail.com>
2026-01-20 20:56:06 +08:00
zeertzjq
8133760c98 test: add tests for #14379 2026-01-20 07:09:15 +08:00
zeertzjq
e051718908 fix(process): don't limit PTY master remaining data size 2026-01-15 09:32:10 +08:00
zeertzjq
295fb3fdb2 fix(terminal): :edit should respect 'bufhidden' with exited job (#37301) 2026-01-10 08:25:49 +08:00
zeertzjq
681d006549 vim-patch:9.1.2066: :wqall! doesn't close a terminal like :qall! does (#37314)
Problem:  :wqall! doesn't close a terminal buffer like :qall! does
          (after 8.0.1525).
Solution: Check eap->forceit (zeertzjq).

Ref: https://github.com/vim/vim/issues/2654#issuecomment-366803932

related: vim/vim#2654
related: neovim/neovim#14061
closes:  vim/vim#19129

d8558fdf4f
2026-01-08 23:36:47 +00:00
zeertzjq
0bd4d3f779 test(terminal/buffer_spec): fix flaky test (#37299)
It turns out that uv_write() doesn't queue the write if there are no
pending writes, so vim.uv.run() isn't needed to reproduce the crash.
2026-01-08 02:40:04 +00:00
zeertzjq
23aa4853b3 fix(buffer): don't reuse 1-line terminal buffer (#37261)
Problem:  :edit and :enew may reuse a 1-line terminal buffer, causing
          the new buffer to still be a terminal buffer.
Solution: Don't reuse a terminal buffer, as it's not reused when it has
          more than 1 line.

After this change close_buffer() is the only place where buf_freeall()
can be called on a terminal buffer, so move the buf_close_terminal()
call into buf_freeall() to save some code. Furthermore, closing the
terminal in buf_freeall() is probably more correct anyway, as it is
"things allocated for a buffer that are related to the file".

Also, remove the useless check for on_detach callbacks deleting buffer.
Even if b_locked fails to prevent that, the crash will happen at the end
of buf_updates_unload() first. On the other hand, many other call sites
of buf_updates_unload() and other buffer_updates_* functions don't set
b_locked, which may be a problem as well...
2026-01-06 16:42:17 +08:00
zeertzjq
366251a5d2 fix(terminal): avoid multiple terminals writing to same buffer (#37219)
Problem:  Calling termopen() or nvim_open_term() on a buffer with an
          existing terminal leads to two terminals writing to the same
          buffer if the terminal job is still running, or memory leak
          if the terminal job has exited.
Solution: Close the terminal if the terminal job has exited, otherwise
          report an error. For nvim_open_term() also don't write a
          closed terminal's buffer content to the PTY.
2026-01-05 13:50:23 +08:00
zeertzjq
b67ac8cc6b fix(terminal): crash with race between buffer close and OSC 2 (#37225)
Problem:  Crash when a terminal receives OSC 2 just after closing its
          buffer but before terminal job exits.
Solution: Remove FUNC_ATTR_NONNULL_ALL from buf_set_term_title() and
          check for NULL.
2026-01-05 08:00:50 +08:00
zeertzjq
f6ca9262b8 fix(terminal): handle closing terminal with pending TermRequest (#37227)
Problem:  Destroying a terminal with pending TermRequest leads to
          heap-use-after-free when processing TermRequest afterwards.
Solution: Store the buffer handle instead of the Terminal pointer in the
          pending TermRequest event, and don't emit TermRequest if the
          terminal is already closed.
2026-01-04 22:35:40 +08:00
zeertzjq
3621af9b97 fix(terminal): inconsistent mode change when switching buffer (#37215)
Problem:  When switching to another terminal buffer in Terminal mode,
          usually Nvim stays in Terminal mode, but leaves Terminal mode
          if the old terminal buffer was deleted.
Solution: Don't always leave Terminal mode when active terminal buffer
          is deleted. Instead let terminal_check_focus() decide that.
2026-01-03 17:55:07 +08:00
Kyle
03377b9552 feat(terminal): include sequence terminator in TermRequest event (#37152)
Problem:
Terminals should respond with the terminator (either BEL or ST) used in
the query so that clients can reliably parse the responses. The
`TermRequest` autocmd used to handle background color requests in the
terminal does not have access to the original sequence terminator, so it
always uses BEL. #37018

Solution:
Update vterm parsing to include the terminator type, then forward this
data into the emitted `TermRequest` events for OSC/DCS/APC sequences.
Update the foreground/background `TermRequest` callback to use the same
terminator as the original request.

Details:
I didn't add the terminator to the `TermResponse` event. However, I
assume the `TermResponse` event doesn't care about the terminator
because the sequence is already parsed. I also didn't update any of the
functions in `src/nvim/vterm/state.c` that write out responses. It
looked like those all pretty much used ST, and it would be a much larger
set of changes. In that same file, there's also logic for 8 bit ST
sequences, but from what I can tell, 8 bit doesn't really work (see `:h
xterm-8bit`), so I didn't use the 8 bit ST at all.
2025-12-29 16:30:23 -06:00
Justin M. Keyes
d6bee7e407 test: skip noisy "terminal mode unavailable" logs #36794
Problem:
Every CI log has a lot of noise at the end, which makes it harder to
find relevant test failures:

    Running tests from test/functional/terminal/tui_spec.lua
    ...
    T5831 TUI bg color queries the terminal for background color:
    T5832 TUI bg color triggers OptionSet from automatic background processing:
    T5833 TUI bg color sends theme update notifications when background changes #31652:
    ...
    Running tests from test/functional/ui/output_spec.lua
    ...
    WRN 2025-12-02T03:36:47.304 ui/c/T5831.28003.0 tui_handle_term_mode:223: TUI: terminal mode 2026 unavailable, state 0
    WRN 2025-12-02T03:36:47.359 ui/c/T5832.28006.0 tui_handle_term_mode:223: TUI: terminal mode 2048 unavailable, state 0
    WRN 2025-12-02T03:36:47.414 ui/c/T5833.28009.0 tui_handle_term_mode:223: TUI: terminal mode 2048 unavailable, state 0

Solution:
- Skip logging in test-mode.
    - This can be reverted later, when these logs are changed to "INFO"
      level, per this TODO comment:
      ```
      // TODO(bfredl): This is really ILOG but we want it in all builds.
      // add to show_verbose_terminfo() without being too racy ????
      WLOG("TUI: terminal mode %d unavailable, state %d", mode, state);
      ```
2025-12-05 16:04:24 -05:00
Justin M. Keyes
ebd758f809 test: unreliable "channel opened, ..., deleted by pressing a key"
Problem:
Test sometimes fails on macos:

    test/functional/terminal/channel_spec.lua:96: Expected objects to be the same.
    Passed in:
    (number) 3
    Expected:
    (number) 2

Solution:
Retry a few times.
2025-12-02 00:14:09 -05:00
Justin M. Keyes
c8f2b10a40 test: unreliable "job exit event on jobstart(…,{term=true})"
Problem:
Test often fails in cirrus (bsd) ci:

    FAILED   test/functional/terminal/channel_spec.lua @ 149: no crash when TermOpen autocommand processes job exit event when using jobstart(…,{term=true})
    test/functional/terminal/channel_spec.lua:158: Row 1 did not match.
    Expected:
      |*^ready $ foobar                                              |
      |*                                                            |
      |*[Process exited 0]                                          |
      |                                                            |
    Actual:
      |*^ready $                                                     |
      |*[Process exited 0]                                          |
      |*                                                            |
      |                                                            |

Solution:
Use one printf call instead of multiple.
2025-12-02 00:08:38 -05:00
Olivia Kinnear
12d4c624bb feat(ex_cmds): consistent :restart behavior (#36723) 2025-11-30 02:14:28 -08:00
alf171
d464dffd2f fix: make :restart respect 'confirm' option #36531
When 'confirm' is set and there are unsaved buffers,
:restart now prompts before quitting, matching the behavior of :quit.
2025-11-16 11:08:38 -08:00
bfredl
e1ffa8d33b feat(build): HAVE_UNIBILIUM
compile time features are hot again.

Note: this changes the &term value for builtin definition from
'builtin_xterm' to just 'xterm'. It's an xterm regardless of we use an
external definition or an internal. Prior to this commit the vast
majority of POSIX users will have used external terminfo, so plugins and
scripts are only going to have checked for &term == 'xterm' or 'tmux' or
whatever.
The status of external loading is still available in "nvim -V3" output.
2025-10-31 08:39:32 +01:00
zeertzjq
ce9a73625a test(tui_spec): check logfile for --listen error (#36390) 2025-10-30 09:06:30 +00:00
zeertzjq
e87f2d1cf9 test(tui_spec): separate remote client :restart tests (#36388)
:restart changes the terminal under which the server process is run,
which can be confusing when combined with other testing.

Also, use COLORTERM=xterm-256color for tests with 'notermguicolors' to
avoid delay on server exit. Not all these delays are blocking, but they
increase the number of simultaneously existing Nvim processes.
2025-10-30 16:23:22 +08:00
zeertzjq
50a38d9698 fix(tui): heap-use-after-free when resuming (#36387)
Discovered when writing more tests for suspend/resume.
It seems that this isn't always reproducible with ASAN due to the arena.
2025-10-30 05:26:49 +00:00
zeertzjq
69bddc089f fix(tui): don't call tinput_init() twice (#36386) 2025-10-30 03:06:30 +00:00
zeertzjq
4ef7aa83c4 fix(terminal): keep last cursor if it's on the last row 2025-10-29 10:18:01 +08:00
zeertzjq
db35dd6734 test(ex_terminal_spec): fix flakiness (#36347) 2025-10-27 02:54:14 +00:00
zeertzjq
df23952ce9 fix(tui): don't treat remote TUI as GUI (#36319)
Set "stdin_tty" and "stdout_tty" UI options, so that a remote TUI is not
treated as a GUI.
2025-10-26 06:18:13 +08:00
zeertzjq
520568f40f fix(terminal): adjust marks when deleting scrollback lines (#36294)
This also fixes inconsistent scrolling behavior on terminal output when
cursor is in the middle of the buffer and the scrollback is full.
2025-10-25 06:48:04 +08:00
zeertzjq
67832710a5 fix(terminal): wrong row in TermRequest with full scrollback (#36298)
Problem:  Wrong row in TermRequest with full scrollback.
Solution: Subtract by the number of lines deleted from scrollback.
2025-10-24 06:01:13 +08:00
bfredl
e656d7be2e perf(tui): faster implementation of terminfo
The processing of terminfo can be separated into two steps:

1. The initialization of terminfo, which includes trying to find $TERM
   in a terminfo database file. As a fallback, common terminfo
   definitions are compiled in. After this, we apply a lot of ad-hoc
   patching to cover over limitations of terminfo.

2. While processing updates from nvim, actually using terminfo strings
   and formatting them with runtime values. for this part, terminfo
   essentially is a hyper-enhanced version of snprintf(), including
   a sm0l stack based virtual machine which can manipulate the runtime
   parameters.

This PR completely replaces libuniblium for step 2, with code
vendored from NetBSD's libtermkey which has been adapted to use typesafe
input parameters and to write into an output buffer in place.

The most immedatiate effects is a performance enhancement of
update_attrs() which is a very hot function when profiling the
TUI-process part of screen updates. In a stupid microbenchmark
(essentially calling nvim__screenshot over and over in a loop) this
leads to a speedup of ca 1.5x for redrawing the screen on the TUI-side.
What this means in practise when using nvim as a text editor is probably
no noticible effect at all, and when reabusing nvim as idk a full screen
RGB ASCII art rendrer maybe an increase from 72 to 75 FPS LMAO.

As nice side-effect, reduce the usage of unibilium to initialization only..
which will make it easier to remove, replace or make unibilium optional,
adressing #31989. Specifically, the builtin fallback doesn't use
unibilium at all, so a unibilium-free build is in principle possible
if the builtin definitions are good enough.

As a caveat, this PR doesn't touch libtermkey at all, which still has a
conditional dependency on unibilium. This will be investigated in a
follow-up PR

Note: the check of $TERMCOLOR was moved from tui/tui.c to
_defaults.lua in d7651b27d5 as we want to
skip the logic in _defaults.lua if the env var was set, but there
is no harm in TUI getting the right value when the TUI is trying to
initialize its terminfo shenanigans. Also this check is needed when
a TUI connects to a `--headless` server later, which will observe
a different $TERMCOLOR value than the nvim core process itself.
2025-10-18 11:36:16 +02:00
zeertzjq
40bf38fefc fix(terminal): handle OSC 8 split into multiple fragments
Also fix off-by-one size passed to xmemdupz().
2025-10-04 08:35:15 +08:00
zeertzjq
f64475a226 fix(tui): handle sequence larger than entire buffer 2025-10-04 07:54:50 +08:00
zeertzjq
97ab7dd784 test(tui_spec): deduplicate (#36003) 2025-10-03 10:25:04 +00:00
zeertzjq
6d550f3cdb test(terminal/mouse_spec): forwarding works with resized grid (#35969) 2025-10-01 01:24:02 +00:00
zeertzjq
94f1abf89c test(tui_spec): avoid dangling Nvim processes on test failure (#35900)
Also don't wait indefinitely for all Nvim processes to exit.
2025-09-24 02:21:42 +00:00
zeertzjq
4a69847df4 fix(tui): don't wait for DA1 response when stdin is closed (#35745) 2025-09-13 20:53:17 +08:00
Sean Dewar
e6ba78919c fix(terminal): possibly wrong wrow/wcol in active terminal
Problem: w_wrow/col calculation in terminal_check_cursor is wrong when the
terminal is smaller than the window. Common when there's a larger window open
with the same terminal, or just after a resize (as refresh_size is deferred).

Solution: don't calculate it; validate_cursor will correct it later if it's
out-of-date.

Note that the toplines set for the terminal (also before this PR) assume
'nowrap' (which is set by default for terminal windows), and that no weird stuff
like filler lines are around. That means, for example, it's possible for the
cursor to be moved off-screen if there's wrapped lines. If this happens, it's
likely update_topline will move the cursor back on screen via validate_cursor or
similar, but maybe this should be handled more elegantly in the future?
2025-08-26 09:49:12 +01:00
Sean Dewar
c845f1923d fix(terminal): patch various autocommand-related holes
Problem: autocommands can cause various problems in terminal mode, which can
lead to crashes, for example.

Solution: fix found issues. Move some checks to terminal_check and guard against
autocommands messing with things. Trigger TermEnter/Leave after terminal mode
has changed/restored most state. Wipeout the correct buffer if TermLeave
switches buffers and fix a UAF if it or WinScrolled/Resized frees the terminal
prematurely.

These changes also allow us to remove the buffer restrictions on TextChangedT;
they were inadequate in stopping some issues, and WinScrolled/Resized was
lacking them anyway.
2025-08-26 09:49:12 +01:00
Sean Dewar
b7124ae768 fix(terminal): update winopts and focus when switching terminals
Problem: window options and terminal focus notifications not updated when
switching terminals without leaving terminal mode.

Solution: update them.
2025-08-26 09:49:12 +01:00
Sean Dewar
d07cbb2f42 fix(terminal): check size when creating new tabpage
Problem: when creating a new tabpage with a terminal window, terminal size is
not updated if there is no statusline.

Solution: do not rely on last_status to implicitly call terminal_check_size as a
side effect of making room for a statusline; call it directly.
2025-08-26 09:49:12 +01:00
Sean Dewar
61217e3618 fix(terminal): avoid events messing up topline of focused terminal
Problem: topline of a focused terminal window may not tail to terminal output if
events scroll the window.

Solution: set the topline in terminal_check_cursor.
2025-08-26 09:49:12 +01:00