aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2024-12-07 12:06:58 +0100
committerGitHub <noreply@github.com>2024-12-07 12:06:58 +0100
commit92e61072ac7493d85c15e3403f17619446782b51 (patch)
tree18411eac11c86440ee8e410b3ad8d2ac9163b29b
parentc63e49cce2d20cee129a6312319dde8dcea6e3f6 (diff)
parentc4f76299f0398f8a9b42bb7c1a5fad3205680298 (diff)
downloadrneovim-92e61072ac7493d85c15e3403f17619446782b51.tar.gz
rneovim-92e61072ac7493d85c15e3403f17619446782b51.tar.bz2
rneovim-92e61072ac7493d85c15e3403f17619446782b51.zip
Merge pull request #31475 from luukvbaal/delgravity
fix(marks): check gravity at range bounds when deleting text
-rw-r--r--src/nvim/extmark.c26
-rw-r--r--test/functional/api/extmark_spec.lua2
2 files changed, 19 insertions, 9 deletions
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index c20c7dea23..6119d838f9 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -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);
while (true) {
MTKey mark = marktree_itr_current(itr);
- if (mark.pos.row < 0
- || mark.pos.row > u_row
- || (mark.pos.row == u_row && mark.pos.col > u_col)) {
+ if (mark.pos.row < 0 || mark.pos.row > u_row) {
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;
// Invalidate/delete 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);
continue;
} else {
+ copy = true;
invalidated = true;
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
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
- 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 = {
.mark = mt_lookup_key(mark),
.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) {
// Copy and invalidate marks that would be effected by delete
- // TODO(bfredl): Be "smart" about gravity here, left-gravity at the
- // beginning and right-gravity at the end need not be preserved.
- // Also be smart about marks that already have been saved (important for
- // merge!)
+ // TODO(bfredl): Be smart about marks that already have been
+ // saved (important for merge!)
int end_row = start_row + old_row;
int end_col = (old_row ? 0 : start_col) + old_col;
u_header_T *uhp = u_force_get_undo_header(buf);
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index 43be0c0e43..49c55288e8 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -249,7 +249,7 @@ describe('API/extmarks', function()
set_extmark(ns, 2, 1, 0, { right_gravity = false })
eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
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)
end)