<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rneovim.git/test/functional/api/vim_spec.lua, branch extregs</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(options): out-of-range number in 'iskeyword' aborts Nvim (#42410)</title>
<updated>2026-10-16T23:33:11+00:00</updated>
<author>
<name>ump45nose</name>
<email>52391318+ump45nose@users.noreply.github.com</email>
</author>
<published>2026-10-16T23:33:11+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=9b7ec59580fddf671f7bf922f66ef114a59a51ee'/>
<id>9b7ec59580fddf671f7bf922f66ef114a59a51ee</id>
<content type='text'>
Problem:
A number in 'iskeyword', 'isfname' or 'isident' that overflows (e.g. via
a modeline) hits abort() or an assert in getdigits_int().

Solution:
Parse the numbers non-strictly so an out-of-range value gives E474.

Fixes #42409

AI-assisted</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
A number in 'iskeyword', 'isfname' or 'isident' that overflows (e.g. via
a modeline) hits abort() or an assert in getdigits_int().

Solution:
Parse the numbers non-strictly so an out-of-range value gives E474.

Fixes #42409

AI-assisted</pre>
</div>
</content>
</entry>
<entry>
<title>fix(options): extend dry-run validation</title>
<updated>2026-10-15T17:22:38+00:00</updated>
<author>
<name>Lewis Russell</name>
<email>lewis6991@gmail.com</email>
</author>
<published>2026-09-18T16:33:48+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=380cccb11f1ffcd9ecf15a1b2ac8e2502df0eed1'/>
<id>380cccb11f1ffcd9ecf15a1b2ac8e2502df0eed1</id>
<content type='text'>
Problem: nvim_set_option_value() dry runs skip checks in did_set_*
callbacks. This logic also prepares values needed to apply the option,
such as tab widths or a compiled regexp. Moving the checks into
validation callbacks needs a way to save that work for did_set_*.

Solution: Store prepared values in optset_T so did_set_* can consume
them after the option is stored. Dry runs perform the same validation,
then free the prepared values without changing live state.

This extends dry-run validation for:

- 'cedit': reject invalid command-line window keys.
- 'completeitemalign': require each completion column exactly once.
- 'cursorlineopt': reject empty values and conflicting line modes.
- 'encoding': accept only UTF-8 and its aliases.
- 'fileencoding': reject lists and local changes with 'nomodifiable'.
- 'messagesopt': require mandatory fields and enforce numeric limits.
- 'spellcapcheck': return regexp errors, including under :silent!.
- 'spellsuggest': reject conflicting suggestion modes.
- 'varsofttabstop' and 'vartabstop': reject invalid tab widths.
- 'wildmode': reject more than four completion stages.

'makeencoding' also uses the shared encoding preparation.

Separating value preparation exposed a bug in 'vartabstop' and
'varsofttabstop': failed assignments could discard local tab widths, and
global assignments could overwrite them. Fix this by preparing new
widths separately and applying them only after a valid local assignment.

AI-assisted
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem: nvim_set_option_value() dry runs skip checks in did_set_*
callbacks. This logic also prepares values needed to apply the option,
such as tab widths or a compiled regexp. Moving the checks into
validation callbacks needs a way to save that work for did_set_*.

Solution: Store prepared values in optset_T so did_set_* can consume
them after the option is stored. Dry runs perform the same validation,
then free the prepared values without changing live state.

This extends dry-run validation for:

- 'cedit': reject invalid command-line window keys.
- 'completeitemalign': require each completion column exactly once.
- 'cursorlineopt': reject empty values and conflicting line modes.
- 'encoding': accept only UTF-8 and its aliases.
- 'fileencoding': reject lists and local changes with 'nomodifiable'.
- 'messagesopt': require mandatory fields and enforce numeric limits.
- 'spellcapcheck': return regexp errors, including under :silent!.
- 'spellsuggest': reject conflicting suggestion modes.
- 'varsofttabstop' and 'vartabstop': reject invalid tab widths.
- 'wildmode': reject more than four completion stages.

'makeencoding' also uses the shared encoding preparation.

Separating value preparation exposed a bug in 'vartabstop' and
'varsofttabstop': failed assignments could discard local tab widths, and
global assignments could overwrite them. Fix this by preparing new
widths separately and applying them only after a valid local assignment.

AI-assisted
</pre>
</div>
</content>
</entry>
<entry>
<title>fix(api): nvim_set_option_value() "remove" ignores non-adjacent items #42351</title>
<updated>2026-10-14T14:47:30+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-10-14T14:47:30+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=613988b5aa6ef3cc465135838b163849e3b386cc'/>
<id>613988b5aa6ef3cc465135838b163849e3b386cc</id>
<content type='text'>
Problem:
`nvim_set_option_value('fo', {'c','r','o'}, {operation='remove'})` does
nothing on "jcqrol": the items are joined into one `:set-=` value, which
only matches a contiguous substring. Removing map keys, e.g. {'eol','space'}
from 'listchars', never matches. `vim.opt:remove{…}` inherits this.

(Regression from f34ee3da80e8; 429338e74bf4 fixed the case where the
flags are adjacent and in order.)

Solution:
Remove each item separately.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
`nvim_set_option_value('fo', {'c','r','o'}, {operation='remove'})` does
nothing on "jcqrol": the items are joined into one `:set-=` value, which
only matches a contiguous substring. Removing map keys, e.g. {'eol','space'}
from 'listchars', never matches. `vim.opt:remove{…}` inherits this.

(Regression from f34ee3da80e8; 429338e74bf4 fixed the case where the
flags are adjacent and in order.)

Solution:
Remove each item separately.</pre>
</div>
</content>
</entry>
<entry>
<title>fix(api): crash on invalid :tab address #42328</title>
<updated>2026-10-13T08:59:36+00:00</updated>
<author>
<name>glepnir</name>
<email>glephunter@gmail.com</email>
</author>
<published>2026-10-13T08:59:36+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=f84f8a4155713689f5ebdf297b7c9d4db81d18b1'/>
<id>f84f8a4155713689f5ebdf297b7c9d4db81d18b1</id>
<content type='text'>
Problem:
nvim_parse_cmd("'btab", {}) and typing ":'btab" crash, parse_cmdline()
continues with a NULL eap-&gt;cmd after an invalid :tab address.

Solution:
Fail if parse_command_modifiers() set an error.</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
nvim_parse_cmd("'btab", {}) and typing ":'btab" crash, parse_cmdline()
continues with a NULL eap-&gt;cmd after an invalid :tab address.

Solution:
Fail if parse_command_modifiers() set an error.</pre>
</div>
</content>
</entry>
<entry>
<title>feat(api): nvim_chan_set()</title>
<updated>2026-10-09T11:16:00+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-10-09T00:58:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=d2d8188851430da8bfe8b489ae22f34de5942fff'/>
<id>d2d8188851430da8bfe8b489ae22f34de5942fff</id>
<content type='text'>
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()`.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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()`.
</pre>
</div>
</content>
</entry>
<entry>
<title>fix(terminal): nvim_open_term crash in zero-size window #42248</title>
<updated>2026-10-06T11:41:00+00:00</updated>
<author>
<name>Justin M. Keyes</name>
<email>justinkz@gmail.com</email>
</author>
<published>2026-10-06T11:41:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=501dda72aa110adae71ac46bd775bf49d569214a'/>
<id>501dda72aa110adae71ac46bd775bf49d569214a</id>
<content type='text'>
Problem:
nvim_open_term() sizes the terminal from the current window, which may
have 0 rows (bordered float, 'cmdheight' taking all rows). libvterm
aborts when resizing from 0 rows.

Solution:
In `terminal_alloc()`, treat zero width/height as the pty default
(80x24), like jobstart(term=true).

Open question:
nvim_win_get_height() on such a float returns -1 (winheight() returns 0).</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
nvim_open_term() sizes the terminal from the current window, which may
have 0 rows (bordered float, 'cmdheight' taking all rows). libvterm
aborts when resizing from 0 rows.

Solution:
In `terminal_alloc()`, treat zero width/height as the pty default
(80x24), like jobstart(term=true).

Open question:
nvim_win_get_height() on such a float returns -1 (winheight() returns 0).</pre>
</div>
</content>
</entry>
<entry>
<title>test: simplify functional test expectations</title>
<updated>2026-10-05T16:33:44+00:00</updated>
<author>
<name>Lewis Russell</name>
<email>lewis6991@gmail.com</email>
</author>
<published>2026-10-05T14:37:06+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=483815ab45cf8fc08804e0cfa95b126493a5dd1f'/>
<id>483815ab45cf8fc08804e0cfa95b126493a5dd1f</id>
<content type='text'>
Problem: Repeated default fields and field-by-field assertions obscure
the values that each functional test is meant to check.

Solution: Add eq_partial() to check selected record fields while
preserving list length and order. Use local helpers to fill fixed
expected defaults where tests need full equality. Keep explicit absence
checks and test-specific values at the call sites.

AI-assisted
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem: Repeated default fields and field-by-field assertions obscure
the values that each functional test is meant to check.

Solution: Add eq_partial() to check selected record fields while
preserving list length and order. Use local helpers to fill fixed
expected defaults where tests need full equality. Keep explicit absence
checks and test-specific values at the call sites.

AI-assisted
</pre>
</div>
</content>
</entry>
<entry>
<title>Merge pull request #41971 from bfredl/noisprint</title>
<updated>2026-09-22T13:05:17+00:00</updated>
<author>
<name>bfredl</name>
<email>bjorn.linse@gmail.com</email>
</author>
<published>2026-09-22T13:05:17+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=51d7d99fe7c3625f524b47f3f5d041c6a5895f81'/>
<id>51d7d99fe7c3625f524b47f3f5d041c6a5895f81</id>
<content type='text'>
refactor(charset)!: delete 'isprint' and cleanup 'iskeyword' and friends</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
refactor(charset)!: delete 'isprint' and cleanup 'iskeyword' and friends</pre>
</div>
</content>
</entry>
<entry>
<title>fix(api): preserve option trust during merges</title>
<updated>2026-09-22T12:43:25+00:00</updated>
<author>
<name>Lewis Russell</name>
<email>lewis6991@gmail.com</email>
</author>
<published>2026-09-22T11:24:54+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=8c4dcecfb996c3a7a0cfa3c1d38d44d398120f3c'/>
<id>8c4dcecfb996c3a7a0cfa3c1d38d44d398120f3c</id>
<content type='text'>
Problem:
API append, prepend, and remove operations reach the option setter as
full replacements. This can clear an expression's untrusted flag and
allow it to write files, unlike equivalent :set operations.

Solution:
Pass replacement status through the option setters so merges preserve
the existing value's trust restrictions.

AI-assisted
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Problem:
API append, prepend, and remove operations reach the option setter as
full replacements. This can clear an expression's untrusted flag and
allow it to write files, unlike equivalent :set operations.

Solution:
Pass replacement status through the option setters so merges preserve
the existing value's trust restrictions.

AI-assisted
</pre>
</div>
</content>
</entry>
<entry>
<title>refactor(charset)!: delete 'isprint' and cleanup 'iskeyword' and friends</title>
<updated>2026-09-22T10:31:48+00:00</updated>
<author>
<name>bfredl</name>
<email>bjorn.linse@gmail.com</email>
</author>
<published>2026-09-17T09:58:37+00:00</published>
<link rel='alternate' type='text/html' href='http://git.josher.dev/rneovim.git/commit/?id=6be4cd6560d17573f9ef9910bae4360cf96d760f'/>
<id>6be4cd6560d17573f9ef9910bae4360cf96d760f</id>
<content type='text'>
In the `enc=utf-8` only world, the 'isprint' option is quite obsolete.
The function is only consulted for decoded U+0080 to U+00FF chars
whose printability is defined by the unicode charset, just like
higher codepoints. Meanwhile, invalid `\x80` to `\xFF` bytes are always
unprintable.

Disentangle 'iskeyword', 'isfname' and 'isident' from each other by
giving them all separate bitsets. Now these can be updated individually.
These updaters can back out of errors gracefully, no need for extra
panic logic in option[str].c to restore partially updated chartabs.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In the `enc=utf-8` only world, the 'isprint' option is quite obsolete.
The function is only consulted for decoded U+0080 to U+00FF chars
whose printability is defined by the unicode charset, just like
higher codepoints. Meanwhile, invalid `\x80` to `\xFF` bytes are always
unprintable.

Disentangle 'iskeyword', 'isfname' and 'isident' from each other by
giving them all separate bitsets. Now these can be updated individually.
These updaters can back out of errors gracefully, no need for extra
panic logic in option[str].c to restore partially updated chartabs.
</pre>
</div>
</content>
</entry>
</feed>
