From 320e9c1c21817fd76b84345018661f70437fa4b5 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Wed, 13 Dec 2023 23:30:19 +0100 Subject: [PATCH] fix(extmark): only invalidate unpaired marks on deleted rows Problem: Unpaired marks are invalidated if its column is deleted, which may just be a "placeholder" column, e.g. for signs. Solution: Only remove unpaired marks if its entire row is deleted. --- src/nvim/extmark.c | 10 +++++++--- test/functional/ui/sign_spec.lua | 23 +++++++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 92fbc6fb79..f914137ccc 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -332,9 +332,13 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln if (endpos.row < 0) { endpos = mark.pos; } - if ((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)) { + // Invalidate unpaired marks in deleted lines and paired marks whose entire + // 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))) { if (mt_no_undo(mark)) { extmark_del(buf, itr, mark, true); continue; diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index bf2830f2f0..316d3fe3ac 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -218,14 +218,15 @@ describe('Signs', function() ]]) -- "auto:3" accommodates all the signs we defined so far. command('set signcolumn=auto:3') - screen:expect([[ + local s3 = [[ {1:>>}{8:XX}{2: }{6: 1 }a | {8:XX}{1:>>}{2: }{6: 2 }b | {8:XX}{1:>>}WW{6: 3 }c | {2: }{6: 4 }^ | {0:~ }|*9 | - ]]) + ]] + screen:expect(s3) -- Check "yes:9". command('set signcolumn=yes:9') screen:expect([[ @@ -239,14 +240,7 @@ describe('Signs', function() -- Check "auto:N" larger than the maximum number of signs defined in -- a single line (same result as "auto:3"). command('set signcolumn=auto:4') - screen:expect{grid=[[ - {1:>>}{8:XX}{2: }{6: 1 }a | - {8:XX}{1:>>}{2: }{6: 2 }b | - {8:XX}{1:>>}WW{6: 3 }c | - {2: }{6: 4 }^ | - {0:~ }|*9 - | - ]]} + screen:expect(s3) -- line deletion deletes signs. command('3move1') command('2d') @@ -257,6 +251,15 @@ describe('Signs', function() {0:~ }|*10 | ]]) + -- character deletion does not delete signs. + feed('x') + screen:expect([[ + {1:>>}{8:XX}{6: 1 }a | + {8:XX}{1:>>}{6: 2 }^ | + {2: }{6: 3 } | + {0:~ }|*10 + | + ]]) end) it('auto-resize sign column with minimum size (#13783)', function()