vterm does not send us the terminator in the string fragment. Our OSC 8
parser assumed that it was and therefore treated short strings as
invalid (as it assumed it was missing a terminator).
Uses the undocumented "error_exit" UI event for a different purpose:
When :detach is used on the server, send an "error_exit" with 0 `status`
to indicate that the server shouldn't wait for client exit.
Problem:
Test often fails on cirrus CI (freebsd):
buffer cursor position is correct in terminal with number column in a line with single-cell multibyte chars and no trailing spaces, before_each
test/functional/terminal/cursor_spec.lua:805: Row 5 did not match.
Expected:
|{7: 1 } |
|{7: 2 } |
|{7: 3 } |
|{7: 4 } |
|*{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|{7: 6 }:^ |
|{3:-- TERMINAL --} |
Actual:
|{7: 1 } |
|{7: 2 } |
|{7: 3 } |
|{7: 4 } |
|*{7: 5 } |
|{7: 6 }:^ |
|{3:-- TERMINAL --} |
Solution:
Skip it. Ex mode isn't that important.
Problem: A 'winblend' window floating over uninitialized cells loses
its highlighting.
Solution: Return the front attribute for uninitialized background cells.
Problem:
Developing/troubleshooting plugins has friction because "restarting"
Nvim requires quitting and manually starting again. #32484
Solution:
- Implement a `:restart` command which emits `restart` UI event.
- Handle the `restart` UI event in the builtin TUI client: stop the
`nvim --embed` server, start a new one, and attach to it.
Problem:
Currently undefined behavior can occur when `string_fragment()` is
called with `OSC_COMMAND`. This is because when the state changes to
`OSC_COMMAND`, `string_initial` is set to true. Then in some cases,
directly after this `string_initial` will be set back to false before
the on_osc callback is called, this leads to `term_settermprop()` never
initializing the title.
Solution:
In all of the no-op cases in `string_fragment()` currently, we continue
to the end of the function where `vt->parser.string_initial` is set to
false. This change returns in the no-op cases instead since in these
cases the string has not yet been terminated and sent to the callback.
Note:
This change also adds a test with a byte sequence from the file
in #34028 that caused nvim to crash. This byte sequences is the shortest
sequence I could trim down from that file that still would trigger the
crash. There are also two other tests I added which validate that
setting the title with OSC-0 and OSC-2 still works.
Fixes: #34028
Problem: The TUI doesn't forward a key properly when it has unsupported
modifiers like NumLock.
Solution: Don't try to add modifiers when only unsupported modifiers are
present.
Related #33791
This fixes the problem that sending a raw C0 control code to trigger a
mapping for it does not work in Terminal mode.
Note: this isn't done for 00 or 7F, as that'll be backward-incompatible.
Problem:
Default 'statusline' is implemented in C and not representable as
a statusline expression. This makes it hard for user configs/plugins to
extend it.
Solution:
- Change the default 'statusline' slightly to a statusline expression.
- Remove the C implementation.
Problem:
Nvim tries to use OSC 52 even when no TUIs are attached.
Solution:
On each UIEnter/UILeave event, check that there is a TUI client connected to Nvim's stdout.
Always allow the following four events to be nested, as they may contain
important information, and are triggered on the event loop, which may be
processed by a blocking call inside another autocommand.
- ChanInfo
- ChanOpen
- TermRequest
- TermResponse
There are some other events that are triggered on the event loop, but
they are mostly triggered by user actions in a UI client, and therefore
not very likely to happen during another autocommand, so leave them
unchanged for now.
Problem:
When a function like vim.wait() is used, we continuously drain the main
event queue until it is empty, never stopping for user input. This means
the libuv timer never runs and the terminal never gets refreshed, so
emit_termrequest continously reschedules itself onto the same event
queue, causing an infinite loop.
Solution:
Use a separate "pending" event queue, where events that require a
terminal refresh are temporarily placed. Drain this queue after a
terminal refresh and events are copied back onto the main queue. This
prevents infinite loops since the main event queue will always be able
to properly drain.
Problem: terminal mode cursor refresh logic has too many edge cases where it
fails when events change curbuf.
Solution: change the logic. Introduce cursor_visible to TerminalState to more
reliably track if terminal mode has changed busy. Move visibility handling to
refresh_cursor and move its call in refresh_terminal to terminal_check to avoid
temporarily changed curbufs from influencing cursor state.
This has the effect of "debouncing" shape/visibility updates to once per
terminal state tick (with the final attributes taking effect, as expected). I
think this is OK, but as a result it may also be warranted to update when
redrawing during the same state tick (e.g: from events executing :redraw); this
can be added later, if wanted.
Also move previous tests to a more appropriate place.
When a plugin registers a TermRequest handler there is currently no way
for the handler to know where the terminal's cursor position was when
the sequence was received. This is often useful information, e.g. for
OSC 133 sequences which are used to annotate shell prompts.
Modify the event data for the TermRequest autocommand to be a table
instead of just a string. The "sequence" field of the table contains the
sequence string and the "cursor" field contains the cursor
position when the sequence was received.
To maintain consistency between TermRequest and TermResponse (and to
future proof the latter), TermResponse's event data is also updated to
be a table with a "sequence" field.
BREAKING CHANGE: event data for TermRequest and TermResponse is now a
table
Problem: after #32458, it may still be possible for `busy_start` UI events to be
emitted without matching `busy_stop`s in the terminal.
Solution: do `terminal_enter`'s cursor visibility check immediately after
setting/restoring State so it occurs before events. This ensures that if pending
escape sequences are processed while in `terminal_enter`, the cursor's initial
visibility is set before `is_focused` is checked by `term_settermprop`.
As a result, we can move the call to `showmode` back to where it was originally.
Problem: `showmode` in `terminal_enter` may cause `vpeekc` to process events,
which may handle pending escape sequences. If `CSI ? 25 l` is handled to hide
the cursor, it may remain hidden even after leaving terminal mode if both
`terminal_enter` and (indirectly) `showmode` call `ui_busy_start`, as there is
only one matching call to `ui_busy_stop` after leaving terminal mode.
Solution: let `terminal_enter` handle setting the initial visibility of the
cursor before calling `showmode`.
Closes#32456.
This simple solution assumes it isn't possible for e.g. `os_breakcheck` to be
called indirectly by something else before `terminal_enter` initially handles
cursor visibility and after it restores it, which I think is true.
Problem:
On Windows, spawning the `nvim --embed` server with `detach=true` breaks
various `tt.setup_child_nvim` tests.
Solution:
Make this behavior opt-in with an env var, temporarily.
Problem: getchar() can't distinguish between C-I and Tab.
Solution: Add {opts} to pass extra flags to getchar() and getcharstr(),
with "number" and "simplify" keys.
related: vim/vim#10603closes: vim/vim#16554e0a2ab397f
Cherry-pick tv_dict_has_key() from patch 8.2.4683.
This commit adds basic support for the kitty keyboard protocol to
Neovim's builtin terminal. For now only the first mode ("Disambiguate
escape codes") is supported.
The code represents a useful pattern in normal mode where remapping
`<tab>` will implicitly also remap `<c-i>` unless you remap that
explicitly. This relies on the _unmapped_ behavior being identical which
is not true in terminal mode, as vterm can distinguish these keys.
Vim seems to entangle this with kitty keyboard mode detection which
is irrelevant for us. Conditional fallbacks depending on
keyboard mode could be done completely inside `vterm/` without getchar.c
getting involved, I would think.
Problem:
- `n.spawn()` is misleading because it also connects RPC, it's not just
"spawning" a process.
- It's confusing that `n.spawn()` and `n.spawn_argv()` are separate.
Solution:
- Replace `n.spawn()`/`n.spawn_argv()` with a single function `n.new_session()`.
This name aligns with the existing functions `n.set_session`/`n.get_session`.
- Note: removes direct handling of `prepend_argv`, but I doubt that was
important or intentional. If callers want to control use of `prepend_argv`
then we should add a new flag to `test.session.Opts`.
- Move `keep` to first parameter of `n.new_session()`.
- Add a `merge` flag to `test.session.Opts`
- Mark `_new_argv()` as private. Test should use clear/new_session/spawn_wait
instead.
Problem:
Tests that need to check `nvim` CLI behavior (no RPC session) create
their own ad-hoc `system()` wrappers.
Solution:
- Use `n.spawn_wait` instead of `system()`.
- Bonus: this also improves the tests by explicitly checking for
`stdout` or `stderr`. And if a signal is raised, `ProcStream.status`
will reflect it.
We currently enable the OSC 52 clipboard provider by setting g:clipboard
when a list of conditions are met, one of which is that $SSH_TTY must be
set. We include this condition because often OSC 52 is not the best
clipboard provider, so if there are "local" providers available Nvim
should prefer those over OSC 52.
However, if no other providers are available, Nvim should use OSC 52
even when $SSH_TTY is not set. When a user is in an SSH session then the
checks for the other clipboard providers will still (typically) fail, so
OSC 52 continues to be enabled by default in SSH sessions.
This is marked as a breaking change because there are some cases where
OSC 52 wasn't enabled before and is now (or vice versa).
Problem:
`termopen` has long been a superficial wrapper around `jobstart`, and
has no real purpose. Also, `vim.system` and `nvim_open_term` presumably
will replace all features of `jobstart` and `termopen`, so centralizing
the logic will help with that.
Solution:
- Introduce `eval/deprecated.c`, where all deprecated eval funcs will live.
- Introduce "term" flag of `jobstart`.
- Deprecate `termopen`.
When a terminal application running inside the terminal emulator sets
the cursor shape or blink status of the cursor, update the cursor in the
parent terminal to match.
This removes the "virtual cursor" that has been in use by the terminal
emulator since the beginning. The original rationale for using the
virtual cursor was to avoid having to support additional UI methods to
change the cursor color for other (non-TUI) UIs, instead relying on the
TermCursor and TermCursorNC highlight groups.
The TermCursor highlight group is now used in the default 'guicursor'
value, which has a new entry for Terminal mode. However, the
TermCursorNC highlight group is no longer supported: since terminal
windows now use the real cursor, when the window is not focused there is
no cursor displayed in the window at all, so there is nothing to
highlight. Users can still use the StatusLineTermNC highlight group to
differentiate non-focused terminal windows.
BREAKING CHANGE: The TermCursorNC highlight group is no longer supported.
Before calling "attach" a screen object is just a dummy container for
(row, col) values whose purpose is to be sent as part of the "attach"
function call anyway.
Just create the screen in an attached state directly. Keep the complete
(row, col, options) config together. It is still completely valid to
later detach and re-attach as needed, including to another session.
vim-patch:8.2.4744: a terminal window can't use the bell
vim-patch:8.2.4745: using wrong flag for using bell in the terminal
BREAKING CHANGE: Bells from :terminal are now silent by default, unless
'belloff' option doesn't contain "term" or "all".
Problem: Setting title while TUI buffer is almost full may cause the
end of a flush to be treated as a part of an OSC 2 or OSC 0
sequence, leading to problems like invisible cursor.
Solution: Make the whole sequence to set title a unibi_ext string.