This involves two redesigns of the map.c implementations:
1. Change of macro style and code organization
The old khash.h and map.c implementation used huge #define blocks with a
lot of backslash line continuations.
This instead uses the "implementation file" .c.h pattern. Such a file is
meant to be included multiple times, with different macros set prior to
inclusion as parameters. we already use this pattern e.g. for
eval/typval_encode.c.h to implement different typval encoders reusing a
similar structure.
We can structure this code into two parts. one that only depends on key
type and is enough to implement sets, and one which depends on both key
and value to implement maps (as a wrapper around sets, with an added
value[] array)
2. Separate the main hash buckets from the key / value arrays
Change the hack buckets to only contain an index into separate key /
value arrays
This is a common pattern in modern, state of the art hashmap
implementations. Even though this leads to one more allocated array, it
is this often is a net reduction of memory consumption. Consider
key+value consuming at least 12 bytes per pair. On average, we will have
twice as many buckets per item.
Thus old implementation:
2*12 = 24 bytes per item
New implementation
1*12 + 2*4 = 20 bytes per item
And the difference gets bigger with larger items.
One might think we have pulled a fast one here, as wouldn't the average size of
the new key/value arrays be 1.5 slots per items due to amortized grows?
But remember, these arrays are fully dense, and thus the accessed memory,
measured in _cache lines_, the unit which actually matters, will be the
fully used memory but just rounded up to the nearest cache line
boundary.
This has some other interesting properties, such as an insert-only
set/map will be fully ordered by insert only. Preserving this ordering
in face of deletions is more tricky tho. As we currently don't use
ordered maps, the "delete" operation maintains compactness of the item
arrays in the simplest way by breaking the ordering. It would be
possible to implement an order-preserving delete although at some cost,
like allowing the items array to become non-dense until the next rehash.
Finally, in face of these two major changes, all code used in khash.h
has been integrated into map.c and friends. Given the heavy edits it
makes no sense to "layer" the code into a vendored and a wrapper part.
Rather, the layered cake follows the specialization depth: code shared
for all maps, code specialized to a key type (and its equivalence
relation), and finally code specialized to value+key type.
Problem: use-after-free in do_ecmd
Solution: Verify oldwin pointer after reset_VIsual()
e1dc9a6275
N/A patches for version.c:
vim-patch:9.0.1841: style: trailing whitespace in ex_cmds.c
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: Wrong cursor position with virtual text before double-width
char at window edge.
Solution: Check for double-width char before adding virtual text size.
closes: vim/vim#12977ac2d8815ae
This fixes the issue where the LspNotify handlers for inlay_hint /
diagnostics would end up refreshing all attached clients.
The handler would call util._refresh, which called
vim.lsp.buf_request, which calls the method on all attached clients.
Now util._refresh takes an optional client_id parameter, which is used
to specify a specific client to update.
This commit also fixes util._refresh's handling of the `only_visible`
flag. Previously if `only_visible` was false, two requests would be made
to the server: one for the visible region, and one for the entire file.
Co-authored-by: Stanislav Asunkin <1353637+stasjok@users.noreply.github.com>
Co-authored-by: Mathias Fußenegger <mfussenegger@users.noreply.github.com>
Problem: Wrong cursor position with virtual text before a whitespace
character and 'linebreak'.
Solution: Always set "col_adj" to "size - 1" and apply 'linebreak' after
adding the size of 'breakindent' and 'showbreak'.
closes: vim/vim#129566e55e85f92
N/A patches:
vim-patch:9.0.1826: keytrans() doesn't translate recorded key typed in a GUI
Unfortunately the gc=false objects can refer to a dangling tree if the
gc=true tree was freed first. This reuses the same tree object as the
node itself is keeping alive via the uservalue of the node userdata.
(wrapped in a table due to lua 5.1 restrictions)
Problem: `push_tree`, every time its called for the same TSTree with
`do_copy=false` argument, creates a new userdata for it. Each userdata,
when garbage collected, frees the same TSTree C object.
Solution: Add flag to userdata, which indicates, should C object,
which userdata points to, be freed, when userdata is garbage collected.
Some more reasonable defaults for topline:
- if topline was replaced with another line, that now becomes topline
- if line was inserted just before topline, display it. This is more
similar to the previous API behavior.
Problem: Multiline regex with Visual selection fails when Visual
selection contains virtual text after last char.
Solution: Only include virtual text after last char when getting full
line length.
closes: vim/vim#12908e3daa06be1
Problem: Cursor position still wrong with 'showbreak' and virtual text
after last character or 'listchars' "eol".
Solution: Remove unnecessary w_wcol adjustment in curs_columns(). Also
fix first char of virtual text not shown at the start of a screen
line.
closes: vim/vim#12478closes: vim/vim#12532closes: vim/vim#129046a3897232a
Problem:
'endofline' can be used to detect if a file ends of <EOL>, however
editorconfig can break this.
Solution:
Set 'endofline' during BufWritePre
Fixes: #24869
Problem: Normal mode "gM", "gj", "gk" commands behave incorrectly with
virtual text.
Solution: Use linetabsize() instead of linetabsize_str().
closes: vim/vim#12909d809c0a903
The change in #248240081549 was not a regression, however it was an
incomplete change. Unfortunately some common plugins come to depend on
this exising self-inconsistent behavior. These plugins are going to need
to update for 0.10
nvim_buf_set_lines used to NOT adjust the topline correctly if a buffer
was displayed in just one window. However, if displayed in multiple
windows, it was correctly adjusted for any window not deemed the
current window for the buffer (which could be an arbitrary choice if the
buffer was not already current, as noted in the last rafactor)
This fixes so that all windows have their topline adjusted. The added
tests show this behavior, which should be the reasonable one.
Problem: Now way to show text at the bottom part of floating window
border (a.k.a. "footer").
Solution: Allows `footer` and `footer_pos` config fields similar to
`title` and `title_pos`.
Most of the messy things when changing a non-current buffer is
not about the buffer, it is about windows. In particular, it is about
`curwin`.
When editing a non-current buffer which is displayed in some other
window in the current tabpage, one such window will be "borrowed" as the
curwin. But this means if two or more non-current windows displayed the buffers,
one of them will be treated differenty. this is not desirable.
In particular, with nvim_buf_set_text, cursor _column_ position was only
corrected for one single window. Two new tests are added: the test
with just one non-current window passes, but the one with two didn't.
Two corresponding such tests were also added for nvim_buf_set_lines.
This already worked correctly on master, but make sure this is
well-tested for future refactors.
Also, nvim_create_buf no longer invokes autocmds just because you happened
to use `scratch=true`. No option value was changed, therefore OptionSet
must not be fired.
Problem: wrong cursor position with 'showbreak' and lcs-eol
Solution: Add size of 'showbreak' before when 'listchars' "eol" is used.
Also fix wrong cursor position with wrapping virtual text on
empty line and 'showbreak'.
closes: vim/vim#128911193951beb
Problem: sidescrolloff and scrolloff options work slightly
different than other global-local options
Solution: Make it behave consistent for all global-local options
It was noticed, that sidescrolloff and scrolloff options behave
differently in comparison to other global-local window options like
'listchars'
So make those two behave like other global-local options. Also add some
extra documentation for a few special local-window options.
Add a few tests to make sure all global-local window options behave
similar
closes: vim/vim#12956closes: vim/vim#126434a8eb6e7a9
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: Wrong display with wrapping virtual text or unprintable chars,
'showbreak' and 'smoothscroll'.
Solution: Don't skip cells taken by 'showbreak' in screen lines before
"w_skipcol". Combined "n_skip" and "skip_cells".
closes: vim/vim#12597b557f48982
Problem: Using freed memory when 'tagfunc' wipes out buffer that holds
'complete'.
Solution: Make a copy of the option. Make sure cursor position is valid.
0ff01835a4
Cherry-pick a cmdwin change from patch 9.0.0500.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem: Using setbufvar() may change the window title.
Solution: Do not redraw when creating the autocommand window. (closesvim/vim#9613)
dff97e65eb
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem: state() test fails on some Mac systems.
Solution: Increase the wait time. (closesvim/vim#4983)
b7a97ef340
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem: No tests for state().
Solution: Add tests. Clean up some feature checks. Make "a" flag work.
c258549032
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem: Cursor is adjusted in window that did not change in size by
'splitkeep'.
Solution: Only check that cursor position is valid in a window that
has changed in size.
closes: vim/vim#1250916af913eee
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>