patch 9.1.1782: buffer-listener callbacks may not match buffer content

Problem:  buffer-listener callbacks may not match buffer content, since
          they are buffered until the screen is updated.
Solution: Allow to handle buffer-callbacks un-buffered, meaning to
          handle those changes as soon as they happen (Paul Ollis).

fixes: #18183
closes: #18295

Signed-off-by: Paul Ollis <paul@cleversheep.org>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Paul Ollis
2025-09-21 18:53:40 +00:00
committed by Christian Brabandt
parent 3a6cf6d53b
commit e87d17ecfb
10 changed files with 490 additions and 113 deletions

View File

@ -1,4 +1,4 @@
*builtin.txt* For Vim version 9.1. Last change: 2025 Sep 18
*builtin.txt* For Vim version 9.1. Last change: 2025 Sep 21
VIM REFERENCE MANUAL by Bram Moolenaar
@ -369,7 +369,7 @@ lispindent({lnum}) Number Lisp indent for line {lnum}
list2blob({list}) Blob turn {list} of numbers into a Blob
list2str({list} [, {utf8}]) String turn {list} of numbers into a String
list2tuple({list}) Tuple turn {list} of items into a tuple
listener_add({callback} [, {buf}])
listener_add({callback} [, {buf} [, {unbuffered}]])
Number add a callback to listen to changes
listener_flush([{buf}]) none invoke listener callbacks
listener_remove({id}) none remove a listener callback
@ -6715,7 +6715,7 @@ list2tuple({list}) *list2tuple()*
Return type: tuple<{type}> (depending on the given |List|)
listener_add({callback} [, {buf}]) *listener_add()*
listener_add({callback} [, {buf} [, {unbuffered}]]) *listener_add()*
Add a callback function that will be invoked when changes have
been made to buffer {buf}.
{buf} refers to a buffer name or number. For the accepted
@ -6723,6 +6723,11 @@ listener_add({callback} [, {buf}]) *listener_add()*
buffer is used.
Returns a unique ID that can be passed to |listener_remove()|.
If the {buf} already has registered callbacks then the
equivalent of >
listener_flush({buf})
< is performed before the new callback is added.
The {callback} is invoked with five arguments:
bufnr the buffer that was changed
start first changed line number
@ -6765,20 +6770,37 @@ listener_add({callback} [, {buf}]) *listener_add()*
added 0
col first column with a change or 1
The entries are in the order the changes were made, thus the
most recent change is at the end. The line numbers are valid
when the callback is invoked, but later changes may make them
invalid, thus keeping a copy for later might not work.
When {unbuffered} is |FALSE| or not provided the {callback} is
invoked:
The {callback} is invoked just before the screen is updated,
when |listener_flush()| is called or when a change is being
made that changes the line count in a way it causes a line
number in the list of changes to become invalid.
1. Just before the screen is updated.
2. When |listener_flush()| is called.
3. When a change is being made that changes the line count in
a way that causes a line number in the list of changes to
become invalid.
The entries are in the order the changes were made, thus the
most recent change is at the end.
Because of the third trigger reason for triggering a callback
listed above, the line numbers passed to the callback are not
guaranteed to be valid. If this is a problem then make
{unbuffered} |TRUE|.
When {unbuffered} is |TRUE| the {callback} is invoked for every
single change. The changes list only holds a single dictionary
and the "start", "end" and "added" values in the dictionary are
the same as the corresponding callback arguments. The line
numbers are valid when the callback is invoked, but later
changes may make them invalid, thus keeping a copy for later
might not work.
The {callback} is invoked with the text locked, see
|textlock|. If you do need to make changes to the buffer, use
a timer to do this later |timer_start()|.
You may not call listener_add() during the {callback}. *E1569*
The {callback} is not invoked when the buffer is first loaded.
Use the |BufReadPost| autocmd event to handle the initial text
of a buffer.

View File

@ -4741,6 +4741,7 @@ E1565 remote.txt /*E1565*
E1566 remote.txt /*E1566*
E1567 remote.txt /*E1567*
E1568 options.txt /*E1568*
E1569 builtin.txt /*E1569*
E157 sign.txt /*E157*
E158 sign.txt /*E158*
E159 sign.txt /*E159*

View File

@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2025 Sep 18
*version9.txt* For Vim version 9.1. Last change: 2025 Sep 21
VIM REFERENCE MANUAL by Bram Moolenaar
@ -41736,6 +41736,8 @@ Functions: ~
- |matchfuzzy()| and |matchfuzzypos()| use an improved fuzzy matching
algorithm (same as fzy).
- |sha256()| also accepts a |Blob| as argument.
- |listener_add()| allows to register un-buffered listeners, so that chagnes
are handled as soon as they happen.
Others: ~
- the regex engines match correctly case-insensitive multi-byte characters