<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rneovim.git/test/functional/api/ui_spec.lua, branch master</title>
<subtitle>Neovim fork with Rahm's personal hacks.</subtitle>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/'/>
<entry>
<title>fix(rpc): redraw parse failure silently closes channel #42220</title>
<updated>2026-10-03T16:45:57+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-10-03T16:45:57+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=e77fa0a97266b3a31e470d3d5c6036f245e3a5e8'/>
<id>e77fa0a97266b3a31e470d3d5c6036f245e3a5e8</id>
<content type='text'>
Problem:
When `unpacker_parse_redraw()` fails, it closes the unpacker without
setting `unpack_error`, so `chan_close_on_err()` gets a NULL message.
A pending request fails with an empty error (`RPC: (null)`).

c04d0734a728 fixed the crash that followed (advancing the closed
unpacker), but not the silent close itself.

Repro:
Self-attach (`nvim_ui_attach` on a loopback `sockconnect()` channel)
closes the channel without a visible reason, either while
`nvim_ui_attach` is pending or at the next redraw.

Solution:
Set an error msg when `unpacker_parse_redraw()` fails.

Note:
Self-attach fails for accidental reasons, not by design:
- An incoming "redraw" notif is always parsed "as a UI client"
  (`handle_ui_client_redraw`), whose `grid_line` buffer is only
  allocated in a UI client process. A loopback channel is both ends, so
  it parses its own redraw stream as if it were the TUI.
- Even if parsing worked, `parse_msgpack()` drops redraw events unless
  `ui_client_attached`, and a `sockconnect()` client has no notification
  callback.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
When `unpacker_parse_redraw()` fails, it closes the unpacker without
setting `unpack_error`, so `chan_close_on_err()` gets a NULL message.
A pending request fails with an empty error (`RPC: (null)`).

c04d0734a728 fixed the crash that followed (advancing the closed
unpacker), but not the silent close itself.

Repro:
Self-attach (`nvim_ui_attach` on a loopback `sockconnect()` channel)
closes the channel without a visible reason, either while
`nvim_ui_attach` is pending or at the next redraw.

Solution:
Set an error msg when `unpacker_parse_redraw()` fails.

Note:
Self-attach fails for accidental reasons, not by design:
- An incoming "redraw" notif is always parsed "as a UI client"
  (`handle_ui_client_redraw`), whose `grid_line` buffer is only
  allocated in a UI client process. A loopback channel is both ends, so
  it parses its own redraw stream as if it were the TUI.
- Even if parsing worked, `parse_msgpack()` drops redraw events unless
  `ui_client_attached`, and a `sockconnect()` client has no notification
  callback.</pre>
