feat(options): schema, "dict" options, messages

Problem:
Options parsing is still painful for dict-style options.

Solution:
schema-maxxing => better `opt:get()` (will be the basis for `vim.o()`),
unified (and more-detailed) err msgs.

- Drop bespoke structure-builder in `_core/options.lua`.
- Define `schema` for all non-primitive options (except 'guicursor' and
  statusline-style options); generate reified keysets `OptKeyDict`).
  - Generate 'fillchars' => `fcs_tab`, 'listchars' => `lcs_tab`.
- `nvim_set_option_value`:
  - Return the improved structures. Also from `vim.opt.x:get()`.
  - Eliminate api <=> lua roundtrip, centralize option structure
    handling.
- Improve/unify errors.
  - Bump ERR_BUFLEN 80 → 256 so the "one of" list isn't truncated.
- Eliminate old 'diffopt' order-dependence (`iwhiteall` before `iwhite`)

Error samples:

    Typed-key path (opt_strings_check → diffopt/mousescroll/breakindentopt):
    E474: Unknown item 'foo'
    E474: 'context' requires a number
    E474: 'ver' number is out of range
    E474: 'algorithm' must be one of: myers, minimal, patience, histogram
    E474: 'filler' does not take a value

Related:

- #31084
- #34661
- #31820
- #14739
- #20107
- fix #18875
  - :get() returns `{ sbr = true, shift = '3' }` (reified-keyset) instead of `{'sbr', 'shift:3'}`
  - Setting via table now works too. `object_as_optval_for` `is_map` now recognizes struct options.
- fix #30296
  - instead of `E474: Invalid argument`, errors now look like:
    ```
    E474: Invalid value 'x', expected one of: single, double: ambiwidth=x
    E474: Unknown item 'foo': diffopt=foo
    E474: 'context' requires a number: diffopt=context:x
    ```

simplify `win_float_parse_option` from #26799.
This commit is contained in:
Justin M. Keyes
2026-07-21 18:43:55 +02:00
parent 5d76b9836a
commit f8cfd7f06a
63 changed files with 2142 additions and 1230 deletions

View File

@@ -177,7 +177,7 @@ int get_highest_fnum(void)
static int read_buffer(bool read_stdin, exarg_T *eap, int flags)
{
int retval = OK;
bool silent = shortmess(SHM_FILEINFO);
bool silent = shortmess(kShmFileinfo);
// Read from the buffer which the text is already filled in and append at
// the end. This makes it possible to retry when 'fileformat' or
@@ -250,7 +250,7 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
bufref_T old_curbuf;
OptInt old_tw = curbuf->b_p_tw;
bool read_fifo = false;
bool silent = shortmess(SHM_FILEINFO);
bool silent = shortmess(kShmFileinfo);
// The 'readonly' flag is only set when BF_NEVERLOADED is being reset.
// When re-entering the same buffer, it should not change, because the
@@ -384,9 +384,9 @@ int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
// When reading stdin, the buffer contents always needs writing, so set
// the changed flag. Unless in readonly mode: "ls | nvim -R -".
// When interrupted and 'cpoptions' contains 'i' set changed flag.
if ((got_int && vim_strchr(p_cpo, CPO_INTMOD) != NULL)
if ((got_int && vim_strchr(p_cpo, kCpoIntmod) != NULL)
|| curbuf->b_modified_was_set // autocmd did ":set modified"
|| (aborting() && vim_strchr(p_cpo, CPO_INTMOD) != NULL)) {
|| (aborting() && vim_strchr(p_cpo, kCpoIntmod) != NULL)) {
changed(curbuf);
} else if (retval != FAIL && !read_stdin && !read_fifo) {
unchanged(curbuf, false, true);
@@ -1287,7 +1287,7 @@ static int empty_curbuf(bool close_others, int forceit, int action)
if (!close_others) {
need_fileinfo = false;
} else if (retval == OK && !shortmess(SHM_FILEINFO)) {
} else if (retval == OK && !shortmess(kShmFileinfo)) {
// do_ecmd() does not display file info for a new empty buffer.
need_fileinfo = true;
}
@@ -1834,7 +1834,7 @@ static void enter_buffer(buf_T *buf)
open_buffer(false, NULL, 0);
} else {
if (!msg_silent && !shortmess(SHM_FILEINFO)) {
if (!msg_silent && !shortmess(kShmFileinfo)) {
need_fileinfo = true; // display file info after redraw
}
// check if file changed
@@ -3349,7 +3349,7 @@ void fileinfo(int fullname, int shorthelp, bool dont_truncate)
IOSIZE - bufferlen,
"\"%s%s%s%s%s%s",
curbufIsChanged()
? (shortmess(SHM_MOD) ? " [+]" : _(" [Modified]"))
? (shortmess(kShmMod) ? " [+]" : _(" [Modified]"))
: " ",
(curbuf->b_flags & BF_NOTEDITED) && !dontwrite
? _("[Not edited]") : "",
@@ -3358,7 +3358,7 @@ void fileinfo(int fullname, int shorthelp, bool dont_truncate)
(curbuf->b_flags & BF_READERR)
? _("[Read errors]") : "",
curbuf->b_p_ro
? (shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"))
? (shortmess(kShmRo) ? _("[RO]") : _("[readonly]"))
: "",
(curbufIsChanged()
|| (curbuf->b_flags & BF_WRITE_MASK)