Problem: when create a hidden terminal job with `nvim_buf_call`+
`jobstart(…,{term=true})`, program like `lazygit` cannot figure out the
correct width and height.
Solution: `jobstart(…,{term=true})` accepts `width`/`height`
Problem: if pumblend >= 50, non-whitespace menu character gets italic,
bold, underline (or similar) attribute from the cell underneath, which
is not really useful and can't be "blended".
Solution: drop highlight combination for that special case (@zeertzjq
on #36133).
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Problem:
If a client doesn't have a config then an error may be thrown.
Probably caused by: 2f78ff816b
Lua callback: …/lsp.lua:442: attempt to index local 'config' (a nil value)
stack traceback:
…/lsp.lua:442: in function 'can_start'
…/lsp.lua:479: in function 'lsp_enable_callback'
…/lsp.lua:566: in function <…/lsp.lua:565>
Solution:
Not all clients necessarily have configs.
- Handle `config=nil` in `can_start`.
- If user "enables" an invalid name that happens to match a *client*
name, don't auto-detach the client.
Problem: Ctrl-F and Ctrl-B at more prompt not working with kitty
keyboard protocol or modifyOtherKeys (after v9.1.1849).
Solution: Call merge_modifyOtherKeys() in get_keystroke() (zeertzjq).
closes: vim/vim#185586622dc2ded
Problem: CTRL-F and CTRL-B don't work in more prompt
Solution: Make CTRL-F and CTRL-B scroll by a screen down/up
(Bjoern Foersterling)
closes: vim/vim#18545fcf4c435af
Co-authored-by: bfoersterling <bjoern.foersterling@gmail.com>
Problem: nvim_parse_cmd('exe "ls"|edit foo', {}) fails to separate
nextcmd, returning args as { '"ls"|edit', 'foo' } instead of { '"ls"' }
with nextcmd='edit foo'.
Solution: Skip expressions before checking for '|' separator.
fix(help): only set url for nvim-owned tags
Problem:
1. gx on |nonexistingtag| opens
https://neovim.io/doc/user/helptag.html?nonexistingtag.
2. b:undo_ftplugin doesn't remove url extmarks.
Solution:
1. Check if the tag is defined in a help file in $VIMRUNTIME.
2. Solution: clear namespace for buffer in b:undo_ftplugin.
Fixes issue on mac where it was constantly reloading buffers as paths
were not being normalized and resolved correctly (in relation to buffer
name).
Quickfix entry:
/var/folders/pt/2s7dzyw12v36tsslrghfgpkr0000gn/T/git-difftool.m95lj8/right/app.vue
Buffer name:
/private/var/folders/pt/2s7dzyw12v36tsslrghfgpkr0000gn/T/git-difftool.m95lj8/right/app.vue
/var was synlinked to /private/var and this was not being properly
handled.
Also added lazy redraw to avoid too many redraws when this happens in
future and added test for symlink handling.
Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
Problem
As part of https://github.com/neovim/neovim/pull/34373 a unit test was
added that executes the `write` command. This causes a file to be
created named `Xtestfile-functional-shada-buffers-2`. In general tests
should cleanup resources they create.
Solution
Remove the call to `write`, test functions correctly without it.
- Always open the right window to the right, regardless of 'splitright'
setting, ensuring the left window is always leftmost.
- Use `vim.fn.systemlist` for diffr output to avoid manual splitting.
- Add a test to verify window layout consistency with 'splitright' and
'nosplitright' options.
- Escape quotes in git difftool example properly.
Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
Problem
In `vim.pack` the source of any errors is included in the `update`
buffer from lua's `pcall` method. Since the full path is known it is
replaced in the unit test by the string `VIM_PACK_RUNTIME`. The issue is
that `pcall` does not necessarily include the full path, it instead uses
the `lua_Debug` `short_src` value which can be truncated. This means
depending on where you've cloned the repo locally the test can fail.
Solution
Change the replacement pattern for the traceback to be more generic and
handle any path prefix, not just the value of `vim.env.VIMRUNTIME`.
Problem:
1. Setting `pumborder=+,+,+,+,+,+,+,+` failed to render the custom
border characters correctly. The issue occurred in `parse_winborder()`
where it incorrectly used `p_winborder` instead of the `border_opt`
parameter when the option value didn't contain commas.
2. In `pum_redraw()`, calling `parse_border_style()` directly with the
option string failed to parse comma-separated border characters.
3. Missing documentation for PmenuShadow and PmenuShadowThrough
highlight groups used by the shadow border style.
4. Coverity reports CID 631420: passing WinConfig (480 bytes) by value
in `grid_draw_border()`.
5. crash when using `shadow` value on pumborder.
Solution:
1. Fix `parse_winborder()` to use `border_opt` parameter consistently,
ensuring the correct option value is parsed regardless of which
option (winborder/pumborder) is being set.
2. Update `pum_redraw()` to call `parse_winborder()` instead of
`parse_border_style()`, properly handling both predefined styles
and custom comma-separated border characters.
3. Add documentation for PmenuShadow (blended shadow areas) and
PmenuShadowThrough (see-through corners) highlight groups.
4. Change `grid_draw_border()` to accept WinConfig by pointer.
5. When the "shadow" style is used, no additional row and column offset
is applied, and the border width is reduced.
Problem:
Built-in diff mode (nvim -d) does not support directory diffing
as required by git difftool -d. This makes it difficult to compare
entire directories, detect renames, and navigate changes efficiently.
Solution:
Add a DiffTool plugin and command that enables side-by-side diffing of
files and directories in Neovim. The plugin supports rename detection,
highlights changes in the quickfix list, and provides a user command for
easy invocation. This allows proper integration with git difftool -d for
directory comparison.
Example git config:
```ini
[diff]
tool = nvim_difftool
[difftool "nvim_difftool"]
cmd = nvim -c "packadd nvim.difftool" -c "DiffTool $LOCAL $REMOTE"
```
Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
Co-authored-by: Phạm Bình An <111893501+brianhuster@users.noreply.github.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(lsp): type of root_dir should be annotated with string|fun|nil
* feat(lsp): support root_dir as function in _get_workspace_folders
* feat(lsp): let checkhealth support root_dir() function
Examples:
vim.lsp: Active Clients ~
- lua_ls (id: 1)
- Version: <Unknown>
- Root directories:
~/foo/bar
~/dev/neovim
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem: when splitkeep=screen, after enlarge float window with
nvim_win_set_height, lines("w$") return stale value
Solution: update in win_set_inner_size
Problem: :fclose may crash Nvim if autocommands close floats prematurely.
Alternatively, :fclose may call win_close for windows not in curtab if
autocommands change curtab or move windows between tab pages via
nvim_win_set_config (may not crash, but is wrong).
Solution: check win_valid before calling win_close.
Problem
Similar to https://github.com/neovim/neovim/pull/33257, but for the date
component. When timezone is behind UTC the epoch date of individual
components mismatch causing the test to fail.
Solution
The `epoch` variable is created using `os.date` with a `!`, which means
format the date in UTC instead of local timezone:
https://www.lua.org/manual/5.1/manual.html#pdf-os.date.
Since the individual components like year, month, and day are expected
to match `epoch` they should all be created using a `!` as well.
Problem:
Popup menu cannot have a border.
Solution:
Support 'pumborder' option.
Generalize `win_redr_border` to `grid_redr_border`,
which redraws border for window grid and pum grid.
Problem: Window may have wrong height if resized from another tabpage.
Solution: Improve check for whether a tabline has been added (zeertzjq).
fixes: vim/vim#18518closes: vim/vim#18519bd3b958027
Problem: after #35601, nvim_open_win incorrectly attempts to set the size of a
split window to 0 if it wasn't specified.
Solution: only attempt to set the size again if it was actually specified. This has the effect of defaulting to half the size of the parent window (or it may be equalized with other windows to make room), like before.
Fix#36080
Problem: popup: there are some position logic bugs
Solution: Refactor position logic and fix a few bugs
(Girish Palya).
This change does the following:
- Simplified and rewrote horizontal positioning logic (was overly
complex).
- Split horizontal and vertical positioning into separate functions.
- Fixed missing truncation marker (e.g. `>`) when items were truncated
and `pummaxwidth` was not set.
- Fixed occasional extra space being added to menu items.
- Update tests
closes: vim/vim#18441e3ed5584ed
Cherry-pick pum_display_{rtl,ltr}_text() changes from patch 9.1.1835.
Co-authored-by: Girish Palya <girishji@gmail.com>
Problem: 'cursorlineopt' "screenline" isn't redrawn when moving cursor
and then using line("w0") and :retab that does nothing.
Solution: Call redraw_for_cursorcolumn() when setting a valid w_virtcol
(zeertzjq).
closes: vim/vim#18506a084914361
Remove WM_LIST, which was previously added in #7110, but now statusline
and messages no longer interfere with each other thanks to the message
grid, etc., and terminal refreshing no longer calls update_screen()
directly since #9883.
Tests from #7110 and #10107 still pass.
Problem: If plugin was intended to install but there were errors (like
if there is a typo in `src`), lockfile still includes its entry.
This leads to all source of problems (like not correct `get()` output,
not working `update()`, etc.).
Solution: Explicitly account for plugins that were not installed.
Alternative solution might be to write a safe
`lock_set(plug, field, value)` wrapper (which sets field for a correct
`plugins` entry in the lockfile Lua table) and use it after install
to detect the change in `version`. However, this always requires
an extra pass through plugins on every startup, which is suboptimal.
Optimizing for the "happy path" should be a priority in `add()`.
Problem: vertical separator of 'winfixwidth' windows may remain if they
become right-most windows from closing windows to the right.
Solution: Don't implicitly rely on frame_new_width to fix vseps, as the
call may be skipped for 'winfixwidth' windows to preserve
their width; do it explicitly in winframe_remove (Sean Dewar).
Note that I prefer win_new_width here over setting w_width directly, which
would've previously been done by win_split_ins after frame_add_vsep, as this
wasn't true for winframe_remove.
Though the equivalent issue of bottom 'winfixheight' windows leaving stray
statuslines with &ls=0 doesn't seem to exist, test it anyway.
closes: vim/vim#18481620c655677
Nvim: calling win_new_width over setting w_width directly is especially
important in making sure stuff like w_view_width is correct here.
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Problem: No way to granularly operate on plugins when inside
confirmation buffer.
Solution: Implement code actions for in-process LSP that act on "plugin
at cursor":
- Update (if has updates).
- Skip updating (if has updates).
- Delete.
Activate via default `gra` or `vim.lsp.buf.code_action()`.
Problem: :trust is executed even when inside false condition.
Solution: Make skip_cmd() return true for CMD_trust, as ex_trust() does
not handle eap->skip itself.
Problem: Installing plugin always pulls latest `version` changes
(usually from the default branch or "latest version tag"). It is more
robust to prefer initial installation to use the latest recorded
(i.e. "working") revision.
Solution: Prefer using revision from the lockfile (if present) during
install. The extra `update()` will pull the latest changes.
Problem: Running `update()` by default doesn't include not active
plugins, because there was no way to get relevant `version` to get
updates from. This might be a problem in presence of lazy loaded
plugins, i.e. ones that can be "not *yet* active" but still needed to
be updated.
Solution: Include not active plugins by default since their `version` is
tracked via lockfile.
Problem: The revision data is returned behind `opts.info` flag because
it required extra Git calls. With lockfile it is not the case.
Solution: Use lockfile to always set `rev` field in output of `get()`.
Problem: `get()` doesn't return `spec.version` about not-yet-active
plugins (because there was no way to know that without `add()`).
Solution: Use lockfile data to set `spec.version` of non-active plugins.
Problem: Some use cases require or benefit from persistent on disk
storage of plugin data (a.k.a. "lockfile"):
1. Allow `update()` to act on not-yet-active plugins. Currently if
`add()` is not yet called, then plugin's version is unknown
and `update()` can't decide where to look for changes.
2. Efficiently know plugin's dependencies without having to read
'pkg.json' files on every load for every plugin. This is for the
future, after there is `packspec` support (or other declaration of
dependencies on plugin's side).
3. Allow initial install to check out the exact latest "working" state
for a reproducible setup. Currently it pulls the latest available
`version.`
4. Ensure that all declared plugins are installed, even if lazy loaded.
So that later `add()` does not trigger auto-install (when there
might be no Internet connection, for example) and there is no issues
with knowing which plugins are used in the config (so even never
loaded rare plugins are still installed and can be updated).
5. Allow `add()` to detect if plugin's spec has changed between
Nvim sessions and act accordingly. I.e. either set new `src` as
origin or enforce `version.` This is not critical and can be done
during `update()`, but it might be nice to have.
Solution: Add lockfile in JSON format that tracks (adds, updtes,
removes) necessary data for described use cases. Here are the required
data that enables each point:
1. `name` -> `version` map.
2. `name` -> `dependencies` map.
3. `name` -> `rev` map. Probably also requires `name` -> `src` map
to ensure that commit comes from correct origin.
4. `name` -> `src` map. It would be good to also track the order,
but that might be too many complications and redundant together
with point 2.
5. Map from `name` to all relevant spec fields. I.e. `name` -> `src`
and `name` -> `version` for now. Storing data might be too much,
but can be discussed, of course.
This commit only adds lockfile tracking without implementing actual
use cases. It is stored in user's config directory and is suggested to
be tracked via version control.
Example of a lockfile:
```json
{
# Extra nesting to more future proof.
"plugins": {
"plug-a": {
"ref": "abcdef1"
"src": "https://github.com/user/plug-a",
# No `version` means it was `nil` (infer default branch later)
},
"plug-b": {
"dependencies": ["plugin-a", "plug-c"],
"src": "https://github.com/user/plug-b",
"ref": "bcdefg2",
# Enclose string `version` in quotes
"version": "'dev'"
},
"plug-c": {
"src": "https://github.com/user/plug-c",
"ref": "cdefgh3",
# Store `vim.version.Range` via its `tostring()` output
"version": ">=0.0.0",
}
}
}
```
Problem: requested window size passed to nvim_open_win for splits may be ignored
by win_split_ins if it decides to forcefully equalize window sizes instead (e.g:
in an attempt to make room for the new window).
Solution: try to set the size again if it differs from what was requested.
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Problem: completion: some issues with 'acl' when "preinsert" and
"longest" is in 'completeopt' (musonius, after v9.1.1638)
Solution: Fix various issues (see details below) (Girish Palya)
This commit addresses multiple issues in the 'autocompletedelay' behavior with
"preinsert" and "longest":
- Prevents spurious characters from being inserted.
- Ensures the completion menu is not shown until `autocompletedelay` has
expired.
- Shows the "preinsert" effect immediately.
- Keeps the "preinsert" effect visible even when a character is deleted.
fixes: vim/vim#18443closes: vim/vim#18460f77c187277
Co-authored-by: Girish Palya <girishji@gmail.com>
This commit changes `languagetree.lua` so that it creates a scratch
buffer under the hood when dealing with string parsers. This will make
it much easier to just use extmarks whenever we need to track injection
trees in `languagetree.lua`. This also allows us to remove the
`treesitter.c` code for parsing a string directly.
Note that the string parser's scratch buffer has `set noeol nofixeol` so
that the parsed source exactly matches the passed in string.