Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undo calls changed_lines before on_bytes #26499

Open
tomtomjhj opened this issue Dec 10, 2023 · 1 comment
Open

Undo calls changed_lines before on_bytes #26499

tomtomjhj opened this issue Dec 10, 2023 · 1 comment
Labels
bug issues reporting wrong behavior marks marks, extmarks, decorations, virtual text, namespaces

Comments

@tomtomjhj
Copy link
Contributor

tomtomjhj commented Dec 10, 2023

Problem

Undo (u) calls changed_lines() before adjusting extmarks (which triggers on_bytes):

neovim/src/nvim/undo.c

Lines 2378 to 2430 in 096211a

changed_lines(curbuf, top + 1, 0, bot, newsize - oldsize, do_buf_event);
// When text has been changed, possibly the start of the next line
// may have SpellCap that should be removed or it needs to be
// displayed. Schedule the next line for redrawing just in case.
if (spell_check_window(curwin) && bot <= curbuf->b_ml.ml_line_count) {
redrawWinline(curwin, bot);
}
// Set the '[ mark.
if (top + 1 < curbuf->b_op_start.lnum) {
curbuf->b_op_start.lnum = top + 1;
}
// Set the '] mark.
if (newsize == 0 && top + 1 > curbuf->b_op_end.lnum) {
curbuf->b_op_end.lnum = top + 1;
} else if (top + newsize > curbuf->b_op_end.lnum) {
curbuf->b_op_end.lnum = top + newsize;
}
u_newcount += newsize;
u_oldcount += oldsize;
uep->ue_size = oldsize;
uep->ue_array = newarray;
uep->ue_bot = top + newsize + 1;
// insert this entry in front of the new entry list
nuep = uep->ue_next;
uep->ue_next = newlist;
newlist = uep;
}
// Ensure the '[ and '] marks are within bounds.
if (curbuf->b_op_start.lnum > curbuf->b_ml.ml_line_count) {
curbuf->b_op_start.lnum = curbuf->b_ml.ml_line_count;
}
if (curbuf->b_op_end.lnum > curbuf->b_ml.ml_line_count) {
curbuf->b_op_end.lnum = curbuf->b_ml.ml_line_count;
}
// Adjust Extmarks
ExtmarkUndoObject undo_info;
if (undo) {
for (int i = (int)kv_size(curhead->uh_extmark) - 1; i > -1; i--) {
undo_info = kv_A(curhead->uh_extmark, i);
extmark_apply_undo(undo_info, undo);
}
// redo
} else {
for (int i = 0; i < (int)kv_size(curhead->uh_extmark); i++) {
undo_info = kv_A(curhead->uh_extmark, i);
extmark_apply_undo(undo_info, undo);
}
}

Normally, changed_lines() should be called after adjusting extmarks. This order is important because the result of changed_lines() may depend on the result of on_bytes. For example, changed_lines() updates folds, and the treesitter folding shifts foldlevels in on_bytes. So if changed_lines() is called before on_bytes, the folds can be wrong. See also #26364.

Steps to reproduce

repro.vim

function Fde()
  echom 'foldexpr' v:lnum
endfunction
set foldmethod=expr foldexpr=Fde()
lua vim.api.nvim_buf_attach(0, false, {on_bytes = function() print('on_bytes') end})
  1. Run
    nvim --clean
    :so repro.vim
    
    This prints foldexpr 1 to :mess
  2. Type o<Esc>.
    This prints the following to :mess, in the correct order.
    on_bytes
    foldexpr 1
    foldexpr 2
    
  3. Type u.
    This prints the following to :mess, in the wrong order.
    foldexpr 1
    on_bytes
    

Expected behavior

on_bytes, then foldexpr

Neovim version (nvim -v)

2ebd328

Vim (not Nvim) behaves the same?

N/A

Operating system/version

ubuntu 23.10

Terminal name/version

GNOME Terminal 3.49.92 using VTE 0.74.0 +BIDI +GNUTLS +ICU +SYSTEMD

$TERM environment variable

tmux-256color

Installation

build from repo

@tomtomjhj tomtomjhj added the bug issues reporting wrong behavior label Dec 10, 2023
@tomtomjhj
Copy link
Contributor Author

Why isn't ExtmarkUndoObject stored in each u_entry_T?

@zeertzjq zeertzjq added the marks marks, extmarks, decorations, virtual text, namespaces label Feb 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug issues reporting wrong behavior marks marks, extmarks, decorations, virtual text, namespaces
Projects
None yet
Development

No branches or pull requests

2 participants