0
0
mirror of https://github.com/vim/vim.git synced 2025-10-02 05:04:20 -04:00

patch 8.1.1489: sign order wrong when priority was changed

Problem:    Sign order wrong when priority was changed.
Solution:   Reorder signs when priority is changed. (Yegappan Lakshmanan,
            closes #4502)
This commit is contained in:
Bram Moolenaar
2019-06-07 21:37:13 +02:00
parent 150f0550f4
commit 64416127fc
4 changed files with 374 additions and 10 deletions

View File

@@ -5320,7 +5320,7 @@ qf_find_closest_entry(
* the list. If linewise is TRUE, then treat multiple entries on a single line * the list. If linewise is TRUE, then treat multiple entries on a single line
* as one. * as one.
*/ */
static qfline_T * static void
qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr) qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
{ {
while (n-- > 0 && !got_int) while (n-- > 0 && !got_int)
@@ -5348,8 +5348,6 @@ qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
entry = entry->qf_next; entry = entry->qf_next;
++*errornr; ++*errornr;
} }
return entry;
} }
/* /*
@@ -5357,7 +5355,7 @@ qf_get_nth_below_entry(qfline_T *entry, int n, int linewise, int *errornr)
* the list. If linewise is TRUE, then treat multiple entries on a single line * the list. If linewise is TRUE, then treat multiple entries on a single line
* as one. * as one.
*/ */
static qfline_T * static void
qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr) qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr)
{ {
while (n-- > 0 && !got_int) while (n-- > 0 && !got_int)
@@ -5373,8 +5371,6 @@ qf_get_nth_above_entry(qfline_T *entry, int n, int linewise, int *errornr)
if (linewise) if (linewise)
entry = qf_find_first_entry_on_line(entry, errornr); entry = qf_find_first_entry_on_line(entry, errornr);
} }
return entry;
} }
/* /*
@@ -5403,11 +5399,9 @@ qf_find_nth_adj_entry(
{ {
// Go to the n'th entry in the current buffer // Go to the n'th entry in the current buffer
if (dir == FORWARD) if (dir == FORWARD)
adj_entry = qf_get_nth_below_entry(adj_entry, n, linewise, qf_get_nth_below_entry(adj_entry, n, linewise, &errornr);
&errornr);
else else
adj_entry = qf_get_nth_above_entry(adj_entry, n, linewise, qf_get_nth_above_entry(adj_entry, n, linewise, &errornr);
&errornr);
} }
return errornr; return errornr;

View File

@@ -307,6 +307,78 @@ sign_get_info(signlist_T *sign)
return d; return d;
} }
/*
* Sort the signs placed on the same line as "sign" by priority. Invoked after
* changing the priority of an already placed sign. Assumes the signs in the
* buffer are sorted by line number and priority.
*/
static void
sign_sort_by_prio_on_line(buf_T *buf, signlist_T *sign)
{
signlist_T *p = NULL;
// If there is only one sign in the buffer or only one sign on the line or
// the sign is already sorted by priority, then return.
if ((sign->prev == NULL
|| sign->prev->lnum != sign->lnum
|| sign->prev->priority > sign->priority)
&& (sign->next == NULL
|| sign->next->lnum != sign->lnum
|| sign->next->priority < sign->priority))
return;
// One or more signs on the same line as 'sign'
// Find a sign after which 'sign' should be inserted
// First search backward for a sign with higher priority on the same line
p = sign;
while (p->prev != NULL && p->prev->lnum == sign->lnum
&& p->prev->priority <= sign->priority)
p = p->prev;
if (p == sign)
{
// Sign not found. Search forward for a sign with priority just before
// 'sign'.
p = sign->next;
while (p->next != NULL && p->next->lnum == sign->lnum
&& p->next->priority > sign->priority)
p = p->next;
}
// Remove 'sign' from the list
if (buf->b_signlist == sign)
buf->b_signlist = sign->next;
if (sign->prev != NULL)
sign->prev->next = sign->next;
if (sign->next != NULL)
sign->next->prev = sign->prev;
sign->prev = NULL;
sign->next = NULL;
// Re-insert 'sign' at the right place
if (p->priority <= sign->priority)
{
// 'sign' has a higher priority and should be inserted before 'p'
sign->prev = p->prev;
sign->next = p;
p->prev = sign;
if (sign->prev != NULL)
sign->prev->next = sign;
if (buf->b_signlist == p)
buf->b_signlist = sign;
}
else
{
// 'sign' has a lower priority and should be inserted after 'p'
sign->prev = p;
sign->next = p->next;
p->next = sign;
if (sign->next != NULL)
sign->next->prev = sign;
}
}
/* /*
* Add the sign into the signlist. Find the right spot to do it though. * Add the sign into the signlist. Find the right spot to do it though.
*/ */
@@ -331,6 +403,7 @@ buf_addsign(
// Update an existing sign // Update an existing sign
sign->typenr = typenr; sign->typenr = typenr;
sign->priority = prio; sign->priority = prio;
sign_sort_by_prio_on_line(buf, sign);
return; return;
} }
else if (lnum < sign->lnum) else if (lnum < sign->lnum)

