Commit Graph

6811 Commits

Author SHA1 Message Date
zeertzjq
34a786bc49 fix(extmarks): inline virt_text support multiple hl groups (#25303) 2023-09-22 14:21:58 +08:00
Sergey Slipchenko
345bd91db2 fix(lsp): handle absence of a trailing newline #25194
Fixes #24339

rust-analyzer sends "Invalid offset" error in such cases. Some other
servers handle it specially.

LSP spec mentions that "A range is comparable to a selection in an
editor". Most editors don't handle trailing newlines the same way
Neovim/Vim does, it's clearly visible if it's present or not. With that
in mind it's understandable why sending end position as simply the start
of the line after the last one is considered invalid in such cases.
2023-09-21 03:06:40 -07:00
bfredl
f246cf029f Merge pull request #25270 from bfredl/indeterminism
fix(test): fix "indeterminism" warnings in UI tests
2023-09-21 09:36:41 +02:00
zeertzjq
e25cf47ad3 fix(mouse): click on empty line with 'foldcolumn' 2023-09-21 11:13:48 +08:00
zeertzjq
acc32f20be test(ui/float_spec): click in bordered float sets correct curswant 2023-09-21 09:55:47 +08:00
zeertzjq
adb73772d9 vim-patch:9.0.1919: Wrong curswant when clicking on empty line or with vsplits
Problem:  Wrong curswant when clicking on empty line or with vsplits.
Solution: Don't check for ScreenCols[] before the start of the window
          and handle empty line properly.

closes: vim/vim#13132

03cd697d63
2023-09-21 09:43:12 +08:00
zeertzjq
dc6c11394b fix(statuscolumn): update number hl for each screen line (#25277) 2023-09-21 07:03:26 +08:00
bfredl
380b634ac9 fix(test): fix "indeterminism" warnings in UI tests 2023-09-20 21:51:57 +02:00
Ibby
23c21e7630 fix(extmarks): account for rightleft when drawing virt text (#25262)
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
2023-09-20 22:39:54 +08:00
zeertzjq
818d7f6daf fix(extmarks): fix win_col virt_text drawn on wrong screen line (#25264) 2023-09-20 21:48:12 +08:00
bfredl
acde86d436 Merge pull request #25096 from glepnir/float_winnew
fix(float): trigger winnew event when float window create
2023-09-20 09:25:59 +02:00
bfredl
c6cc56d69c Merge pull request #25155 from glepnir/fix_winhl
fix(highlight): winhl receive wrong argument
2023-09-20 09:18:59 +02:00
Maria José Solano
b2265bb72c test(lsp): add normalize_markdown tests 2023-09-20 07:00:52 +01:00
Maria José Solano
cfd4a9dfaf feat(lsp): use treesitter for stylize markdown 2023-09-19 14:47:37 +01:00
zeertzjq
c5abf487f1 fix(float): make "fixed" work with relative=win (#25243) 2023-09-19 18:45:11 +08:00
glepnir
437ed3cee2 fix(float): trigger winnew event when float window create 2023-09-19 18:44:48 +08:00
bfredl
1db45a9c1f Merge pull request #25214 from bfredl/glyphcache
refactor(grid): change schar_T representation to be more compact
2023-09-19 12:32:41 +02:00
glepnir
ab92575753 fix(highlight): winhl receive wrong argument 2023-09-19 18:05:59 +08:00
bfredl
2de5cddeb1 Merge pull request #25148 from glepnir/fixed_opt
fix(float): add fixed option
2023-09-19 11:49:59 +02:00
bfredl
8da986ea87 refactor(grid): change schar_T representation to be more compact
Previously, a screen cell would occupy 28+4=32 bytes per cell
as we always made space for up to MAX_MCO+1 codepoints in a cell.

As an example, even a pretty modest 50*80 screen would consume

50*80*2*32 = 256000, i e a quarter megabyte

With the factor of two due to the TUI side buffer, and even more when
using msg_grid and/or ext_multigrid.

This instead stores a 4-byte union of either:
- a valid UTF-8 sequence up to 4 bytes
- an escape char which is invalid UTF-8 (0xFF) plus a 24-bit index to a
  glyph cache

This avoids allocating space for huge composed glyphs _upfront_, while
still keeping rendering such glyphs reasonably fast (1 hash table lookup
+ one plain index lookup). If the same large glyphs are using repeatedly
on the screen, this is still a net reduction of memory/cache
consumption. The only case which really gets worse is if you blast
the screen full with crazy emojis and zalgo text and even this case
only leads to 4 extra bytes per char.

When only <= 4-byte glyphs are used, plus the 4-byte attribute code,
i e 8 bytes in total there is a factor of four reduction of memory use.
Memory which will be quite hot in cache as the screen buffer is scanned
over in win_line() buffer text drawing

A slight complication is that the representation depends on host byte
order. I've tested this manually by compling and running this
in qemu-s390x and it works fine. We might add a qemu based solution
to CI at some point.
2023-09-19 11:25:31 +02:00
glepnir
fd08fd3de3 fix(float): add fixd option 2023-09-18 18:21:14 +08:00
zeertzjq
9cadbf1d36 test(tui_spec): update cursor_address test for wrap flag (#25228) 2023-09-18 12:16:32 +08:00
zeertzjq
508dda0e6c test(ui/fold_spec): more testing for clicking on 'foldcolumn' (#25225) 2023-09-18 07:07:54 +08:00
zeertzjq
f54677132b test(ui/fold_spec): click on multibyte "foldclosed" (#25216) 2023-09-17 21:31:51 +08:00
zeertzjq
71530cc972 feat(folds): support virtual text format for 'foldtext' (#25209)
Co-authored-by: Lewis Russell <lewis6991@gmail.com>
2023-09-17 20:29:18 +08:00
bfredl
a0c99755b8 Merge pull request #25190 from glepnir/echo_hl
fix(highlight): correct hi command output
2023-09-17 12:23:22 +02:00
glepnir
5183651773 fix(highlight): correct hi command output 2023-09-17 17:47:51 +08:00
Phelipe Teles
4ab9c5fa46 fix(lua): not using global value in vim.opt_global (#25196) 2023-09-17 06:35:12 +08:00
zeertzjq
054839437e test(plugin/man_spec): use pesc() on actual_file in pattern (#25199) 2023-09-17 06:07:53 +08:00
L Lllvvuu
908843df61 fix(languagetree): apply resolve_lang to metadata['injection.language']
`resolve_lang` is applied to `@injection.language` when it's supplied as a
capture:

f5953edbac/runtime/lua/vim/treesitter/languagetree.lua (L766-L768)

If we want to support `metadata['injection.language']` (as per #22518 and
[tree-sitter upstream](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection))
then the behavior should be consistent.

Fixes: nvim-treesitter/nvim-treesitter#4918
2023-09-16 11:12:06 +01:00
bfredl
40bfca744d Merge pull request #25183 from llllvvuu/fix/marktree_move
fix(marktree): off-by-one error in `marktree_move`
2023-09-16 10:39:54 +02:00
bfredl
2d2cf150e1 Merge pull request #25078 from glepnir/au
fix(float): don't trigger au event when enter is false
2023-09-16 10:27:45 +02:00
L Lllvvuu
585549625d fix(marktree): off-by-one error in marktree_move
If you would insert element X at position j, then if you are moving that
same element X from position i < j, you should move it to position j -
1, because you are losing an element.

This error caused a gap to be left in the array, so that it looked like
[x, null, y] instead of [x, y], where len = 2. This triggered #25147.

Fixes: #25147
2023-09-16 01:12:15 -07:00
zeertzjq
35e50d79c6 fix(extmarks): overlay virt_text position after 'showbreak' (#25175)
Also make virt_text_hide work properly.
2023-09-15 20:30:50 +08:00
glepnir
a916523574 fix(ui): doesn't trigger au event when enter is false 2023-09-15 19:18:01 +08:00
Ilia Choly
f5a09f1b03 fix: invoke changed_bytes when rewriting <Tab> char #25125
When tabstop and shiftwidth are not equal, tabs are inserted as individual
spaces and then rewritten as tab characters in a second pass. That second pass
did not call changed_bytes which resulted in events being omitted.

Fixes #25092
2023-09-15 03:45:51 -07:00
dundargoc
2d9e7a33f4 test(windows): unskip working tests (#25153)
Also simplify home detection with os_homedir()
2023-09-15 16:33:26 +08:00
zeertzjq
a6e4793baf fix(extmarks): draw virt_text below diff filler lines properly (#25170)
fix(extmarks): draw virt_text properly below diff filler lines
2023-09-15 15:56:52 +08:00
zeertzjq
b65cd7ff1a fix(extmarks): fix wrong virt_text position after wrapped TAB (#25168) 2023-09-15 14:54:42 +08:00
zeertzjq
b52bd8a2de fix(extmarks): properly handle virt_text on next screen line (#25166)
TODO: virt_text_hide doesn't work for the first char on a wrapped screen
line, and it's not clear how to fix that.
2023-09-15 12:35:27 +08:00
zeertzjq
f5953edbac fix(float): update position of anchored windows first (#25133) 2023-09-14 07:42:22 +08:00
bfredl
b04286a187 feat(extmark): support proper multiline ranges
The removes the previous restriction that nvim_buf_set_extmark()
could not be used to highlight arbitrary multi-line regions

The problem can be summarized as follows: let's assume an extmark with a
hl_group is placed covering the region (5,0) to (50,0) Now, consider
what happens if nvim needs to redraw a window covering the lines 20-30.
It needs to be able to ask the marktree what extmarks cover this region,
even if they don't begin or end here.

Therefore the marktree needs to be augmented with the information covers
a point, not just what marks begin or end there. To do this, we augment
each node with a field "intersect" which is a set the ids of the
marks which overlap this node, but only if it is not part of the set of
any parent. This ensures the number of nodes that need to be explicitly
marked grows only logarithmically with the total number of explicitly
nodes (and thus the number of of overlapping marks).

Thus we can quickly iterate all marks which overlaps any query position
by looking up what leaf node contains that position. Then we only need
to consider all "start" marks within that leaf node, and the "intersect"
set of that node and all its parents.

Now, and the major source of complexity is that the tree restructuring
operations (to ensure that each node has T-1 <= size <= 2*T-1) also need
to update these sets. If a full inner node is split in two, one of the
new parents might start to completely overlap some ranges and its ids
will need to be moved from its children's sets to its own set.
Similarly, if two undersized nodes gets joined into one, it might no
longer completely overlap some ranges, and now the children which do
needs to have the have the ids in its set instead. And then there are
the pivots! Yes the pivot operations when a child gets moved from one
parent to another.
2023-09-12 10:38:23 +02:00
Jaehwang Jung
65738202f8 fix(decorations): better approximation of botline #24794
Problem:
* The guessed botline might be smaller than the actual botline e.g. when
  there are folds and the user is typing in insert mode. This may result
  in incorrect treesitter highlights for injections.
* botline can be larger than the last line number of the buffer, which
  results in errors when placing extmarks.

Solution:
* Take a more conservative approximation. I am not sure if it is
  sufficient to guarantee correctness, but it seems to be good enough
  for the case mentioned above.
* Clamp it to the last line number.

Co-authored-by: Lewis Russell <me@lewisr.dev>
2023-09-11 12:29:39 -07:00
Sergey Slipchenko
f859d16aea fix(tests): set SHELL=sh #24941
Problem:
Some tests fail with $SHELL=fish #6172
Related: https://github.com/neovim/neovim/pull/6176

Solution:
Replace "echo -n" with "printf", because "echo" in sh may be provided
as a shell builtin, which does not accept an "-n" flag to avoid a
trailing newline (e.g. on macos). "printf" is more portable (defined by
POSIX) and it does not output a trailing newline by itself.
Fixes #6172

TODO:
Other test failures may be related to "session leader" issue: https://github.com/neovim/neovim/issues/2354
Checked by running `:terminal ./build/bin/tty-test` from Nvim with
`shell=/bin/fish` (inherited from `$SHELL`) and it indeed complains
about "process does not own the terminal". With `shell=sh` it doesn't complain. And
unsetting `$SHELL` seems to make `nvim` to fall back to `shell=sh`.

    FAILED   test/functional/terminal/tui_spec.lua @ 1017: TUI paste: terminal mode
    test/functional/terminal/tui_spec.lua:1024: Row 1 did not match.
    Expected:
      |*tty ready                                         |
      |*{1: }                                                 |
      |*                                                  |
      |                                                  |
      |{5:^^^^^^^                                           }|
      |{3:-- TERMINAL --}                                    |
      |{3:-- TERMINAL --}                                    |
    Actual:
      |*process does not own the terminal                 |
      |*                                                  |
      |*[Process exited 2]{1: }                               |
      |                                                  |
      |{5:^^^^^^^                                           }|
      |{3:-- TERMINAL --}                                    |
      |{3:-- TERMINAL --}                                    |

    To print the expect() call that would assert the current screen state, use
    screen:snapshot_util(). In case of non-deterministic failures, use
    screen:redraw_debug() to show all intermediate screen states.

    stack traceback:
        test/functional/ui/screen.lua:622: in function '_wait'
        test/functional/ui/screen.lua:352: in function 'expect'
        test/functional/terminal/tui_spec.lua:1024: in function <test/functional/terminal/tui_spec.lua:1017>

    FAILED   test/functional/terminal/tui_spec.lua @ 1551: TUI forwards :term palette colors with termguicolors
    test/functional/terminal/tui_spec.lua:1567: Row 1 did not match.
    Expected:
      |*{1:t}ty ready                                         |
      |                                                  |
      |*                                                  |
      |                                                  |
      |{2:^^^^^^^                                           }|
      |                                                  |
      |{3:-- TERMINAL --}                                    |
    Actual:
      |*{1:p}rocess does not own the terminal                 |
      |                                                  |
      |*[Process exited 2]                                |
      |                                                  |
      |{2:^^^^^^^                                           }|
      |                                                  |
      |{3:-- TERMINAL --}                                    |

    To print the expect() call that would assert the current screen state, use
    screen:snapshot_util(). In case of non-deterministic failures, use
    screen:redraw_debug() to show all intermediate screen states.

    stack traceback:
        test/functional/ui/screen.lua:622: in function '_wait'
        test/functional/ui/screen.lua:352: in function 'expect'
        test/functional/terminal/tui_spec.lua:1567: in function <test/functional/terminal/tui_spec.lua:1551>
2023-09-11 10:01:00 -07:00
Sergey Slipchenko
d22172f36b fix(api): more intuitive cursor updates in nvim_buf_set_text
Fixes #22526
2023-09-11 08:16:03 +04:00
zeertzjq
2b475cb5cc fix(mouse): click on 'statuscolumn' with 'rightleft' (#25090) 2023-09-11 08:29:33 +08:00
Sergey Slipchenko
af0684f0d5 test: unignore test which froze sourcehut (#25067) 2023-09-11 05:53:05 +08:00
Grace Petryk
5e3cf9fb4b feat(lsp): improve control over placement of floating windows (#24494) 2023-09-10 10:02:23 +02:00
glepnir
8afb3a49c0 fix(highlight): add create param in nvim_get_hl 2023-09-09 17:15:58 +08:00
bfredl
5970157e1d refactor(map): enhanced implementation, Clean Code™, etc etc
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.
2023-09-08 12:48:46 +02:00