diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2025-02-05 23:09:29 +0000 |
commit | d5f194ce780c95821a855aca3c19426576d28ae0 (patch) | |
tree | d45f461b19f9118ad2bb1f440a7a08973ad18832 /src/nvim/extmark.c | |
parent | c5d770d311841ea5230426cc4c868e8db27300a8 (diff) | |
parent | 44740e561fc93afe3ebecfd3618bda2d2abeafb0 (diff) | |
download | rneovim-rahm.tar.gz rneovim-rahm.tar.bz2 rneovim-rahm.zip |
Diffstat (limited to 'src/nvim/extmark.c')
-rw-r--r-- | src/nvim/extmark.c | 63 |
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); |