If I populate a buffer with setline()
and then I make some changes, each change becomes an undo step as expected.
If the buffer is populated from the output of a command spawn by job_start()
, however, the same changes are not recorded in the undotree.
To reproduce:
vim --clean test.vim
, where test.vim
is the following script:vim9script var input = '' def Filter() while true redraw var c = getcharstr() if char2nr(c) == 0x80 || char2nr(c) < 0x20 break endif input ..= c execute $'g!:\m{input}:norm "_dd' echomsg $'Char={c} seq_cur={undotree()["seq_cur"]}' endwhile enddef def FilterItems() new setline(1, ['abcdf', 'abcee', 'abdde', 'accde', 'bbcde']) Filter() enddef def FilterCmdOutput() new const nr = bufnr() job_start(['echo', "abcdf\nabcee\nabdde\naccde\nbbcde"], { 'close_cb': (ch) => Filter(), 'out_io': 'buffer', 'out_buf': nr, }) enddef # FilterItems() FilterCmdOutput()
:source %
abcde
, then Esc. Each key press removes a line from the buffer.:messages
.The output in messages is:
Char=a seq_cur=5
Char=b seq_cur=5
Char=c seq_cur=5
Char=d seq_cur=5
Char=e seq_cur=5
Note how seq_cur
does not increase. If you run the same script, but uncomment FilterItems()
instead of FilterCmdOutput()
, the output is:
Char=a seq_cur=2
Char=b seq_cur=3
Char=c seq_cur=4
Char=d seq_cur=5
Char=e seq_cur=6
Now seq_cur
was increased after each key press.
I would expect seq_cur
to increase every time Filter()
is called, regardless of how the text was added to the buffer. In particular, I would expect the script above to record the following output:
Char=a seq_cur=5
Char=b seq_cur=6
Char=c seq_cur=7
Char=d seq_cur=8
Char=e seq_cur=9
9.1.494
macOS 14.5
Apple Terminal
xterm-256color
ZSH 5.9
No response
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
According to :help undojoin
, calling getchar()
should start a new change. That does not seem to be the case if the code using getchar()
is in a callback.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
According to
:help undojoin
, callinggetchar()
should start a new change. That does not seem to be the case if the code usinggetchar()
is in a callback.
I don't think that's the case. It just recommends that you use :undojoin
before calling getchar()
.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
I agree with @zeertzjq reading of the help.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
I beg to disagree. The help describes a case where undojoin
is necessary to merge two changes with a getchar()
in between exactly because
the next key press will start a new change
In fact, that is what happens:
vim9script def Foo() normal aX getchar() normal aY undo enddef Foo()
X
remains in the buffer after the undo. But if the function is used as a callback, it behaves as if undojoin
has been added. That is, the following script:
vim9script def Foo() normal aX getchar() normal aY undo enddef job_start(['ls'], {'close_cb': (_) => Foo()})
behaves the same as:
vim9script def Foo() normal aX getchar() undojoin normal aY undo enddef Foo()
I would like the function invoked as a job_start()
's callback to behave the same as if invoked directly.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
A workaround for this issue is to force a new change:
def Foo() normal aX getchar
() execute "normal" "i\<c-g>u" normal aY undo enddef
Similarly, my original example is fixed by adding execute "normal" "i\<c-g>u"
before (or after) getcharstr()
.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.