Merge pull request #12323 from da-x/orphaned-signs

Handle 'orphaned signs' on line deletion for signcolumn >= 2
This commit is contained in:
Matthieu Coudron
2021-04-18 17:12:41 +02:00
committed by GitHub
5 changed files with 62 additions and 25 deletions

View File

@@ -7582,10 +7582,20 @@ int csh_like_shell(void)
/// Return the number of requested sign columns, based on current
/// buffer signs and on user configuration.
int win_signcol_count(win_T *wp)
{
return win_signcol_configured(wp, NULL);
}
/// Return the number of requested sign columns, based on user / configuration.
int win_signcol_configured(win_T *wp, int *is_fixed)
{
int minimum = 0, maximum = 1, needed_signcols;
const char *scl = (const char *)wp->w_p_scl;
if (is_fixed) {
*is_fixed = 1;
}
// Note: It checks "no" or "number" in 'signcolumn' option
if (*scl == 'n'
&& (*(scl + 1) == 'o' || (*(scl + 1) == 'u'
@@ -7603,7 +7613,11 @@ int win_signcol_count(win_T *wp)
return 1;
}
// auto or auto:<NUM>
if (is_fixed) {
// auto or auto:<NUM>
*is_fixed = 0;
}
if (!strncmp(scl, "auto:", 5)) {
// Variable depending on a configuration
maximum = scl[5] - '0';

View File

@@ -18,6 +18,7 @@
#include "nvim/move.h"
#include "nvim/screen.h"
#include "nvim/syntax.h"
#include "nvim/option.h"
/// Struct to hold the sign properties.
typedef struct sign sign_T;
@@ -726,15 +727,29 @@ void sign_mark_adjust(
long amount_after
)
{
sign_entry_T *sign; // a sign in a b_signlist
linenr_T new_lnum; // new line number to assign to sign
sign_entry_T *sign; // a sign in a b_signlist
sign_entry_T *next; // the next sign in a b_signlist
sign_entry_T *last = NULL; // pointer to pointer to current sign
sign_entry_T **lastp = NULL; // pointer to pointer to current sign
linenr_T new_lnum; // new line number to assign to sign
int is_fixed = 0;
int signcol = win_signcol_configured(curwin, &is_fixed);
curbuf->b_signcols_max = -1;
lastp = &curbuf->b_signlist;
FOR_ALL_SIGNS_IN_BUF(curbuf, sign) {
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 (amount != MAXLNUM) {
if (amount == MAXLNUM && (!is_fixed || signcol >= 2)) {
*lastp = next;
if (next) {
next->se_prev = last;
}
xfree(sign);
continue;
} else {
new_lnum += amount;
}
} else if (sign->se_lnum > line2) {
@@ -746,6 +761,9 @@ void sign_mark_adjust(
if (sign->se_lnum >= line1 && new_lnum <= curbuf->b_ml.ml_line_count) {
sign->se_lnum = new_lnum;
}
last = sign;
lastp = &sign->se_next;
}
}

View File

@@ -1628,26 +1628,7 @@ func Test_sign_lnum_adjust()
" Delete the line with the sign
call deletebufline('', 4)
let l = sign_getplaced(bufnr(''))
call assert_equal(4, l[0].signs[0].lnum)
" Undo the delete operation
undo
let l = sign_getplaced(bufnr(''))
call assert_equal(5, l[0].signs[0].lnum)
" Break the undo
let &undolevels=&undolevels
" Delete few lines at the end of the buffer including the line with the sign
" Sign line number should not change (as it is placed outside of the buffer)
call deletebufline('', 3, 6)
let l = sign_getplaced(bufnr(''))
call assert_equal(5, l[0].signs[0].lnum)
" Undo the delete operation. Sign should be restored to the previous line
undo
let l = sign_getplaced(bufnr(''))
call assert_equal(5, l[0].signs[0].lnum)
call assert_equal(0, len(l[0].signs))
sign unplace * group=*
sign undefine sign1