feat(signs)!: place higher-priority signs from the left #27781

Problem:
Higher-priority signs may be hidden by lower-priority signs.

Solution:
Place higher-priority signs from the left.

Example:

    nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='H', priority=1})
    nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='W', priority=2})
    nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='E', priority=3})

Before:

            |     |
          H | W E |
          ^ |     |
Not visible

After:

  |     |
  | E W | H
  |     | ^
          Not visible

Fixes #16632
This commit is contained in:
Tobias Schmitz
2024-05-21 18:21:42 +02:00
committed by GitHub
parent 8263ed4670
commit ad191be65e
8 changed files with 54 additions and 52 deletions

View File

@@ -38,7 +38,7 @@ DEFAULTS
EDITOR EDITOR
• TODO • The order in which signs are placed was changed. Higher priority signs will now appear left of lower priority signs.
EVENTS EVENTS

View File

@@ -72,9 +72,10 @@ on the same line, the attributes of the sign with the highest priority is used
independently of the sign group. The default priority for a sign is 10. The independently of the sign group. The default priority for a sign is 10. The
priority is assigned at the time of placing a sign. priority is assigned at the time of placing a sign.
When two signs with the same priority are present, and one has an icon or text When multiple signs that each have an icon or text are present, signs are
in the signcolumn while the other has line highlighting, then both are ordered with increasing priority from left to right, up until the maximum
displayed. width set in 'signcolumn'. Lower priority signs that do not fit are hidden.
Highest priority signs with highlight attributes are always shown.
When the line on which the sign is placed is deleted, the sign is removed along When the line on which the sign is placed is deleted, the sign is removed along
with it. with it.

View File