</div>
</content>
</entry>
<entry>
<title>test(api): self-attach test #42219</title>
<updated>2026-10-03T15:18:23+00:00</updated>
<author>
<name>CompileAndConquer</name>
<email>69109614+LorenzoPiombini@users.noreply.github.com</email>
</author>
<published>2026-10-03T15:18:23+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=4e127b2245688602a20d7491b99a571d12f07800'/>
<id>4e127b2245688602a20d7491b99a571d12f07800</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>fix(rpc): don't advance closed unpacker on self-attach</title>
<updated>2026-10-02T13:33:36+00:00</updated>
<author>
<name>Lorenzo Piombini</name>
<email>piombinilorenzo1987@gmail.com</email>
</author>
<published>2026-09-30T17:05:03+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=c04d0734a728a56889e70682ebd88cf0c6a91a99'/>
<id>c04d0734a728a56889e70682ebd88cf0c6a91a99</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>feat(multicursor): MC HAMMER #41587</title>
<updated>2026-09-01T15:17:22+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-09-01T15:17:22+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=9a29622b545fc76c8b44d0e2b90f318a599eef39'/>
<id>9a29622b545fc76c8b44d0e2b90f318a599eef39</id>
<content type='text'>
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().</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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().</pre>
</div>
</content>
</entry>
<entry>
<title>test(harness): migrate away from magic globals</title>
<updated>2026-07-21T11:22:39+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-07-20T15:16:51+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=6d8c8b18d551d0be0490640c00fabb816727ec10'/>
<id>6d8c8b18d551d0be0490640c00fabb816727ec10</id>
<content type='text'>
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`.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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`.
</pre>
</div>
</content>
</entry>
<entry>
<title>test(api/ui_spec): fix flaky test (#40767)</title>
<updated>2026-07-16T11:36:13+00:00</updated>
<author>
<name>zeertzjq</name>
<email>zeertzjq@outlook.com</email>
</author>
<published>2026-07-16T11:36:13+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=7c091348af0ea3e0f6e05b5f387a972b418bfd9b'/>
<id>7c091348af0ea3e0f6e05b5f387a972b418bfd9b</id>
<content type='text'>
The poke_eventloop() and screen:expect() sometimes don't run the test
runner's event loop long enough for the data to arrive at the reading
end of the pipe. Use a screen:expect_unchanged() so that the event loop
can run a bit longer.

FAILED   ...ovim/build/Xtest_xdg_api/test/functional/api/ui_spec.lua @ 105: nvim_ui_send works with stdout_tty
Expected values to be equal.
Expected:
"\27]11;?\7Hello world"
Actual:
"\27]11;?\7"
stack traceback:
	...ovim/build/Xtest_xdg_api/test/functional/api/ui_spec.lua:138: in function &lt;...ovim/build/Xtest_xdg_api/test/functional/api/ui_spec.lua:105&gt;</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The poke_eventloop() and screen:expect() sometimes don't run the test
runner's event loop long enough for the data to arrive at the reading
end of the pipe. Use a screen:expect_unchanged() so that the event loop
can run a bit longer.

FAILED   ...ovim/build/Xtest_xdg_api/test/functional/api/ui_spec.lua @ 105: nvim_ui_send works with stdout_tty
Expected values to be equal.
Expected:
"\27]11;?\7Hello world"
Actual:
"\27]11;?\7"
stack traceback:
	...ovim/build/Xtest_xdg_api/test/functional/api/ui_spec.lua:138: in function &lt;...ovim/build/Xtest_xdg_api/test/functional/api/ui_spec.lua:105&gt;</pre>
</div>
</content>
</entry>
<entry>
<title>fix(tui): attribute `TermResponse` to source channel #40330</title>
<updated>2026-06-23T10:19:56+00:00</updated>
<author>
<name>Barrett Ruth</name>
<email>62671086+barrettruth@users.noreply.github.com</email>
</author>
<published>2026-06-23T10:19:56+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=db30608058db402de37be7a1d33fa60b7fc7de83'/>
<id>db30608058db402de37be7a1d33fa60b7fc7de83</id>
<content type='text'>
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.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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.</pre>
</div>
</content>
</entry>
<entry>
<title>fix(defaults): detect `'background'`/`'termguicolors'` on UI attach #40175</title>
<updated>2026-06-21T00:09:34+00:00</updated>
<author>
<name>Barrett Ruth</name>
<email>62671086+barrettruth@users.noreply.github.com</email>
</author>
<published>2026-06-21T00:09:34+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=74f163c67dafcba4b8d9150fa26131c2115f20f6'/>
<id>74f163c67dafcba4b8d9150fa26131c2115f20f6</id>
<content type='text'>
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.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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.</pre>
</div>
</content>
</entry>
<entry>
<title>test: run Lua harness with nvim -l</title>
<updated>2026-05-13T12:14:07+00:00</updated>
<author>
<name>Lewis Russell</name>
<email>lewis6991@gmail.com</email>
</author>
<published>2026-05-08T10:35:50+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=9432e6c1e2e93ffffabeeeaeb6ccc0cbdf9609dd'/>
<id>9432e6c1e2e93ffffabeeeaeb6ccc0cbdf9609dd</id>
<content type='text'>
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
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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
</pre>
</div>
</content>
</entry>
<entry>
<title>fix(rpc): trigger UILeave earlier on channel close (#38846)</title>
<updated>2026-04-07T21:29:08+00:00</updated>
<author>
<name>zeertzjq</name>
<email>zeertzjq@outlook.com</email>
</author>
<published>2026-04-07T21:29:08+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=5d66ef188fd034b6342c4146e9bbb10fdc4a8643'/>
<id>5d66ef188fd034b6342c4146e9bbb10fdc4a8643</id>
<content type='text'>
Problem:
On exit, rpc_free() is called when processing main_loop.events after
libuv calls close callbacks of the channel's stream. However, when there
are no child processes, these libuv callbacks are called in loop_close()
instead of proc_teardown(), and main_loop.events isn't processed after
loop_close(). As a result, calling remote_ui_disconnect() in rpc_free()
causes UILeave to depend on the presence of child processes.

Solution:
Always call remote_ui_disconnect() in rpc_close_event(), and remove the
call in rpc_free().</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
On exit, rpc_free() is called when processing main_loop.events after
libuv calls close callbacks of the channel's stream. However, when there
are no child processes, these libuv callbacks are called in loop_close()
instead of proc_teardown(), and main_loop.events isn't processed after
loop_close(). As a result, calling remote_ui_disconnect() in rpc_free()
causes UILeave to depend on the presence of child processes.

Solution:
Always call remote_ui_disconnect() in rpc_close_event(), and remove the
call in rpc_free().</pre>
</div>
</content>
</entry>
</feed>
