mirror of
https://github.com/neovim/neovim
synced 2025-07-17 17:51:48 +00:00
fix(marks): skip right_gravity marks when deleting text
Problem: Marks that are properly restored by the splice associated with
an undo edit, are unnecessarily pushed to the undo header. This
results in incorrect mark tracking in the "copy_only"
save/restore completion path.
Solution: Avoid pushing left gravity marks at the beginning of the range,
and right gravity marks at the end of the range to the undo
header.
(cherry picked from commit c4f76299f0
)
This commit is contained in:
committed by
github-actions[bot]
parent
7abc58349e
commit
01fe4fc589
@ -367,12 +367,23 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
|
|||||||
marktree_itr_get(buf->b_marktree, (int32_t)l_row, l_col, itr);
|
marktree_itr_get(buf->b_marktree, (int32_t)l_row, l_col, itr);
|
||||||
while (true) {
|
while (true) {
|
||||||
MTKey mark = marktree_itr_current(itr);
|
MTKey mark = marktree_itr_current(itr);
|
||||||
if (mark.pos.row < 0
|
if (mark.pos.row < 0 || mark.pos.row > u_row) {
|
||||||
|| mark.pos.row > u_row
|
|
||||||
|| (mark.pos.row == u_row && mark.pos.col > u_col)) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool copy = true;
|
||||||
|
// No need to copy left gravity marks at the beginning of the range,
|
||||||
|
// and right gravity marks at the end of the range, unless invalidated.
|
||||||
|
if (mark.pos.row == l_row && mark.pos.col - !mt_right(mark) < l_col) {
|
||||||
|
copy = false;
|
||||||
|
} else if (mark.pos.row == u_row) {
|
||||||
|
if (mark.pos.col > u_col + 1) {
|
||||||
|
break;
|
||||||
|
} else if (mark.pos.col + mt_right(mark) > u_col) {
|
||||||
|
copy = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool invalidated = false;
|
bool invalidated = false;
|
||||||
// Invalidate/delete mark
|
// Invalidate/delete mark
|
||||||
if (!only_copy && !mt_invalid(mark) && mt_invalidate(mark) && !mt_end(mark)) {
|
if (!only_copy && !mt_invalid(mark) && mt_invalidate(mark) && !mt_end(mark)) {
|
||||||
@ -388,6 +399,7 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
|
|||||||
extmark_del(buf, itr, mark, true);
|
extmark_del(buf, itr, mark, true);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
copy = true;
|
||||||
invalidated = true;
|
invalidated = true;
|
||||||
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
|
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
|
||||||
marktree_revise_meta(buf->b_marktree, itr, mark);
|
marktree_revise_meta(buf->b_marktree, itr, mark);
|
||||||
@ -397,7 +409,7 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Push mark to undo header
|
// Push mark to undo header
|
||||||
if (only_copy || (uvp != NULL && op == kExtmarkUndo && !mt_no_undo(mark))) {
|
if (copy && (only_copy || (uvp != NULL && op == kExtmarkUndo && !mt_no_undo(mark)))) {
|
||||||
ExtmarkSavePos pos = {
|
ExtmarkSavePos pos = {
|
||||||
.mark = mt_lookup_key(mark),
|
.mark = mt_lookup_key(mark),
|
||||||
.invalidated = invalidated,
|
.invalidated = invalidated,
|
||||||
@ -541,10 +553,8 @@ void extmark_splice_impl(buf_T *buf, int start_row, colnr_T start_col, bcount_t
|
|||||||
|
|
||||||
if (old_row > 0 || old_col > 0) {
|
if (old_row > 0 || old_col > 0) {
|
||||||
// Copy and invalidate marks that would be effected by delete
|
// Copy and invalidate marks that would be effected by delete
|
||||||
// TODO(bfredl): Be "smart" about gravity here, left-gravity at the
|
// TODO(bfredl): Be smart about marks that already have been
|
||||||
// beginning and right-gravity at the end need not be preserved.
|
// saved (important for merge!)
|
||||||
// Also be smart about marks that already have been saved (important for
|
|
||||||
// merge!)
|
|
||||||
int end_row = start_row + old_row;
|
int end_row = start_row + old_row;
|
||||||
int end_col = (old_row ? 0 : start_col) + old_col;
|
int end_col = (old_row ? 0 : start_col) + old_col;
|
||||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||||
|
@ -249,7 +249,7 @@ describe('API/extmarks', function()
|
|||||||
set_extmark(ns, 2, 1, 0, { right_gravity = false })
|
set_extmark(ns, 2, 1, 0, { right_gravity = false })
|
||||||
eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
||||||
feed('u')
|
feed('u')
|
||||||
eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
eq({ { 1, 0, 0 }, { 2, 0, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
|
||||||
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user