Problem:
We have too many build flags.
BUNDLED_CMAKE_FLAG is redundant with DEPS_CMAKE_FLAGS.
Solution:
In documentation, refer to DEPS_CMAKE_FLAGS instead of BUNDLED_CMAKE_FLAG.
As a matter of caution it sets it to the default gcc errorformat:
```
errorformat=%*[^"]"%f"%*\D%l: %m,"%f"%*\D%l: %m,%-Gg%\?make[%*\d]: *** [%f:%l:%m,%-Gg%\?make: *** [%f:%l:%m,%-G%f:%l: (Each undeclared identifier is reported only once,%-G%f:%l: for each function it appears in.),%-GIn file included from %f:%l:%c:,%-GIn file included from %f:%l:%c\,,%-GIn file included from %f:%l:%c,%-GIn file included from %f:%l,%-G%*[ ]from %f:%l:%c,%-G%*[ ]from %f:%l:,%-G%*[ ]from %f:%l\,,%-G%*[ ]from %f:%l,%f:%l:%c:%m,%f(%l):%m,%f:%l:%m,"%f"\, line %l%*\D%c%*[^ ] %m,%D%*\a[%*\d]: Entering directory %*[`']%f',%X%*\a[%*\d]: Leaving directory %*[`']%f',%D%*\a: Entering directory %*[`']%f',%X%*\a: Leaving directory %*[`']%f',%DMaking %*\a in %f,%f|%l| %m
```
so that the compiler keeps working after switching to others.
While likely only a subset is needed; such a subset has been proposed in
a commented errorformat;
checked to work for yamllint but ran out of steam for other compilers;
closes: vim/vim#1875474b4f9242e
Co-authored-by: Konfekt <Konfekt@users.noreply.github.com>
This formatting (although rare) is actually accepted by GHC, but vim
does not highlight it. This patch adds the simplest possible regex to
support the behavior.
Inconveniently, this might trigger weird formatting on lines that
contain errors, e.g. if the first backtick is removed from:
a `b` c `d` e
then `c` is going to be marked as an operator, which seems weird but is
valid.
closes: vim/vim#18776ddb88ab796
Co-authored-by: Mirek Kratochvil <exa.exa@gmail.com>
Problem: 'commentstring' requires the +folding feature but is used in
contexts other than folding.
Solution: Remove the +folding feature guards from 'commentstring' and
make it available in all builds (Doug Kearns).
closes: vim/vim#18731a08030c9f7
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
Problem:
If the buffer changes during iteration of the query matches,
`get_node_text()` may fail, showing an error to the user.
Solution:
Use `pcall` to not propogate the error to the user. Retry once if an
error occurred.
Problem:
Trying to match the search highlight groups to the Normal highlight for
the window can fail when the message highlighting contains a fg/bg that
the Normal highlight doesn't (like an error message in cmd will have
ErrorMsg highlight instead of MsgArea - which is Normal in cmd.)
Solution:
Link the search highlight groups to an empty group in 'winhighlight'
thus disabling them instead of overriding them with Normal/MsgArea/etc.
Problem:
When running ":edit <url>", filetype detection is not triggered.
Solution:
Run the autocmds in the filetypedetect group after loading the content.
Problem:
After fetching remote content from a URL and adding it to the buffer,
the buffer is marked as modified. This is inconsistent with the original
netrw behavior, and it causes problems with `:e` to refresh or `:q` as
it prompts for saving the file even if the user hasn't touched the
content at all.
Solution:
Mark the buffer as unmodified right after adding the remote content to
the buffer.
Technically the current behavior does match documentation. However, the
keys following <Cmd>/K_LUA aren't normally received by vim.on_key()
callbacks either, so it does makes sense to discard them along with the
preceding key.
One may also argue that vim.on_key() callbacks should instead receive
the following keys together with the <Cmd>/K_LUA, but doing that may
cause some performance problems, and even in that case the keys should
still be discarded together.
fix(ui2): hide search highlights in msg window.
Problem: Search highlighting is shown in the msg (and dialog) window.
Solution: Hide search highlighting in all but the pager window.
Problem: running ./build/bin/nvim without make install
- doesn't respect local changes in ./runtime,
- includes the path where Nvim would be installed,
- ignores changes in precompiled Lua modules (like .../vim/_editor.lua)
Solution:
- use VIMRUNTIME=./runtime,
- use --luamod-dev
Problem:
With the typescript LSes typescript-language-server and vtsls,
omnicompletion on partial tokens for certain types, such as array
methods, and functions that are attached as attributes to other
functions, either results in no entries populated in the completion menu
(typescript-language-server), or an unfiltered completion menu with all
array methods included, even if they don't share the same prefix as the
partial token being completed (vtsls).
Solution:
Enable insertReplaceSupport and uses the insert portion of the lsp
completion response in adjust_start_col if it's included in the
response.
Completion results are still filtered client side.
Problem: the opts table also is param of util.open_floating_preview,
vim.diagnostic.Opts.Float missing some fields of open_floating_preview.
Solution: diagnostic.Opts.Float extend util.open_floating_preview.Opts
Fix#29267
Problem: No way to customize completion order across multiple servers.
Solution: Add `cmp` function to `vim.lsp.completion.enable()` options
for custom sorting logic.
Problem: Cannot reuse same config with noautocmd for both window
creation and updates, even when value is unchanged.
Solution: Only reject noautocmd changes for existing windows.
This reverts 2495e7e. That past change meant that we would modify the
buffer contents of a tmux session if it exists, even if the current Nvim
process wasn't running inside of it. Depending on the tmux
configuration, this could even affect the clipboard of an actually
attached tmux client, since tmux itself uses OSC 52 to forward buffer
writes to attached clients.
While autodetection is usually a trade-off and can rarely make everybody
happy, this behavior goes counter the principle of least surprise. If
really desired, it can be brought back by explicit configuration.
**Problem:** Whenever `LanguageTree:parse()` is called, injection trees
from previously parsed ranges are dropped.
**Solution:** Allow the function to accept a list of ranges, so it can
return injection trees for all the given ranges.
Co-authored-by: Jaehwang Jung <tomtomjhj@gmail.com>
Problem:
Users often jump and navigate through LSP windows to yank text.
Concealed markdown can make navigation through hyperlinks and code
blocks more difficult.
Solution:
Change 'concealcursor' from 'n' to '' to preserve clean display
while improving navigation and selection of the LSP response.
Closes#36537
Problem: Until now the UI callback called nvim__redraw() liberally.
It should only be needed when Nvim does not update the screen
in its own event loop.
Solution: Identify which UI events require immediate redrawing.
Problem: unnecessary and deprecated diagnostics use their own highlight
groups (`DiagnosticUnnecessary` and `DiagnosticDeprecated`) which
override the typical severity-based highlight groups (like
`DiagnosticUnderlineWarn`).
This can be misleading, since diagnostics about unused variables which
are warnings or errors, are shown like comments, since then only the
`DiagnosticUnnecessary` highlight group is used. Users do not see the
more eye-catching red/yellow highlight.
Solution: Instead of overriding the highlight group to
`DiagnosticUnnecessary` or `DiagnosticDeprecated`, set them in addition
to the normal severity-based highlights.
Problem: `nvim://` scheme feels more like a generalized interface that
may be requested externally, and it acts like CLI args (roughly).
This is how `vscode://` works.
Anything that behaves like an "app" or a "protocol" deserves its own
scheme. For such Nvim-owned things they will be called `nvim-xx://`.
Solution: Use `nvim-pack://confirm#<bufnr>` template for confirmation
buffer name instead of `nvim://pack-confirm#<bufnr>`.
Problem: Lockfile can become out of sync with what is actually installed
on disk when user performs (somewhat reasonable) manual actions like:
- Delete lockfile and expect it to regenerate.
- Delete plugin directory without `vim.pack.del()`.
- Manually edit lock data in a bad way.
Solution: Synchronize lockfile data with installed plugins on every
lockfile read. In particular:
1. Install immediately all missing plugins with valid lock data.
This helps with "manually delete plugin directory" case by
prompting user to figure out how to properly delete a plugin.
2. Repair lock data for properly installed plugins.
This helps with "manually deleted lockfile", "manually edited
lockfile in an unexpected way", "installation terminated due to
timeout" cases.
3. Remove unrepairable corrupted lock data and their plugins. This
includes bad lock data for missing plugins and any lock data
for corrupted plugins (right now this only means that plugin
path is not a directory, but can be built upon).
Step 1 also improves usability in case there are lazy loaded plugins
that are rarely loaded (like on `FileType` event, for example):
- Previously starting with config+lockfile on a new machine only
installs rare `vim.pack.add()` plugin after it is called (while
an entry in lockfile would still be present). This could be
problematic if there is no Internet connection, for example.
- Now all plugins from the lockfile are installed before actually
executing the first `vim.pack.add()` call in 'init.lua'. And later
they are only loaded on a rare `vim.pack.add()` call.
---
Synchronizing lockfile on its every read makes it work more robustly
if other `vim.pack` functions are called without any `vim.pack.add()`.
---
Performance for a regular startup (good lockfile, everything is
installed) is not affected and usually even increased. The bottleneck
in this area is figuring out which plugins need to be installed.
Previously the check was done by `vim.uv.fs_stat()` for every plugin
in `vim.pack.add()`. Now it is replaced with a single `vim.fs.dir()`
traversal during lockfile sync while later using lockfile data to
figure out if plugin needs to be installed.
The single `vim.fs.dir` approach scales better than `vim.uv.fs_stat`,
but might be less performant if there are many plugins that will be
not loaded via `vim.pack.add()` during startup.
Rough estimate of how long the same steps (read lockfile and normalize
plugin array) take with a single `vim.pack.add()` filled with 43
plugins benchmarking:
- Before commit: ~700 ms
- After commit: ~550 ms
Problem: Currently it is possible to have plugin in a "partial install"
state when `git clone` was successfull but `git checkout` was not.
This was done to not checkout default branch by default in these
situations (for security reasons).
The problem is that it adds complexity when both dealing with lockfile
(plugin's `rev` might be `nil`) and in how `src` and `version` are
treated (wrong `src` - no plugin on disk; wrong `version` - "partial"
plugin on disk).
Solution: Treat plugin as "installed" if both `git clone` and
`git checkout` are successful, while ensuring that not installed
plugins are not on disk and in lockfile.
This also means that if in 'init.lua' there is a `vim.pack.add()` with
bad `version`, for first install there will be an informative error
about it BUT next session will also try to install it. The solution is
the same - adjust `version` beforehand.
Problem: Installation confirmation has several usability issues:
- Choosing "No" results in a `vim.pack.add()` error. This was by
design to ensure that all later code that *might* reference
presumably installed plugin will not get executed. However, this
is often too restrictive since there might be no such code (like
if plugin's effects are automated in its 'plugin/' directory).
Instead the potential code using not installed plugin will throw
an error.
No error on "No" will also be useful for planned lockfile repair.
- List of soon-to-be-installed plugins doesn't mention plugin names.
This might be confusing if plugins are installed under different
name.
Solution: Silently drop installation step if user chose "No" and show
plugin names in confirmation text (together with their pretty aligned
sources).
Problem:
Some servers write log to stdout and there's no way to avoid it.
See https://github.com/neovim/neovim/pull/35743#pullrequestreview-3379705828
Solution:
We can extract `content-length` field byte by byte and skip invalid
lines via a simple state machine (name/colon/value/invalid), with minimal
performance impact.
I chose byte parsing here instead of pattern. Although it's a bit more complex,
it provides more stable performance and allows for more accurate error info when
needed.
Here is a bench result and script:
parse header1 by pattern: 59.52377ms 45
parse header1 by byte: 7.531128ms 45
parse header2 by pattern: 26.06936ms 45
parse header2 by byte: 5.235724ms 45
parse header3 by pattern: 9.348495ms 45
parse header3 by byte: 3.452389ms 45
parse header4 by pattern: 9.73156ms 45
parse header4 by byte: 3.638386ms 45
Script:
```lua
local strbuffer = require('string.buffer')
--- @param header string
local function get_content_length(header)
for line in header:gmatch('(.-)\r?\n') do
if line == '' then
break
end
local key, value = line:match('^%s*(%S+)%s*:%s*(%d+)%s*$')
if key and key:lower() == 'content-length' then
return assert(tonumber(value))
end
end
error('Content-Length not found in header: ' .. header)
end
--- @param header string
local function get_content_length_by_byte(header)
local state = 'name'
local i, len = 1, #header
local j, name = 1, 'content-length'
local buf = strbuffer.new()
local digit = true
while i <= len do
local c = header:byte(i)
if state == 'name' then
if c >= 65 and c <= 90 then -- lower case
c = c + 32
end
if (c == 32 or c == 9) and j == 1 then
-- skip OWS for compatibility only
elseif c == name:byte(j) then
j = j + 1
elseif c == 58 and j == 15 then
state = 'colon'
else
state = 'invalid'
end
elseif state == 'colon' then
if c ~= 32 and c ~= 9 then -- skip OWS normally
state = 'value'
i = i - 1
end
elseif state == 'value' then
if c == 13 and header:byte(i + 1) == 10 then -- must end with \r\n
local value = buf:get()
return assert(digit and tonumber(value), 'value of Content-Length is not number: ' .. value)
else
buf:put(string.char(c))
end
if c < 48 and c ~= 32 and c ~= 9 or c > 57 then
digit = false
end
elseif state == 'invalid' then
if c == 10 then -- reset for next line
state, j = 'name', 1
end
end
i = i + 1
end
error('Content-Length not found in header: ' .. header)
end
--- @param fn fun(header: string): number
local function bench(label, header, fn, count)
local start = vim.uv.hrtime()
local value --- @type number
for _ = 1, count do
value = fn(header)
end
local elapsed = (vim.uv.hrtime() - start) / 1e6
print(label .. ':', elapsed .. 'ms', value)
end
-- header starting with log lines
local header1 =
'WARN: no common words file defined for Khmer - this language might not be correctly auto-detected\nWARN: no common words file defined for Japanese - this language might not be correctly auto-detected\nContent-Length: 45 \r\n\r\n'
-- header starting with content-type
local header2 = 'Content-Type: application/json-rpc; charset=utf-8\r\nContent-Length: 45 \r\n'
-- regular header
local header3 = ' Content-Length: 45\r\n'
-- regular header ending with content-type
local header4 = ' Content-Length: 45 \r\nContent-Type: application/json-rpc; charset=utf-8\r\n'
local count = 10000
collectgarbage('collect')
bench('parse header1 by pattern', header1, get_content_length, count)
collectgarbage('collect')
bench('parse header1 by byte', header1, get_content_length_by_byte, count)
collectgarbage('collect')
bench('parse header2 by pattern', header2, get_content_length, count)
collectgarbage('collect')
bench('parse header2 by byte', header2, get_content_length_by_byte, count)
collectgarbage('collect')
bench('parse header3 by pattern', header3, get_content_length, count)
collectgarbage('collect')
bench('parse header3 by byte', header3, get_content_length_by_byte, count)
collectgarbage('collect')
bench('parse header4 by pattern', header4, get_content_length, count)
collectgarbage('collect')
bench('parse header4 by byte', header4, get_content_length_by_byte, count)
```
Also, I removed an outdated test
accd392f4d/test/functional/plugin/lsp_spec.lua (L1950)
and tweaked the boilerplate in two other tests for reusability while keeping the final assertions the same.
accd392f4d/test/functional/plugin/lsp_spec.lua (L5704)accd392f4d/test/functional/plugin/lsp_spec.lua (L5721)
Problem: Relaxing minimal Git version did not fully preserve previous
behavior in case there no `git` executable. Instead it showed the same
error as if after `vim.system({ 'does_not_exist' })`.
Solution: Show a more direct "No `git` executable" error message.
Problem: No example workflow of how to revert after a bad update.
Solution: Add example workflow of how to revert after a bad update.
In future this might be improved by utilizing other `vim.pack`
features or via a dedicated function (like `vim.pack.restore()` that
restores all installed plugins to a state from the lockfile).
Problem: Changing `src` of an existing plugin cleanly requires manual
`vim.pack.del()` prior to executing `vim.pack.add()` with a new `src`.
Solution: Autodetect `src` change for an existing plugin (by comparing
against lockfile data). If different - properly delete immediately and
treat this as new plugin installation.
Alternative solution might be to update `origin` remote in the
installed plugin after calling `vim.pack.update()`. Although, doable,
this 1) requires more code; and 2) works only for Git plugins (which
might be not the only type of plugins in the future). Automatic
"delete and clean install" feels more robust.
Problem: Plain `vim.pack.add()` calls (with default `opts.load`) does
not fully work if called inside 'plugin/' runtime directory. In
particular, 'plugin/' files of newly added plugins are not sourced.
This is because `opts.load` is `false` during the whole startup, which
means `:packadd!` is used (modify 'runtimepath' but not force source
newly added 'plugin/' files).
This use case is common due to users organizing their config as
separate files in '~/.config/nvim/plugin/'.
Solution: Use newly added `v:vim_did_init` to decide default `opts.load`
value instead of `v:vim_did_enter`.
Problem: Current requirement is Git>=2.36 as `--also-filter-submodules`
flag for `git clone` was introduced there. This is problematic since
default Git version on Ubuntu 22.04 is 2.34.
Solution: Relax minimal Git version to be (at least) 2.0 by selectively
applying necessary flags based on the current Git version.
As 2.0.0 was released in 2014-05-28 (almost the same age as Neovim
project itself), it is reasonable to drop any mention and checks on
minimal version altogether.
Problem:
Nvim does not recognize URI scheme with numeric characters. While rare, there
are URIs that contain numbers (e.g. [ed2k://](https://en.wikipedia.org/wiki/Ed2k_URI_scheme))
and characters like `+` (e.g. `svn+ssh`). I use it in
[distant.nvim](https://github.com/chipsenkbeil/distant.nvim) to support
multiple, distinct connections using `distant+1234://` as the scheme.
Otherwise, if you open a file with the same name & path on two different
machines from the same Nvim instance, their buffer names will conflict
when just using `distant://`.
Solution:
Adds full support for detecting URI scheme per
[RFC3986](https://www.rfc-editor.org/rfc/rfc3986#section-3.1)