@@ -740,14 +740,15 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
if (kv_size(signs)) { if (kv_size(signs)) {
int width = wp->w_minscwidth == SCL_NUM ? 1 : wp->w_scwidth; int width = wp->w_minscwidth == SCL_NUM ? 1 : wp->w_scwidth;
int idx = MIN(width, num_text) - 1; int len = MIN(width, num_text);
int idx = 0;
qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(kv_A(signs, 0)), sign_item_cmp); qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(kv_A(signs, 0)), sign_item_cmp);
for (size_t i = 0; i < kv_size(signs); i++) { for (size_t i = 0; i < kv_size(signs); i++) {
DecorSignHighlight *sh = kv_A(signs, i).sh; DecorSignHighlight *sh = kv_A(signs, i).sh;
if (idx >= 0 && sh->text[0]) { if (idx < len && sh->text[0]) {
memcpy(sattrs[idx].text, sh->text, SIGN_WIDTH * sizeof(sattr_T)); memcpy(sattrs[idx].text, sh->text, SIGN_WIDTH * sizeof(sattr_T));
sattrs[idx--].hl_id = sh->hl_id; sattrs[idx++].hl_id = sh->hl_id;
} }
if (*num_id == 0) { if (*num_id == 0) {
*num_id = sh->number_hl_id; *num_id = sh->number_hl_id;

View File

@@ -1743,7 +1743,7 @@ describe('API/extmarks', function()
command('silent undo') command('silent undo')
screen:expect([[ screen:expect([[
S1{7: }^aaa bbb ccc | S1{7: }^aaa bbb ccc |
S1S2aaa bbb ccc | S2S1aaa bbb ccc |
S2{7: }aaa bbb ccc | S2{7: }aaa bbb ccc |
{7: }aaa bbb ccc |*2 {7: }aaa bbb ccc |*2
| |

View File

@@ -3918,13 +3918,13 @@ describe('API', function()
norm 4G norm 4G
]]) ]])
eq({ eq({
str = '││aabb 4 ', str = '││bbaa 4 ',
width = 9, width = 9,
highlights = { highlights = {
{ group = 'CursorLineFold', start = 0 }, { group = 'CursorLineFold', start = 0 },
{ group = 'Normal', start = 6 }, { group = 'Normal', start = 6 },
{ group = 'IncSearch', start = 6 }, { group = 'ErrorMsg', start = 6 },
{ group = 'ErrorMsg', start = 8 }, { group = 'IncSearch', start = 8 },
{ group = 'Normal', start = 10 }, { group = 'Normal', start = 10 },
}, },
}, api.nvim_eval_statusline( }, api.nvim_eval_statusline(

View File

@@ -5062,7 +5062,7 @@ l5
{7: }^l1 | {7: }^l1 |
S2{7: }l2 | S2{7: }l2 |
S2{7: }l3 | S2{7: }l3 |
S1S2l4 | S2S1l4 |
{7: }l5 | {7: }l5 |
{7: } | {7: } |
{1:~ }|*3 {1:~ }|*3
@@ -5081,7 +5081,7 @@ l5
screen:expect{grid=[[ screen:expect{grid=[[
{7: }^l1 | {7: }^l1 |
S1{7: }l2 | S1{7: }l2 |
S1S2l3 | S2S1l3 |
S2{7: }l4 | S2{7: }l4 |
{7: }l5 | {7: }l5 |
{7: } | {7: } |
@@ -5122,8 +5122,8 @@ l5
api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'}) api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
screen:expect{grid=[[ screen:expect{grid=[[
S1S4^l1 | S4S1^l1 |
x S2l2 | S2x l2 |
S5{7: }l3 | S5{7: }l3 |
{7: }l4 | {7: }l4 |
{7: }l5 | {7: }l5 |
@@ -5147,9 +5147,9 @@ l5
api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'}) api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
screen:expect{grid=[[ screen:expect{grid=[[
S1S3S4^l1 | S4S3S1^l1 |
x S2S3l2 | S3S2x l2 |
S3S5{7: }l3 | S5S3{7: }l3 |
S3{7: }l4 | S3{7: }l4 |
S3{7: }l5 | S3{7: }l5 |
{7: } | {7: } |
@@ -5196,8 +5196,8 @@ l5
end end
screen:expect{grid=[[ screen:expect{grid=[[
W X Y Z {100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:h} |*8 Z Y X W {100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:h} |*8
W X Y Z {100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:^h} | Z Y X W {100:a} {100:b} {100:c} {100:d} {100:e} {100:f} {100:g} {100:^h} |
| |
]]} ]]}
end) end)
@@ -5216,7 +5216,7 @@ l5
api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1}) api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
screen:expect{grid=[[ screen:expect{grid=[[
S1S2O3S4S5^l1 | S5S4O3S2S1^l1 |
{7: }l2 | {7: }l2 |
| |
]]} ]]}
@@ -5256,7 +5256,7 @@ l5
api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200}) api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
screen:expect{grid=[[ screen:expect{grid=[[
O3O3O3O3O3O3O3O3S5^ | S5O3O3O3O3O3O3O3O3^ |
{1:~ }| {1:~ }|
| |
]]} ]]}
@@ -5302,9 +5302,9 @@ l5
feed('gg') feed('gg')
local s1 = [[ local s1 = [[
S1S2^l1 | S2S1^l1 |
S2S3l2 | S3S2l2 |
S2S3l3 | S3S2l3 |
| |
]] ]]
screen:expect{grid=s1} screen:expect{grid=s1}
@@ -5312,7 +5312,7 @@ l5
command('move2') command('move2')
screen:expect{grid=[[ screen:expect{grid=[[
S3{7: }l2 | S3{7: }l2 |
S1S2S3^l1 | S3S2S1^l1 |
{7: }l3 | {7: }l3 |
| |
]]} ]]}
@@ -5320,14 +5320,14 @@ l5
screen:expect{grid=s1} screen:expect{grid=s1}
command('d') command('d')
screen:expect{grid=[[ screen:expect{grid=[[
S1S2S3^l2 | S3S2S1^l2 |
S2S3{7: }l3 | S3S2{7: }l3 |
{7: }l4 | {7: }l4 |
| |
]]} ]]}
command('d') command('d')
screen:expect{grid=[[ screen:expect{grid=[[
S1S2S3^l3 | S3S2S1^l3 |
{7: }l4 | {7: }l4 |
{7: }l5 | {7: }l5 |
| |
@@ -5376,7 +5376,7 @@ l5
]]) ]])
screen:expect{grid=[[ screen:expect{grid=[[
{7: }l3 | {7: }l3 |
S1S2l5 | S2S1l5 |
{7: }^ | {7: }^ |
| |
]]} ]]}
@@ -5468,7 +5468,7 @@ l5
api.nvim_buf_set_extmark(0, ns2, 0, 0, {sign_text = 'S2', id = 1}) api.nvim_buf_set_extmark(0, ns2, 0, 0, {sign_text = 'S2', id = 1})
screen:expect{grid=[[ screen:expect{grid=[[
S1S2^ | S2S1^ |
{1:~ }|*8 {1:~ }|*8
| |
]]} ]]}
@@ -5489,7 +5489,7 @@ l5
command('0d29') command('0d29')
screen:expect{grid=[[ screen:expect{grid=[[
S1S2S3S4{9:^foo} | S4S3S2S1{9:^foo} |
S5{7: }{9:foo} | S5{7: }{9:foo} |
{1:~ }|*7 {1:~ }|*7
29 fewer lines | 29 fewer lines |

View File

@@ -207,7 +207,7 @@ describe('Signs', function()
screen:expect([[ screen:expect([[
{2: }{6: 1 }a | {2: }{6: 1 }a |
{2: }{6: 2 }b | {2: }{6: 2 }b |
{1:>>}WW{6: 3 }c | WW{1:>>}{6: 3 }c |
{2: }{6: 4 }^ | {2: }{6: 4 }^ |
{0:~ }|*9 {0:~ }|*9
| |
@@ -220,9 +220,9 @@ describe('Signs', function()
sign place 3 line=2 name=pietError buffer=1 sign place 3 line=2 name=pietError buffer=1
]]) ]])
screen:expect([[ screen:expect([[
{1:>>}{8:XX}{6: 1 }a | {8:XX}{1:>>}{6: 1 }a |
{8:XX}{1:>>}{6: 2 }b | {1:>>}{8:XX}{6: 2 }b |
{1:>>}WW{6: 3 }c | WW{1:>>}{6: 3 }c |
{2: }{6: 4 }^ | {2: }{6: 4 }^ |
{0:~ }|*9 {0:~ }|*9
| |
@@ -240,9 +240,9 @@ describe('Signs', function()
-- "auto:3" accommodates all the signs we defined so far. -- "auto:3" accommodates all the signs we defined so far.
exec('set signcolumn=auto:3') exec('set signcolumn=auto:3')
local s3 = [[ local s3 = [[
{1:>>}{8:XX}{2: }{6: 1 }a | {8:XX}{1:>>}{2: }{6: 1 }a |
{8:XX}{1:>>}{2: }{6: 2 }b | {1:>>}{8:XX}{2: }{6: 2 }b |
{8:XX}{1:>>}WW{6: 3 }c | WW{1:>>}{8:XX}{6: 3 }c |
{2: }{6: 4 }^ | {2: }{6: 4 }^ |
{0:~ }|*9 {0:~ }|*9
| |
@@ -251,9 +251,9 @@ describe('Signs', function()
-- Check "yes:9". -- Check "yes:9".
exec('set signcolumn=yes:9') exec('set signcolumn=yes:9')
screen:expect([[ screen:expect([[
{1:>>}{8:XX}{2: }{6: 1 }a | {8:XX}{1:>>}{2: }{6: 1 }a |
{8:XX}{1:>>}{2: }{6: 2 }b | {1:>>}{8:XX}{2: }{6: 2 }b |
{8:XX}{1:>>}WW{2: }{6: 3 }c | WW{1:>>}{8:XX}{2: }{6: 3 }c |
{2: }{6: 4 }^ | {2: }{6: 4 }^ |
{0:~ }|*9 {0:~ }|*9
| |
@@ -266,8 +266,8 @@ describe('Signs', function()
exec('3move1') exec('3move1')
exec('2d') exec('2d')
screen:expect([[ screen:expect([[
{1:>>}{8:XX}{6: 1 }a | {8:XX}{1:>>}{6: 1 }a |
{8:XX}{1:>>}{6: 2 }^b | {1:>>}{8:XX}{6: 2 }^b |
{2: }{6: 3 } | {2: }{6: 3 } |
{0:~ }|*10 {0:~ }|*10
| |
@@ -275,8 +275,8 @@ describe('Signs', function()
-- character deletion does not delete signs. -- character deletion does not delete signs.
feed('x') feed('x')
screen:expect([[ screen:expect([[
{1:>>}{8:XX}{6: 1 }a | {8:XX}{1:>>}{6: 1 }a |
{8:XX}{1:>>}{6: 2 }^ | {1:>>}{8:XX}{6: 2 }^ |
{2: }{6: 3 } | {2: }{6: 3 } |
{0:~ }|*10 {0:~ }|*10
| |

View File

@@ -237,7 +237,7 @@ describe('statuscolumn', function()
{2: }{1: │ }aaaaa | {2: }{1: │ }aaaaa |
{0:>!}{2: }{1: 5│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {0:>!}{2: }{1: 5│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │ }aaaaa | {2: }{1: │ }aaaaa |
{1:>>}{0:>!}{1: 6│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {0:>!}{1:>> 6│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │ }aaaaa | {2: }{1: │ }aaaaa |
{2: }{1: 7│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 7│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │ }aaaaa | {2: }{1: │ }aaaaa |
@@ -256,7 +256,7 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 6│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
@@ -273,7 +273,7 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 6│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
@@ -291,7 +291,7 @@ describe('statuscolumn', function()
{2: }{1: 4│}{2: }{1: }aaaaaa | {2: }{1: 4│}{2: }{1: }aaaaaa |
{2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 5│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 5│}{2: }{1: }aaaaaa | {2: }{1: 5│}{2: }{1: }aaaaaa |
{2: }{1: 6│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 6│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 6│}{2: }{1: }aaaaaa | {2: }{1: 6│}{2: }{1: }aaaaaa |
{2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 7│}{2: }{1: }aaaaaa | {2: }{1: 7│}{2: }{1: }aaaaaa |
@@ -309,7 +309,7 @@ describe('statuscolumn', function()
{2: }{1: 4│}{2: }{1: }aaaaaa | {2: }{1: 4│}{2: }{1: }aaaaaa |
{2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 3│}{2: }{1: }aaaaaa | {2: }{1: 3│}{2: }{1: }aaaaaa |
{2: }{1: 2│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 2│}{2: }{1: }aaaaaa | {2: }{1: 2│}{2: }{1: }aaaaaa |
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: 1│}{2: }{1: }aaaaaa | {2: }{1: 1│}{2: }{1: }aaaaaa |
@@ -326,7 +326,7 @@ describe('statuscolumn', function()
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 2│>>}{0:>!}{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 2│}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |
{2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: │}{2: }{1: }aaaaaa |