View File

@@ -1183,6 +1183,301 @@ func Test_sign_priority()
\ 'priority' : 10}], \ 'priority' : 10}],
\ s[0].signs) \ s[0].signs)
call sign_unplace('*')
" Three signs on different lines with changing priorities
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 11, 'priority' : 50})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 12, 'priority' : 60})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 13, 'priority' : 70})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 12, 'priority' : 40})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 13, 'priority' : 30})
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 11, 'priority' : 50})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : '',
\ 'priority' : 50},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 12, 'group' : '',
\ 'priority' : 40},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 13, 'group' : '',
\ 'priority' : 30}],
\ s[0].signs)
call sign_unplace('*')
" Two signs on the same line with changing priorities
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the last sign to highest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 40})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 40},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30}],
\ s[0].signs)
" Change the priority of the first sign to lowest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 25})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 25}],
\ s[0].signs)
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 45})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 55})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 55},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 45}],
\ s[0].signs)
call sign_unplace('*')
" Three signs on the same line with changing priorities
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 40})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 40},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the middle sign to the highest
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 50})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 40},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the middle sign to the lowest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 15}],
\ s[0].signs)
" Change the priority of the last sign to the highest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 55})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 55},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Change the priority of the first sign to the lowest
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 50},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 15}],
\ s[0].signs)
call sign_unplace('*')
" Three signs on the same line with changing priorities along with other
" signs
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 2, 'priority' : 10})
call sign_place(2, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
call sign_place(3, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(4, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 25})
call sign_place(5, '', 'sign2', 'Xsign',
\ {'lnum' : 6, 'priority' : 80})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 25},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the first sign to lowest
call sign_place(2, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 25},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 15},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the last sign to highest
call sign_place(2, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 30})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 25},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the middle sign to lowest
call sign_place(4, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 15})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 15},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
" Change the priority of the middle sign to highest
call sign_place(3, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 35})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 35},
\ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 30},
\ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 15},
\ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
\ 'priority' : 80}],
\ s[0].signs)
call sign_unplace('*')
" Multiple signs with the same priority on the same line
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(2, '', 'sign2', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Place the last sign again with the same priority
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Place the first sign again with the same priority
call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
" Place the middle sign again with the same priority
call sign_place(3, '', 'sign3', 'Xsign',
\ {'lnum' : 4, 'priority' : 20})
let s = sign_getplaced('Xsign', {'group' : '*'})
call assert_equal([
\ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
\ 'priority' : 20},
\ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
\ 'priority' : 20}],
\ s[0].signs)
call sign_unplace('*')
" Place multiple signs with same id on a line with different priority " Place multiple signs with same id on a line with different priority
call sign_place(1, '', 'sign1', 'Xsign', call sign_place(1, '', 'sign1', 'Xsign',
\ {'lnum' : 5, 'priority' : 20}) \ {'lnum' : 5, 'priority' : 20})

View File

@@ -767,6 +767,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1489,
/**/ /**/
1488, 1488,
/**/ /**/