aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/extmark.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
committerJosh Rahm <joshuarahm@gmail.com>2025-02-05 23:09:29 +0000
commitd5f194ce780c95821a855aca3c19426576d28ae0 (patch)
treed45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/extmark.c
parentc5d770d311841ea5230426cc4c868e8db27300a8 (diff)
parent44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff)
downloadrneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.gz
rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.tar.bz2
rneovim-d5f194ce780c95821a855aca3c19426576d28ae0.zip
Merge remote-tracking branch 'upstream/master' into mix_20240309HEADrahm
Diffstat (limited to 'src/nvim/extmark.c')
-rw-r--r--src/nvim/extmark.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index c20c7dea23..7e6dfb8dea 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -95,6 +95,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
MTKey mark = { { row, col }, ns_id, id, flags, decor.data };
marktree_put(buf->b_marktree, mark, end_row, end_col, end_right_gravity);
+ decor_state_invalidate(buf);
revised:
if (decor_flags || decor.ext) {
@@ -111,10 +112,10 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
{
MarkTreeIter itr[1] = { 0 };
MTKey key = marktree_lookup(buf->b_marktree, mark, itr);
- bool move = key.pos.row >= 0 && (key.pos.row != row || key.pos.col != col);
- // Already valid keys were being revalidated, presumably when encountering a
- // SavePos from a modified mark. Avoid adding that to the decor again.
- invalid = invalid && mt_invalid(key);
+ bool move = key.pos.row != row || key.pos.col != col;
+ if (key.pos.row < 0 || (!move && !invalid)) {
+ return; // Mark was deleted or no change needed
+ }
// Only the position before undo needs to be redrawn here,
// as the position after undo should be marked as changed.
@@ -124,13 +125,16 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
int row1 = 0;
int row2 = 0;
+ MarkTreeIter altitr[1] = { *itr };
+ MTKey alt = marktree_get_alt(buf->b_marktree, key, altitr);
+
if (invalid) {
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_INVALID;
- marktree_revise_meta(buf->b_marktree, itr, key);
- } else if (move && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
- MTPos end = marktree_get_altpos(buf->b_marktree, key, NULL);
- row1 = MIN(end.row, MIN(key.pos.row, row));
- row2 = MAX(end.row, MAX(key.pos.row, row));
+ mt_itr_rawkey(altitr).flags &= (uint16_t) ~MT_FLAG_INVALID;
+ marktree_revise_meta(buf->b_marktree, mt_end(key) ? altitr : itr, mt_end(key) ? alt : key);
+ } else if (!mt_invalid(key) && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
+ row1 = MIN(alt.pos.row, MIN(key.pos.row, row));
+ row2 = MAX(alt.pos.row, MAX(key.pos.row, row));
buf_signcols_count_range(buf, row1, row2, 0, kTrue);
}
@@ -139,9 +143,8 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
}
if (invalid) {
- row2 = mt_paired(key) ? marktree_get_altpos(buf->b_marktree, key, NULL).row : row;
- buf_put_decor(buf, mt_decor(key), row, row2);
- } else if (move && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
+ buf_put_decor(buf, mt_decor(key), MIN(row, key.pos.row), MAX(row, key.pos.row));
+ } else if (!mt_invalid(key) && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
buf_signcols_count_range(buf, row1, row2, 0, kNone);
}
}
@@ -184,6 +187,8 @@ void extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
}
}
+ decor_state_invalidate(buf);
+
// TODO(bfredl): delete it from current undo header, opportunistically?
}
@@ -237,6 +242,10 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
}
}
+ if (marks_cleared_any) {
+ decor_state_invalidate(buf);
+ }
+
return marks_cleared_any;
}
@@ -367,16 +376,28 @@ 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)) {
- MTPos endpos = marktree_get_altpos(buf->b_marktree, mark, NULL);
+ MarkTreeIter enditr[1] = { *itr };
+ MTPos endpos = marktree_get_altpos(buf->b_marktree, mark, enditr);
// Invalidate unpaired marks in deleted lines and paired marks whose entire
// range has been deleted.
if ((!mt_paired(mark) && mark.pos.row < u_row)
@@ -388,8 +409,10 @@ 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;
+ mt_itr_rawkey(enditr).flags |= MT_FLAG_INVALID;
marktree_revise_meta(buf->b_marktree, itr, mark);
buf_decor_remove(buf, mark.pos.row, endpos.row, mark.pos.col, mt_decor(mark), false);
}
@@ -397,7 +420,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 +564,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);