Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(column): move sign sentinel after inserting/deleting lines #20400

Merged
merged 1 commit into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 38 additions & 17 deletions src/nvim/sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,27 @@ static void sign_list_placed(buf_T *rbuf, char *sign_group)
}
}

/// Adjust a placed sign for inserted/deleted lines.
/// Adjust or delete a placed sign for inserted/deleted lines.
///
/// @return the new line number of the sign, or 0 if the sign is in deleted lines.
static linenr_T sign_adjust_one(const linenr_T se_lnum, linenr_T line1, linenr_T line2,
linenr_T amount, linenr_T amount_after)
{
if (se_lnum < line1) {
// Ignore changes to lines after the sign
return se_lnum;
}
if (se_lnum > line2) {
// Lines inserted or deleted before the sign
return se_lnum + amount_after;
}
if (amount == MAXLNUM) { // sign in deleted lines
return 0;
}
return se_lnum + amount;
}

/// Adjust placed signs for inserted/deleted lines.
void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after)
{
sign_entry_T *sign; // a sign in a b_signlist
Expand All @@ -735,41 +755,42 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, linenr_T amount, linenr_T
int is_fixed = 0;
int signcol = win_signcol_configured(curwin, &is_fixed);

bool delete = amount == MAXLNUM;

if (delete) {
if (amount == MAXLNUM) { // deleting
buf_signcols_del_check(curbuf, line1, line2);
}

lastp = &curbuf->b_signlist;

for (sign = curbuf->b_signlist; sign != NULL; sign = next) {
next = sign->se_next;
new_lnum = sign->se_lnum;
if (sign->se_lnum >= line1 && sign->se_lnum <= line2) {
if (!delete) {
new_lnum += amount;
} else if (!is_fixed || signcol >= 2) {

new_lnum = sign_adjust_one(sign->se_lnum, line1, line2, amount, amount_after);
if (new_lnum == 0) { // sign in deleted lines
if (!is_fixed || signcol >= 2) {
*lastp = next;
if (next) {
next->se_prev = last;
}
xfree(sign);
continue;
}
} else if (sign->se_lnum > line2) {
new_lnum += amount_after;
}
// If the new sign line number is past the last line in the buffer,
// then don't adjust the line number. Otherwise, it will always be past
// the last line and will not be visible.
if (sign->se_lnum >= line1 && new_lnum <= curbuf->b_ml.ml_line_count) {
sign->se_lnum = new_lnum;
} else {
// If the new sign line number is past the last line in the buffer,
// then don't adjust the line number. Otherwise, it will always be past
// the last line and will not be visible.
if (new_lnum <= curbuf->b_ml.ml_line_count) {
sign->se_lnum = new_lnum;
}
}

last = sign;
lastp = &sign->se_next;
}

new_lnum = sign_adjust_one(curbuf->b_signcols.sentinel, line1, line2, amount, amount_after);
if (new_lnum != 0) {
curbuf->b_signcols.sentinel = new_lnum;
}
}

/// Find index of a ":sign" subcmd from its name.
Expand Down
85 changes: 85 additions & 0 deletions test/functional/ui/sign_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, command = helpers.clear, helpers.feed, helpers.command
local source = helpers.source
local meths = helpers.meths

describe('Signs', function()
local screen
Expand Down Expand Up @@ -592,4 +593,88 @@ describe('Signs', function()
]])
end)
end)

it('signcolumn width is updated when removing all signs after deleting lines', function()
meths.buf_set_lines(0, 0, 1, true, {'a', 'b', 'c', 'd', 'e'})
command('sign define piet text=>>')
command('sign place 10001 line=1 name=piet')
command('sign place 10002 line=5 name=piet')
command('2delete')
command('sign unplace 10001')
screen:expect([[
{2: }a |
{2: }^c |
{2: }d |
>>e |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
command('sign unplace 10002')
screen:expect([[
a |
^c |
d |
e |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
end)

it('signcolumn width is updated when removing all signs after inserting lines', function()
meths.buf_set_lines(0, 0, 1, true, {'a', 'b', 'c', 'd', 'e'})
command('sign define piet text=>>')
command('sign place 10001 line=1 name=piet')
command('sign place 10002 line=5 name=piet')
command('copy .')
command('sign unplace 10001')
screen:expect([[
{2: }a |
{2: }^a |
{2: }b |
{2: }c |
{2: }d |
>>e |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
command('sign unplace 10002')
screen:expect([[
a |
^a |
b |
c |
d |
e |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]])
end)
end)