mirror of
https://github.com/neovim/neovim.git
synced 2026-02-17 18:01:16 +10:00
fix(extmark): adjust invalidate range by one for deleted lines #37897
Problem: A multi-line extmark that ends exactly at a deleted range end
is not invalidated.
Revalidated sign mark is added with incorrect range.
Solution: Remove questionable invalidation range condition which was
originally added to avoid deleting a mark that ends below a
deleted line.
Since splicing for a deleted line, and a replaced range that
explicitly ends at column 0 beyond a deleted line is identical,
we can't try to distinguish these two cases. I.e. :1delete 1
and nvim_buf_set_text(0, 0, 0, 1, 0, {}) yield the same splice
operation.
This means that a multi-line sign_text mark should now span at
least one column beyond its end_row, as seen in the adjusted
test. This is still somewhat unexpected/inconvenient to me
which is what prompted me to try to avoid it with the original
condition.
Add revalidated sign mark back to decor with correct range;
third sign mark added to test exposed a crash.
This commit is contained in:
@@ -141,7 +141,7 @@ static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool
|
||||
}
|
||||
|
||||
if (invalid) {
|
||||
buf_put_decor(buf, mt_decor(key), MIN(row, key.pos.row), MAX(row, key.pos.row));
|
||||
buf_put_decor(buf, mt_decor(key), MIN(row, alt.pos.row), MAX(row, alt.pos.row));
|
||||
} else if (!mt_invalid(key) && key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
|
||||
buf_signcols_count_range(buf, row1, MIN(curbuf->b_ml.ml_line_count - 1, row2), 0, kNone);
|
||||
}
|
||||
@@ -398,9 +398,8 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
|
||||
// range has been deleted.
|
||||
if ((!mt_paired(mark) && mark.pos.row < u_row)
|
||||
|| (mt_paired(mark)
|
||||
&& (endpos.col <= u_col || (!u_col && endpos.row == mark.pos.row))
|
||||
&& mark.pos.col >= l_col
|
||||
&& mark.pos.row >= l_row && endpos.row <= u_row - (u_col ? 0 : 1))) {
|
||||
&& (mark.pos.row > l_row || (mark.pos.row == l_row && mark.pos.col >= l_col))
|
||||
&& (endpos.row < u_row || (endpos.row == u_row && endpos.col <= u_col)))) {
|
||||
if (mt_no_undo(mark)) {
|
||||
extmark_del(buf, itr, mark, true);
|
||||
continue;
|
||||
|
||||
@@ -1774,13 +1774,14 @@ describe('API/extmarks', function()
|
||||
it('invalidated marks are deleted', function()
|
||||
screen = Screen.new(40, 6)
|
||||
feed('dd6iaaa bbb ccc<CR><ESC>gg')
|
||||
api.nvim_set_option_value('signcolumn', 'auto:2', {})
|
||||
api.nvim_set_option_value('signcolumn', 'auto:3', {})
|
||||
set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1', end_row = 1 })
|
||||
set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2', end_row = 2 })
|
||||
set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2', end_row = 2, end_col = 0 })
|
||||
set_extmark(ns, 3, 1, 0, { invalidate = true, sign_text = 'S3', end_row = 2, end_col = 1 })
|
||||
-- mark with invalidate is removed
|
||||
command('d2')
|
||||
screen:expect([[
|
||||
{7:S2}^aaa bbb ccc |
|
||||
{7:S3}^aaa bbb ccc |
|
||||
{7: }aaa bbb ccc |*3
|
||||
{7: } |
|
||||
|
|
||||
@@ -1788,15 +1789,16 @@ describe('API/extmarks', function()
|
||||
-- mark is restored with undo_restore == true
|
||||
command('silent undo')
|
||||
screen:expect([[
|
||||
{7:S1 }^aaa bbb ccc |
|
||||
{7:S2S1}aaa bbb ccc |
|
||||
{7:S2 }aaa bbb ccc |
|
||||
{7: }aaa bbb ccc |*2
|
||||
{7:S1 }^aaa bbb ccc |
|
||||
{7:S3S2S1}aaa bbb ccc |
|
||||
{7:S3S2 }aaa bbb ccc |
|
||||
{7: }aaa bbb ccc |*2
|
||||
|
|
||||
]])
|
||||
-- decor is not removed twice
|
||||
command('d3')
|
||||
api.nvim_buf_del_extmark(0, ns, 1)
|
||||
api.nvim_buf_del_extmark(0, ns, 3)
|
||||
command('silent undo')
|
||||
-- mark is deleted with undo_restore == false
|
||||
set_extmark(ns, 1, 0, 0, { invalidate = true, undo_restore = false, sign_text = 'S1' })
|
||||
@@ -1806,7 +1808,6 @@ describe('API/extmarks', function()
|
||||
-- mark is not removed when deleting bytes before the range
|
||||
set_extmark(ns, 3, 0, 4, {
|
||||
invalidate = true,
|
||||
undo_restore = true,
|
||||
hl_group = 'Error',
|
||||
end_col = 7,
|
||||
right_gravity = false,
|
||||
|
||||
Reference in New Issue
Block a user