Problem:
The bundled `zip` plugin is implemented in Vimscript, making it harder to
maintain and build on with Nvim's Lua runtime infrastructure.
Solution:
Add an opt-out `zip.lua` browser backed by `nvim.dir`, and disable the legacy
Vimscript implementation by moving it to `pack/dist/opt/zip/`. Load it with
`:packadd zip`.
Problem:
After expanding tabs with the `expandtab` option, if the old indent
matches the requested one, `vim.text.indent()` returns the input
unchanged.
The optimization path assumes that if old_indent == size, the input
wouldn't be changed, which is not correct when old_indent is formed by
expanded tabs.
Solution:
Apply the optimization only when `expandtab` is not set.
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.
Problem:
When 'shellslash' is set, exepath() returns forward-slashed paths.
Passing that path to vim.system() can prevent cmd.exe from launching.
Solution:
Convert the resolved executable path to native separators before spawning.
Add a Windows regression test for cmd.exe with 'shellslash' enabled.
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`.
FAILED …/plugin/pack_spec.lua:92: …/plugin/pack_spec.lua @ 70: vim.pack update() can use lockfile revision as a target
…/plugin/pack_spec.lua:92: …/plugin/pack_spec.lua:70: process still exists
stack traceback:
D:/a/neovim/neovim/test/functional/testnvim/exec_lua.lua:124: in function 'system_sync'
…/plugin/pack_spec.lua:92: in function 'git_cmd'
…/plugin/pack_spec.lua:113: in function 'git_add_commit'
…/plugin/pack_spec.lua:1209: in function <…/plugin/pack_spec.lua:1173>
fix#40167
Problem:
Continue separators normalization, and try to keep it at the
nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx`
Solution:
some key changes
- normalize `$HOME-windows`
- normalize entry points of changing directory
- `nvim_set_current_dir()`, `chdir()`
- normalize the named pipe
- `--listen` arg, `--server` arg, `:restart`
- `serverstart()`, `sockconnect()`, `serverstop()`
- make `expand()` respect 'shellslash' again
- clean up `did_set_shellslash`
- replace `forward_slash` with `TO_SLASH`
- remove obsolete `TMP_PATHSEPSTR`
- remove `slash_adjust` in `do_autocmd_dirchanged`?
- make `fnamemodify()` always return `/` (except when substituting
separators via `:s`, `:gs` ?)
Note:
- these funcs still apply `slash_adjust` on return, as before:
`:pwd`, `chdir()`, `exepath()`, `getcwd()`
- these funcs alwarys return `/`, unlike before the normalization PRs
- `getcompletion()`, `finddir()`, `findfile()`
Also
- clean up code, comments, formatting and tests
- move `TO_SLASH` from `f_chdir` to `changedir_func`
- move `TO_SLASH` from `f_bufadd` to `buflist_new`
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem:
Malformed server responses with `null` (vim.NIL) values, do not show
clear error messages.
Solution:
Assert two known, specific cases, to avoid user confusion.
Problem:
URI buffer names can end with a slash, but slash-ended directory
matching should not preempt URI filetype patterns.
Solution:
Do not use the slash shortcut for names with URI schemes, so those
continue through normal filetype matching.
Co-authored-by: Adam Karafyllidis <akisarou90@gmail.com>
FAILED 2 tests, listed below:
FAILED …/lua/system_spec.lua:124: …/lua/system_spec.lua @ 44: vim.system (async) supports timeout
…/lua/system_spec.lua:124: …/lua/system_spec.lua:44: process still exists
stack traceback:
D:/a/neovim/neovim/test/functional/testnvim/exec_lua.lua:124: in function 'system'
…/lua/system_spec.lua:124: in function <…/lua/system_spec.lua:118>
FAILED …/lua/system_spec.lua:111: …/lua/system_spec.lua @ 22: vim.system (sync) can set environment with clear_env = true and env = nil
…/lua/system_spec.lua:111: …/lua/system_spec.lua:22: process still exists
stack traceback:
D:/a/neovim/neovim/test/functional/testnvim/exec_lua.lua:124: in function 'system'
…/lua/system_spec.lua:111: in function <…/lua/system_spec.lua:97>
Problem:
`vim.filetype.match()` needs a cheap way to recognize directory buffers
without doing filesystem stat work.
Solution:
Ensure full buffer names for directories end in a trailing slash. Now
directory buffers can proceed through the normal 'filetype' path.
Note side-effects: session and ShaDa buffer-list restore behavior must
be compatible, so those + corresponding tests must be updated.
Problem: No concise way to execute a callback with temporarily set
working directory. This might be useful when sourcing nested files to
allow them to assume that current working directory is their root
directory.
Solution: Add `cwd` context to `vim._with().`
fix(iconv): conversion to utf-16be using iconv is inconsistent
vim-patch:9.2.0769
Problem: enc_canonize function changes utf-16be to utf-16 but in linux
type utf-16 defaults to utf-16le.
Solution: Creating a separate entry for utf-16be in enc_canon_table.
Note: the effect is only visible on iconv implementations that
treat "utf-16" and "utf-16be" differently, so the test does
not necessarily fail on an unpatched Vim. But the bug is
visible in vim.iconv. (Manoj Panda)
from: vim/vim@2a63f74
closes: neovim#40262
Signed-off-by: Manoj Panda <manojpandawork@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem:
vim.fs.dir() and vim.fs.find() drop errors returned by uv.fs_scandir().
Solution:
- vim.fs.dir():
- Return root scan failures as a secondary return value.
- Propagate recursive scan failures through the iterator. This allows
callers to distinguish unreadable directories from empty ones.
- vim.fs.find(): Collect errors during search, and return the list as
a second retval.
Problem:
- Lua<=>API roundtrips
- Although we prefer Lua for most business-logic code, doing this
conversion in C makes sense in this case because:
1. setting options is a hot path
2. most of the options logic lives in C
3. the current arrangement is MORE verbose and requires MORE code
Solution:
Move conversion to a C util.
- nvim_set_option_value passes the raw Object (scalar, Array, or Dict)
to `object_as_optval_for()` which flattens it to the canonical `:set`
string and validates the type.
- drop `convert_value_to_vim`, eliminate its roundtrip.
The added test shows the context, one expected a JSON field
to be a Object but it was a null value
pros: shows `vim.NIL` instead of `a userdata`
cons: the context `field 'foo'` is lost. I think this is generated
with internal magic which is hard to replicate.
Problem:
`nvim_set_option_value` cannot "update" options similar to `:set opt=`,
`:set opt+=`, etc. The Lua impls of "vim.opt" / "vim.o" have incomplete,
bespoke reimplementations of those operations.
ref #38420
Solution:
- Add `operation` param to `nvim_set_option_value`, which may be "set",
"append", "prepend", or "remove".
- Use this feature to implement `vim.opt` / `vim.o`.
Problem: vim.diagnostic.Opts.VirtualLines.current_line and
vim.diagnostic.Opts.VirtualText.current_line cause redraw
on every CursorMoved event that makes the text jump
uncomfortably with rapid cursor movement.
Solution: `current_line` state is applied only on CursorHold,
while still being cleared on CursorMoved making it so that
until the cursor has stopped on a line, its diagnostic
looks like cursor is not on the line preventing flicker.
Problem: Running `vim.filetype.match()` when current working directory
was removed from disk throws a `vim.fs.abspath` assertion error.
However, the matching might still be possible without trying to match
against full path (like if it is a known extension).
Solution: Safely compute absolute path and ignore it if it errors.
Problem: Diagnostic virtual lines are hardcoded with "scroll" for
virt_lines_overflow option.
Solution: Add a `overflow` option to `virtual_lines` config
to support "wrap", "scroll", "trunc", and "auto".
Problem:
Listing individual "skipped" notices for each non-actionable or
NVIM_TEST_INTEG test is noisy and makes the "skipped" list overwhelming
and less meaningful.
Solution:
- Mark non-actionable tests with "N/A".
- Report NVIM_TEST_INTEG tests as a separate 1-line summary.
Problem:
`vim.pos.cursor(vim.api.nvim_get_current_buf(win), vim.api.nvim_win_get_cursor(win))`
is too verbose to create a cursor position of a window,
but it is a common use case.
Solution:
Overload `vim.pos.cursor()`, so that it accepts `win` as an argument when `pos` is omitted.
Problem:
When `vim.hl.range(0, …, { timeout = N })` is called, the deferred
`range_hl_clear` captures `buf=0`, which resolves to an arbitrary
"current buffer" at timeout. This may cause a stale highlight that never
gets cleared.
Solution:
Resolve `buf=0` explicitly, before `range_hl_clear` captures it.
Problem:
Diagnostic highlight groups were applied by iterating and calling
`vim.hl.range` for each group individually. That resulted in multiple
extmarks with the same priority being created separately, which does not
allow `DiagnosticUnnecessary` and `DiagnosticDeprecated` with matching
options override `Diagnostic*` styling.
Solution:
Pass the list of hl-groups to `vim.hl.range` so they are applied
together in the correct order.
Problem:
It is repetitive to map multiple keymaps to do the same thing. Here are some
cases where being able to do this would be useful:
-- Visual movement for both j/k and down/up:
vim.keymap.set({ 'n', 'x' }, { 'j', '<Down>' }, 'v:count == 0 ? "gj" : "j"', { expr = true })
vim.keymap.set({ 'n', 'x' }, { 'k', '<Up>' }, 'v:count == 0 ? "gk" : "k"', { expr = true })
-- Map multiple keys to `<Nop>` concisely:
vim.keymap.set({ 'n', 'x' }, { '<Leader>', '<Localleader>', '<CR>' }, '<Nop>')
-- Remove multiple keymaps at once:
vim.keymap.del('n', { 'gri', 'grn', 'grr' })
Solution:
Support the `lhs` of `vim.keymap.set()` and `vim.keymap.del()` being a table, in
the same way that `modes` can be.
Problem:
Currently, only some filesystems (Btrfs, ext2, ext3, ext4) have full
support of accessing the `dirent` entry-type. On other filesystems,
`uv.fs_scandir_next` may return `nil` for an existing but unsupported
entry-type.
This means consumers (such as `fs.dir()`), cannot know if `nil` means
"non-existent" or "unsupported".
Solution:
Fall back to `uv.fs_lstat` when `etype` is `nil`; return "unknown" if it
fails.
Problem: Redrawing when a loaded buffer is not shown in any window on
the current tabpage.
Solution: Check that buffer is shown in a (normal) window before redrawing.
Problem:
- To share logic, creating a `vim.Range` currently creates two `vim.Pos` values
as intermediates, which causes unnecessary table allocations.
- `pos.lua` and `range.lua` contain some overlapping logic.
Solution:
Add `vim.pos._util`, a module for handling
positions represented directly by `row` and `col`.