aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval
Commit message (Collapse)AuthorAge
* multicursor: v:cascading #42289Evgeni Chasnovski8 days
| | | | | Problem: No way to check if cascade is in action. Solution: Add `v:cascading` variable.
* vim-patch:9.2.1169: getfsize() checks file type twice (#42261)zeertzjq13 days
| | | | | | | | | | | | | | | | Problem: getfsize() checks the file type twice. Solution: Use S_ISDIR macro instead of calling mch_isdir() (Yasuhiro Matsumoto). On MS-Windows: 40.8 us -> 26.6 us for a file, 41.1 us -> 25.3 us for a directory. closes: vim/vim#21448 Assisted-by: AI https://github.com/vim/vim/commit/ea1e40e5e06b1a6a5abebe77223f4a7e36930a87 Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
* vim-patch:8.2.1628: Vim9: cannot pass "true" to timer_paused()Jan Edmund Lazo2026-09-30
| | | | | | | | | Problem: Vim9: cannot pass "true" to timer_paused(). Solution: Use tv_get_bool(). (closes vim/vim#6891) https://github.com/vim/vim/commit/418155def2aa45afd7fc034db341dc874b00af3a Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1627: Vim9: cannot pass "true" to submatch/term_gettty/term_startJan Edmund Lazo2026-09-30
| | | | | | | | | | Problem: Vim9: cannot pass "true" to submatch(), term_gettty() and term_start() Solution: Use tv_get_bool_chk(). (closes vim/vim#6888, closes vim/vim#6890, closes vim/vim#6889) https://github.com/vim/vim/commit/ad30470610e228e66afb837fdbab6bea36c43de4 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:partial:9.2.1145: repeat() can cause an integer overflowzeertzjq2026-09-30
| | | | | | | | | | | | Problem: repeat() with a large number can cause an overflow (Yuyao Jiang) Solution: Add overflow check for the various repeat() functions. related: vim/vim#21373 https://github.com/vim/vim/commit/70903d2be29ddf759ea55cfa6d343c026ea04779 Co-authored-by: Christian Brabandt <cb@256bit.org>
* vim-patch:9.2.1139: list2blob() can be improved (#42138)zeertzjq2026-09-29
| | | | | | | | | | | | | | | Problem: list2blob() appends one byte at a time. Solution: Preallocate the buffer and write the bytes directly (Yasuhiro Matsumoto). Cover large conversions, descending ranges, and invalid trailing items. All 33 blob tests pass. Local five-run medians improve by 17% for 4096 items and 19% for 65536 items. closes: vim/vim#21385 https://github.com/vim/vim/commit/c77608d35e899a0103d022fb9edb19c58ea00396 Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
* fix(api): preserve option trust during mergesLewis Russell2026-09-22
| | | | | | | | | | | | | 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
* refactor(multicursor): view/extmark/region logic #42030Justin M. Keyes2026-09-21
| | | | | | | | | | Problem: Redundant logic. Solution: Deduplicate. Also: `winrestview()` no longer forces a status-line redraw and resending `win_pos` (`win_new_width()` on unchanged width).
* refactor(option): simplify error buffer handlingLewis Russell2026-09-21
| | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Option validators and setters repeatedly pass error buffers and their sizes separately. Some setters return messages in static storage. Solution: - Add CharBuf for borrowed writable storage, with its length including space for a terminating NUL. - Move option error buffers to the callers that report errors. Preserve existing buffer sizes, truncation, and calls that do not need a message. - Consolidate option error formatting and the duplicated code that lists valid option values. - Return error messages directly from do_one_set_option(). - Remove unused arguments from get_option_newval() and set_option_value_for(). - Handle legacy TTY assignments in the existing callers and remove the redundant compatibility wrapper. - Reuse CharBuf for Tree-sitter query errors. - Pass CharBuf through the statusline and statuscolumn builders, retaining the buffer sizes provided by their callers, including title formatting. AI-assisted
* vim-patch:9.2.1107: getregionpos() is slow when only the region bounds are ↵Volodymyr Chernetskyi2026-09-15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | needed (#41925) Problem: getregionpos() returns a pair of positions for every line, so obtaining just the outer endpoints of a region costs O(lines); for a 100000 line region that is about 1.4 million list allocations for a result of which the caller keeps two positions. Solution: Add a "bounds" item to {opts} that returns a single pair with the start on the first line and the end on the last line (Volodymyr Chernetskyi). The lines in between do not influence the outer endpoints, so with "bounds" they are not visited at all. The two positions then come from different lines and describe a diagonal of the region rather than its shape; for a blockwise region they are the start of the first line and the end of the last line, not the corners of the block. This is exactly what indexing the full result gives, so the awkward corners are kept as they are, including an empty first line yielding a "col" of 0 for the start while the end keeps its own column. On a 100000 line buffer this takes getregionpos() from about 45 ms to about 0.003 ms per call. closes: vim/vim#21209 https://github.com/vim/vim/commit/2173c3e4eceedc76c4fd7d56cdbfbbd35e9be853
* fix(cmdwin): allow a user to switch to other buffers #41199Rob Pilling2026-08-28
|
* vim-patch:9.2.0996: debugger: crash when evaluating a variable in a :def ↵zeertzjq2026-08-24
| | | | | | | | | | | | | | | | | | | | | | function frame (#41460) Problem: In the debugger ">up" and ">frame" select an older function call frame, but get_funccal_local_ht() and the related functions check current_funccal while returning a dictionary of the frame that get_funccal() selected. A :def function keeps its local variables on the vim9 stack, its funccall_T has no l: and a: dictionaries and is allocated cleared, so with such a frame selected the returned hashtab has a NULL ht_array and evaluating any variable name at the debug prompt crashes in hash_lookup(). Solution: Check the funccal that is actually used and return NULL when it has no l: variables, so that the variable is reported as undefined instead. closes: vim/vim#21111 https://github.com/vim/vim/commit/5ad47b07af72950624904a9ec0bc9f2d4ebc77a6 Co-authored-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs: misc #41452Justin M. Keyes2026-08-23
| | | | | Co-authored-by: darkdi <rantovov5@gmail.com> Co-authored-by: Qiaoxi Guo <28090444+breadtitor@users.noreply.github.com> Co-authored-by: zaveshaa <zaveshaa@gmail.com>
* vim-patch: num -> bool patches #41375Justin M. Keyes2026-08-19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Notes: - 8.2.1614 also flips searchcount()'s "recompute" default to FALSE; - 8.2.1620 flips it back, so the default stays true here. vim-patch:8.2.1601: Vim9: cannot use 'true" with garbagecollect() https://github.com/vim/vim/commit/2df47310422f4a77e85de7901a5299923a1addd3 vim-patch:8.2.1602: Vim9: cannot use 'true" with getbufinfo() https://github.com/vim/vim/commit/036c2cf719e3de445779a275514030be66e26883 vim-patch:8.2.1603: Vim9: cannot use "true" with getchar() https://github.com/vim/vim/commit/c08cc72947fdfab484f53c5d9bbea662bc5a9c8f vim-patch:8.2.1604: Vim9: cannot use "true" with getcompletion() https://github.com/vim/vim/commit/d217a87755ba01fc626b1c178c682fcd05ab3a28 vim-patch:8.2.1614: Vim9: cannot pass "true" to searchcount() https://github.com/vim/vim/commit/597aaac9d2b090e0eb738ab4e2afd454b7b92393 vim-patch:8.2.1615: Vim9: cannot pass "true" to searchdecl() https://github.com/vim/vim/commit/30788d3d37a90b0702d94b7272ed26672534ba6f vim-patch:8.2.1616: Vim9: cannot pass "true" to synID() https://github.com/vim/vim/commit/fcb6d7082d563acc33866b3d3a659c32ad19a9e1 vim-patch:8.2.1617: Vim9: cannot pass "true" to win_splitmove() https://github.com/vim/vim/commit/4b9bd692bdffba03fda04f9979e25431b53e416b vim-patch:8.2.1619: Vim9: cannot pass "true" to spellsuggest() https://github.com/vim/vim/commit/7c27f337bf278babc1ccdcb66ac975f115d660b7 vim-patch:8.2.1620: searchcount() test fails https://github.com/vim/vim/commit/4140c4f3fff1a441f2837f2f911ab0f0368e412a N/A patches: vim-patch:8.2.1606: has() takes no second argument in Nvim https://github.com/vim/vim/commit/04637e243d39f791cfc97c3ce96d99ef1bf047e1 vim-patch:8.2.1610: list2str()/str2list() take no "utf8" argument https://github.com/vim/vim/commit/a48f786787e8e070c1a611146fd1f0f7e141e60a vim-patch:8.2.1611: nr2char() ignores its "utf8" argument https://github.com/vim/vim/commit/ed6a430fae72c077ec106c9620379b69cfec3035
* vim-patch:9.2.0960: double-free in string_reduce() (#41357)zeertzjq2026-08-18
| | | | | | | | | | | | | | | | | | Problem: string_reduce() copies *rettv into argv[0] before calling eval_expr_typval(). When the evaluator fails early, rettv is never reset and still aliases argv[0] v_string. clear_tv(&argv[0]) frees it, leaving rettv dangling and when in vim9script get_func_tv() frees it again (Ave Dva). Solution: Set rettv->v_type = VAR_UNKNOWN like what is done in list_reduce() and tuple_reduce(), use tv_get_string_strict() in f_reduce() closes: vim/vim#21048 Supported by AI. https://github.com/vim/vim/commit/cd59994c455a20d39d5cc41b4978ecfd2bf4be2e Co-authored-by: Christian Brabandt <cb@256bit.org>
* feat(input)!: CmdAtom event #41297Justin M. Keyes2026-08-14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: There is no unified notion of a "user action". Vim processes input by one-char-at-a-time, and mostly throws away any hints it might gather about the user's action, with one exception: it stores the last _edit_ action (the "redo buffer", encoded as unstructured `["x][v][count]body` bytes). Plugins can only observe individual keys (vim.on_key) and high-level effects (TextChanged, CursorMoved). Solution: - Users can subscribe to `CmdAtom` events to handle any user action. - Event is deferred; handlers cannot cancel or interfere with user actions. - Capture `CmdSpec` from the normal/insert/visual subsystems. - typeahead/readahead stay unstructured (`buffheader_T`): they are key streams, not commands. - the redo/record buffers become `StringBuilder`: fewer allocations/copies. - Repurpose the input/redo engine to accept `CmdSpec` objects. "atom": one repeatable unit of user input, as a resolved (post-mapping) keysequence plus structured fields. Only user actions, not `:normal`, API calls, or non-"t" `feedkeys`. BREAKING: dot-repeat of an Insert session, replays the entire session including cursor-moves (:help ins-repeat). BREAKING: dot-repeat of a Visual operation, replays the selection instead of operating on a fixed-size region.
* vim-patch:9.2.0945: sort() with a numeric option can be improvedzeertzjq2026-08-13
| | | | | | | | | | | | | | | | Problem: The comments on the precomputed sort keys explain the code by contrasting it with the previous implementation, and one of them exceeds 80 columns (after v9.2.0937). Solution: Drop the redundant comments and shorten the union member ones (Hirohito Higashi). related: vim/vim#21003 closes: vim/vim#21030 https://github.com/vim/vim/commit/722f4292e55d48520b7e32cabb4b8640293d0977 Co-authored-by: Hirohito Higashi <h.east.727@gmail.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* vim-patch:9.2.0937: sort() with a numeric option converts each item on every ↵zeertzjq2026-08-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | comparison (#41286) Problem: sort() with "n", "N" or "f" converts an item to its number on every comparison. For "n" that is a tv2string() plus strtod() per comparison, so sorting a list of numbers turns each number into a string and back O(n log n) times, dwarfing the sort. Solution: Compute the numeric key of each item once, before the sort, and compare the stored key (Samuel Schlesinger). Only the builtin numeric compare modes are affected; uniq(), which passes a bare list item to the compare function, and the string and user-function paths are unchanged. Sorting a list of 100000 numbers (min of 3, macOS arm64): - sort(l, 'n'): 0.205s -> 0.017s - sort(l, 'N'): 0.017s -> 0.010s - sort(l, 'f'): 0.014s -> 0.010s The result is identical, including that a string is still treated as 0 in "n" mode and that "N" keeps full 64-bit precision. Add Test_sort_numeric_precomputed(): a large shuffled list sorted with "n", mixed integers and floats, int64 values beyond the exact range of a double for "N", and uniq() over the non-precomputed path. closes: vim/vim#21003 https://github.com/vim/vim/commit/c8c59db9dfdc2db5f17aa0a78ea1464f035bdf5e Co-authored-by: Samuel Schlesinger <sgschlesinger@gmail.com> Co-authored-by: Claude <noreply@anthropic.com>
* refactor(ex_cmds): use function arguments for magic behaviorbfredl2026-08-10
| | | | | | | | | | | | Now this was a cargo cult anti-pattern to write home about. Doing painful save-and-restore bookkeeping around a separate `magic_overruled` decoy global is just as messy as doing painful save-and-restore logic around `p_magic` itself. only that now you need to wrap every access to the effective value in a function call. This replaces this with a marvellous new Clean Code technique™: passing in the intended behavior as a function parameter to functions where either the option or an explicit value might be used.
* vim-patch:8.2.1475: Vim9: can't use v:true for option flags (#41249)Jan Edmund Lazo2026-08-09
| | | | | | | | | | | | | | | | | | | | Problem: Vim9: can't use v:true for option flags. Solution: Add tv_get_bool_chk(). (closes vim/vim#6725) ---- "tv_get_bool_or_number_chk()" without vim9 params is identical to "tv_get_number_chk()". "tv_get_number_chk()" and tv"_get_bool_chk()" are identical after excluding new vim9 params. Yes, "want_bool" param is N/A because of "in_vim9script()". If I port it, then I will refactor these macros or "static inline" functions within "src/nvim/eval/typval.h". ---- https://github.com/vim/vim/commit/36967b32fd02eaab4273c1a1e7a1210a5fe45d09 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1597: the channel source file is too bigJan Edmund Lazo2026-08-08
| | | | | | | | | | | | | | | | | Problem: The channel source file is too big. Solution: Move job related code to a new source file. ---- Move eval-related prompt-buffer API to src/nvim/nvim/eval/buffer.c. https://github.com/neovim/neovim/pull/37743#issuecomment-3897416840 ---- https://github.com/vim/vim/commit/8b5866ded6036f7adece26b6d16962bbd2d47842 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1590: Vim9: bufnr() doesn't take "true" argumentJan Edmund Lazo2026-08-08
| | | | | | | | | Problem: Vim9: bufnr() doesn't take "true" argument. Solution: use tv_get_bool_chk(). (closes vim/vim#6863) https://github.com/vim/vim/commit/fe136c9a85412f4bdb5de70ef8416af5fa382b28 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1478: Vim9: cannot use "true" for some popup options (#41236)Jan Edmund Lazo2026-08-08
| | | | | | | | Problem: Vim9: cannot use "true" for some popup options. Solution: Add dict_get_bool(). (closes vim/vim#6725) https://github.com/vim/vim/commit/558813314d63dd0263a7a86c0496c1e89b5c8cba Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1576: Vim9: index() does not take "true" as argumentJan Edmund Lazo2026-08-08
| | | | | | | | | Problem: Vim9: index() does not take "true" as argument. Solution: Use tv_get_bool_chk(). (closes vim/vim#6823) https://github.com/vim/vim/commit/6c553f9c04a698ac2e19584f8ea8e2cb7cd98c80 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1575: Vim9: globpath() doesnot take "true" as argumentJan Edmund Lazo2026-08-08
| | | | | | | | | Problem: Vim9: globpath() doesnot take "true" as argument. Solution: Use tv_get_bool_chk(). (closes vim/vim#6821) https://github.com/vim/vim/commit/f966ce5ea24748eed10f708d4f828be44887a559 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1574: Vim9: glob() doesnot take "true" as argumentJan Edmund Lazo2026-08-08
| | | | | | | | | Problem: Vim9: glob() doesnot take "true" as argument. Solution: Use tv_get_bool_chk(). (closes vim/vim#6821) https://github.com/vim/vim/commit/5892ea151197c8a6363c7ce2322d84277b97353e Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1573: Vim9: getreg() does not take "true" as argumentJan Edmund Lazo2026-08-08
| | | | | | | | | Problem: Vim9: getreg() does not take "true" as argument. Solution: Use tv_get_bool_chk(). (closes vim/vim#6820) https://github.com/vim/vim/commit/67ff97ded70a87bc77f58d0bf9a261710ae88112 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1572: Vim9: expand() does not take "true" as argumentJan Edmund Lazo2026-08-08
| | | | | | | | | Problem: Vim9: expand() does not take "true" as argument. Solution: Use tv_get_bool_chk(). (closes vim/vim#6819) https://github.com/vim/vim/commit/551d25e76545df785a9f62df52f34bc1dd368bfb Co-authored-by: Bram Moolenaar <Bram@vim.org>
* refactor(path): pathcmp() #41035tao2026-08-07
| | | | | | | | | | | | | | | | | | | | | | Problem: Redudant code Solution: Add `path_fold_char()` to normalize path sep. Refactor `pathcmp()` and `path_fnamencmp()` into `path_cmp`. | feature | pathcmp | path_fnamencmp | path_cmp(now) | | ------------------------ | -------------- | -------------- | ------------- | | case folding | `mb_toupper()` | `utf_fold()` | `utf_fold()` | | consults fileignorecase | ✅ | ✅ | `ic` param | | `maxlen` | ✅ | ✅ | ✅ | | `/` == `\` | ✅ | ✅ | ✅ | | MSWIN drive letter | ❌ | ✅ | ✅ | | sep affects sorting | ✅ | ❌ | ✅ | | ignores a trailing slash | ✅ | ❌ | ✅ | Refactor `path_fnamecmp` and `path_full_compare` into `path_equal`, with flags controlling "no filesystem" comparison (i.e. `path_cmp`), env variables expansion, absolute path resolution and filesystem access.
* vim-patch:8.2.1533: Vim9: error when passing getreginfo() result to setreg() ↵Jan Edmund Lazo2026-08-07
| | | | | | | | | | #41216 Problem: Vim9: error when passing getreginfo() result to setreg(). Solution: Use dict_get_bool() for "isunnamed". (closes vim/vim#6784) https://github.com/vim/vim/commit/6a950581da52b410a74531044aae8f1f8f38a7df Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1571: Vim9: count() third argument cannot be "true"Jan Edmund Lazo2026-08-07
| | | | | | | | | Problem: Vim9: count() third argument cannot be "true". Solution: use tv_get_bool_chk(). (closes vim/vim#6818) https://github.com/vim/vim/commit/119f5572306c4abba91eaf446c0c52637db223e8 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* vim-patch:8.2.1550: Vim9: bufname('%') gives an errorJan Edmund Lazo2026-08-07
| | | | | | | | | Problem: Vim9: bufname('%') gives an error. Solution: Only give an error for wrong argument type. (closes vim/vim#6807) https://github.com/vim/vim/commit/02aaad91094939758e053588dd23ebda467eea29 Co-authored-by: Bram Moolenaar <Bram@vim.org>
* feat(cwd)!: :lcd! (bang), rearrange :bcd/:lcd/… scope precedence #41194Justin M. Keyes2026-08-07
| | | | | | | | | | | | | | | | Problem: - buf-local CWD scope is lower priority than :lcd, which is weird. ``` win > buf > tab > global ``` - No way to clear current CWD at a given scope. Solution: - Rerrange scope precedence to: ``` buf > win > tab > global ``` - Introduce "bang" variants (`:bcd!`/`:lcd!`/`:tcd!`) which clears the local CWD for the given scope.
* feat(cwd): support explicit chdir (:bcd/:tcd/…) in temp contextJustin M. Keyes2026-08-06
| | | | | | | | | | | | | | | | | | Problem: - Explicit `:bcd` (etc.) persists from `nvim_buf_call()` but not from an autocmd handler targeting a hidden buf (`LspAttach`, `TermRequest`, …), which needs a `vim.schedule()` workaround. - `vim._with()` is supposed to work as a "sandbox", discarding side-effects, but it leaks CWD changes: `:lcd` from a `win` context, any chdir from a visible-buffer context. Solution: - Explicit :cd/:tcd/:bcd during a temp context persists by default. - "Ambient" directory changes ('autochdir', existing win-local CWD, etc.) are still undone, as before. - Add `kCtxKeepDirs`: snapshot/restore the target's full CWD state (w/b/tp-local, global, cwd). Used by `vim._with()` and `'inccommand'`, which must not leak state.
* fix(cwd): validate getcwd(…, -1)Justin M. Keyes2026-08-04
|
* refactor(editor): cleanup change-directory (:bcd) logicJustin M. Keyes2026-08-04
|
* feat(editor): `:bcd` changes buffer-local directorysaher2026-08-04
| | | | | | | | | | | | | | | | | | Problem: No way to set a buffer-local directory. Use-cases: - "Root dir" for LSP (and the "project" concept). - `:terminal` OSC 7 Solution: Add `:bcd` command. - Extend `getcwd()` to take a third arg; `getcwd(-1, -1, bunfr)` returns the buffer-local working directory. - Buffer-local directories have less priority than window-local ones, and more priority than tab-local ones. Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(options): crash on ":let &l:autoread = v:true" #41158Justin M. Keyes2026-08-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Assigning to the local value of a global-local boolean option ('autoread', 'autocomplete', 'fsync') aborts: Assertion failed: (curval.type == newval.type), function ex_let_option, file vars.c, line 1408. ex_let_one ex_let_vars ex_let execute_cmd0 do_cmdline call_user_func ... eval_map_expr vgetorpeek vgetc state_enter main A global-local option may have local value `kObjectTypeUnset`, but `ex_let_option()` guards only `kObjectTypeNil`. Solution: When curval is Unset, resolve it to the inherited global value.
* fix(options): crash on ":let &t_Co = v:true" #41152Justin M. Keyes2026-08-04
| | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Assigning a Boolean or special value (v:true/v:false/v:null/v:none) to a TTY option aborts: Assertion failed: (curval.type == newval.type), function ex_let_option, file vars.c, line 1408. 3 libsystem_c.dylib __assert_rtn + 284 4 nvim ex_let_one + 3308 5 nvim ex_let_vars + 112 6 nvim ex_let + 2356 7 nvim execute_cmd0 + 252 8 nvim do_cmdline + 9076 9 nvim call_user_func + 3320 10 nvim call_func + 2076 11 nvim get_func_tv + 696 12 nvim eval_func + 380 20 nvim eval_to_string_eap + 276 21 nvim eval_map_expr + 444 22 nvim vgetorpeek + 3172 23 nvim vgetc + 764 Solution: Apply the string-type check to TTY options too, so a Boolean/special value gives "E928: String required" instead of aborting. Valid string/number assignments to `t_*` pseudo-options still silently no-op.
* fix(ui2): `:$q` should not target hidden windows #40992Rob Pilling2026-08-02
| | | | | | | | | | | | | | | | | | | | | | | Similar to #36123, the ui2 windows confuse `:$q`, which doesn't close the last window on the tab, but targets a hidden ui2 window. The problem seems to be a combination of using `FOR_ALL_WINDOWS_IN_TAB()`, which includes hidden windows, and then counting the windows without factoring in `win_has_winnr()`. There are examples of using `win_has_winnr()`, such as: - [`eval/buffer.c`'s `buf_win_common()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/eval/buffer.c#L474-L475) - [`eval/window.c`'s `f_getwininfo()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/eval/window.c#L130-L135) - [`window.c`'s `win_get_tabwin()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/window.c#L7860-L7869) But possibly problematic ones: - `ex_docmd.c`'s: - [`invalid_range()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/ex_docmd.c#L3891-L3893) - ^ should this include hidden windows? Can a user address them by number? `win_has_winnr()` suggests not - [`ex_close()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/ex_docmd.c#L5233-L5244) - [`ex_hide()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/ex_docmd.c#L5478-L5484) - `eval/window.c`'s: - [`f_winrestcmd()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/eval/window.c#L797-L808) - [`find_win_by_nr()`](https://github.com/neovim/neovim/blob/4a5062cda69fa6cb59b7dc0c488dfb05accf99de/src/nvim/eval/window.c#L172-L180)
* fix(options): ":set foo?" for Lua callbacks #41100Justin M. Keyes2026-08-01
| | | | | | | | | | | | | | | | | Problem: `:set foo=<tab>` and `:set foo?` for func/expr options set to a Lua function, always displays "v:lua". The existing "<Lua N: file:line>" form was avoided because the ref id N changes on every read of the same option. Solution: - Don't attempt to tab-complete Lua functions. - Show "<Lua file:line>" (or "<Lua>" if source file is unknown). Example: :set operatorfunc? operatorfunc=<Lua ~/.config/nvim/init.lua:42>
* refactor(options): simplify "unset" logicJustin M. Keyes2026-07-31
|
* refactor(options): memory managementJustin M. Keyes2026-07-31
| | | | | | | | | | | | | | | | Problem: Numerous callers have to manually check optval ownership (i.e. whether, and how, to release) via `is_callback_option`, `option_is_global_local`, etc. This is fragile, hard to use correctly; and if we introduce another optval variant in the future, we'll have to redo all of these careful checks and boilerplate again. Solution: Provide a unified system and use it ev