The Lua modules that make up vim.lua are embedded as raw source files into the
nvim binary. These sources are loaded by the Lua runtime on startuptime. We can
pre-compile these sources into Lua bytecode before embedding them into the
binary, which minimizes the size of the binary and improves startuptime.
* str_utf_start/end both cast the offset into the utf string
to a char_u, a pointer + long is well-defined and the cast is
unnecessary. This previously resulted in issues for offsets greater than
256.
refresh_scrollback assumes pending scrollback rows exist only if the
terminal window height decreased (or the screen was full).
However, after accumulating scrollback, it's possible in some cases for
the terminal height to increase before refresh_scrollback is called via
invalidation (especially when the terminal buffer isn't initially
displayed in a window before nvim_open_term), which may crash.
As we'll have enough room for some scrollback rows, just append them to
the top of the buffer until it fills the window, then continue with the
previous logic for any remaining scrollback rows if necessary.
When filling a quickfix/loclist from a string-typed VimL variable, the
complexity is O(N^2) in the number of lines in the variable.
The problem is caused by using `xstrlcpy(3)` to copy the characters from
the current position up to the next newline into the quickfix/loclist
buffer in a loop.
strlcpy(3) returns the length of `src`, so by necessity it has to
compute `strlen(src)`. This means scanning the full rest of the typval
on every iteration while only copying a small fraction (up to the next
'\n').
This is not a problem whenever the srclen-to-copylen ratio is close to
1, which it usually is. But not in this case. Since we already
calculated exactly how many bytes we want to copy, we should be using
memcpy(3).
This problem is not present in Vim, as it uses `vim_strncpy`, a
`strncpy(3)`-alike, which stops at either `\0` or `n`, whichever comes
first.
The quickfix/loclist window can be filled using a:
1. File (used by commands like :grep/:make/... to source directly
from their errorfile)
2. Buffer (used by :cbuffer and its variants)
3. Typval
a. String (used by :cexpr and its variants)
b. List of strings (used by setqflist(), setloclist(), :cepxr and its
variants)
This commit optimizes case (3a), especially when the typval is a long
string.
The pathological path is triggered by (e.g.) :grep enhancements as found
in https://gist.github.com/romainl/56f0c28ef953ffc157f36cc495947ab3:
function! Grep(...)
return system(join([&grepprg] + a:000), ' '))
endfunction
:cgetexpr Grep('foo')
It would've been better for Neovim to use `systemlist` here, before this
commit.
Fixes `q` in more pager, where `:highlight` can be quit out of with a
single `q` keystroke, while in `:lua print(vim.inspect(vim))` it just
scrolls down a page.
nvim_buf_get_extmark uses "end_row" rather than "end_line" in its
'details' dict, which means callers must modify the key names if they
want to re-use the information. Change the parameter name in
nvim_buf_set_extmark to "end_row" and use "end_line" as an alias
to make this more consistent.