[vim/vim] Drawing artifacts and weird cursor movement when `prop_type_delete()` is called while buffer contains virtual text (Issue #11655)

44 views
Skip to first unread message

bfrg

unread,
Dec 2, 2022, 12:49:48 PM12/2/22
to vim/vim, Subscribed

Steps to reproduce

  1. Run vim --clean test.vim -S test.vim, with
vim9script

colorscheme habamax
prop_type_add('test', {highlight: 'ErrorMsg'})
prop_add(1, 0, {
    type: 'test',
    text: 'The quick brown fox jumps over the lazy dog',
    text_align: 'below',
    text_padding_left: 4,
})
prop_add(1, 0, {
    type: 'test',
    text: 'The quick brown fox jumps over the lazy dog',
    text_align: 'below',
    text_padding_left: 4,
})
prop_add(1, 0, {
    type: 'test',
    text: 'The quick brown fox jumps over the lazy dog',
    text_align: 'below',
    text_padding_left: 4,
})
prop_type_delete('test')
normal! G
  1. Result: The cursor is drawn below the last buffer line (see screenshot below).
  2. Move the cursor to the first line with gg, then press j.
  3. Result: The cursor jumps straight to the 5th line.

screenshot-2022-12-02_172635

Expected behaviour

I'm not sure what the correct behavior should be. Maybe: when a text-property
type is deleted with prop_type_delete('mytype'), all text-properties using this
type should be removed as well. If no bufnr is passed to prop_type_delete(),
this would mean removing all text-properties in all buffers.

Additional context

I encountered this bug after removing text-properties while the buffer was in
one state, and then running :undo to go back to an earlier state. It resulted
in text-properties re-appearing in the buffer. This got me thinking: in some use
cases this is desired while in other cases text-properties need to be removed
"permanently", i.e. after an :undo they shouldn't re-appear. An example would
be a plugin that provides some kind of syntax highlighting. If the plugin is
turned off, the text-properties need to be removed and shouldn't show up after
:undo.

There are several ways to accomplish this:

  1. Use listener_add() and call prop_remove() whenever a text-property
    re-appears.
  2. Same as 1., but use TextChanged instead.
  3. Use prop_type_delete() (currently has bugs).

Alternatives:

  1. Add a new option to prop_add() (or prop_type_define()) that tells Vim
    to add the text-properties only to the current buffer state.
  2. Add a new option to prop_remove() that tells Vim to remove the
    text-property from all buffer states, not just the current one.

Version of Vim

9.0.982

Environment

Linux

Logs and stack traces

No response


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11655@github.com>

Bram Moolenaar

unread,
Dec 2, 2022, 3:36:08 PM12/2/22
to vim/vim, Subscribed


> ### Steps to reproduce
>
> 1. Run `vim --clean test.vim -S test.vim`, with
>
> ```vim

> vim9script
>
> colorscheme habamax
> prop_type_add('test', {highlight: 'ErrorMsg'})
> prop_add(1, 0, {
> type: 'test',
> text: 'The quick brown fox jumps over the lazy dog',
> text_align: 'below',
> text_padding_left: 4,
> })
> prop_add(1, 0, {
> type: 'test',
> text: 'The quick brown fox jumps over the lazy dog',
> text_align: 'below',
> text_padding_left: 4,
> })
> prop_add(1, 0, {
> type: 'test',
> text: 'The quick brown fox jumps over the lazy dog',
> text_align: 'below',
> text_padding_left: 4,
> })
> prop_type_delete('test')
> normal! G
> ```
>
> 2. Result: The cursor is drawn below the last buffer line (see
> screenshot below).
> 3. Move the cursor to the first line with `gg`, then press `j`.
> 4. Result: The cursor jumps straight to the 5th line.

In other words: although the text properties are not displayed, they are
counted for positioning the cursor. That's a bug.

> ### Expected behaviour

>
> I'm not sure what the correct behavior should be. Maybe: when a
> text-property type is deleted with `prop_type_delete('mytype')`, all

> text-properties using this type should be removed as well. If no
> `bufnr` is passed to `prop_type_delete()`, this would mean removing
> all text-properties in _all_ buffers.

That is not practical, there could be many text properties, deleting
them might take a considerable effort. And it's not unlikely the buffer
is going to be closed, which means all the work would have been
a waste of time.

> ### Additional context

>
> I encountered this bug after removing text-properties while the buffer
> was in one state, and then running `:undo` to go back to an earlier
> state. It resulted in text-properties re-appearing in the buffer. This
> got me thinking: in some use cases this is desired while in other
> cases text-properties need to be removed "permanently", i.e. after an
> `:undo` they shouldn't re-appear. An example would be a plugin that
> provides some kind of syntax highlighting. If the plugin is turned
> off, the text-properties need to be removed and shouldn't show up
> after `:undo`.

Text properties are stored together with the text. Undo and redo
applies to both. This cannot be changed.


> There are several ways to accomplish this:
> 1. Use `listener_add()` and call `prop_remove()` whenever a text-property
> re-appears.
> 2. Same as 1., but use `TextChanged` instead.
> 3. Use `prop_type_delete()` (currently has bugs).

Using prop_type_delete() will make sure the text properties won't be
used. The bugs related to this need to be fixed.

> Alternatives:
> 1. Add a new option to `prop_add()` (or `prop_type_define()`) that tells Vim
> to add the text-properties only to the _current_ buffer state.

I don't know what "current buffer state" means.

> 2. Add a new option to `prop_remove()` that tells Vim to remove the

> text-property from all buffer states, not just the current one.

What does "all buffer states" mean?

I don't think we need to do more than fix the display and cursor
position computations. I'll use the repro case to find what I can now,
there most likely are a few more. Please provide a repro case if you
find one, preferably in a form it can be used for a regression test.

--
hundred-and-one symptoms of being an internet addict:
211. Your husband leaves you...taking the computer with him and you
call him crying, and beg him to bring the computer back.

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11655/1335816699@github.com>

Bram Moolenaar

unread,
Dec 2, 2022, 3:47:17 PM12/2/22
to vim/vim, Subscribed

Closed #11655 as completed via 89469d1.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/11655/issue_event/7943660698@github.com>

bfrg

unread,
Dec 2, 2022, 4:05:03 PM12/2/22
to vim/vim, Subscribed

Thanks for the quick fix. With "buffer state" I meant the current state in the undo history or buffer history, while pressing u or <C-r>. Not sure what else to call it.

So what is the recommended way to permanently remove the text-properties during a vim session? So that the highlightings don't reappear after undo or redo? The easiest way seems to be with prop_type_delete().


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11655/1335843712@github.com>

bfrg

unread,
Dec 4, 2022, 12:58:10 PM12/4/22
to vim/vim, Subscribed

Here's a small example that illustrates what I mean. The script does the following:

  1. adds text to buffer
  2. highlights text using text-properties
  3. modifies the line that contains text-properties (the highlighted text is not touched)
  4. removes all text-properties
  5. undo last change
  6. result: the previous highlighting reappears

Run vim --clean -S test.vim, with:

vim9script
prop_type_add('test', {highlight: 'ErrorMsg'})
setline(1, 'one two three four')
prop_add(1, 9, {type: 'test', length: 5})
&undolevels = &undolevels
normal! dw
prop_remove({type: 'test', all: true})
undo


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11655/1336478923@github.com>

Bram Moolenaar

unread,
Dec 4, 2022, 3:44:04 PM12/4/22
to vim/vim, Subscribed

This is what I expect to happen. Let me repeat:


"Text properties are stored together with the text. Undo and redo
applies to both. This cannot be changed."

In other words: when saving the text for undo, the text properties are saved as well.
When restoring the text with an undo command, the text properties are also restored.
In a way the text properties are part of the text.

Making changes is a linear sequence of events. Undo goes back through those events.
Adding and remove text properties is part of that. It's not like you can create a parallel universe and jump between the two.

Depending on what added the text property, perhaps you can check the changed lines (no matter if it was a new change or an undo) and add/remove text properties for the current text. I can't really think of what else would be done.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11655/1336512779@github.com>

Illia Bobyr

unread,
Dec 5, 2022, 7:43:10 PM12/5/22
to vim/vim, Subscribed

This fix is causing extra full screen redraws.
I've opened a bug to address it: #11666


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/11655/1338494523@github.com>

Reply all
Reply to author
Forward
0 new messages