neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

test_signs.vim (79133B)


      1 " Test for signs
      2 
      3 source check.vim
      4 CheckFeature signs
      5 
      6 source screendump.vim
      7 
      8 func Test_sign()
      9  new
     10  call setline(1, ['a', 'b', 'c', 'd'])
     11 
     12  " Define some signs.
     13  " We can specify icons even if not all versions of vim support icons as
     14  " icon is ignored when not supported.  "(not supported)" is shown after
     15  " the icon name when listing signs.
     16  sign define Sign1 text=x
     17 
     18  call Sign_command_ignore_error('sign define Sign2 text=xy texthl=Title linehl=Error culhl=Search numhl=Number icon=../../pixmaps/stock_vim_find_help.png')
     19 
     20  " Test listing signs.
     21  let a=execute('sign list')
     22  call assert_match('^\nsign Sign1 text=x \nsign Sign2 ' .
     23       \ 'icon=../../pixmaps/stock_vim_find_help.png .*text=xy ' .
     24       \ 'linehl=Error texthl=Title culhl=Search numhl=Number$', a)
     25 
     26  let a=execute('sign list Sign1')
     27  call assert_equal("\nsign Sign1 text=x ", a)
     28 
     29  " Split the window to the bottom to verify sign jump will stay in the
     30  " current window if the buffer is displayed there.
     31  let bn = bufnr('%')
     32  let wn = winnr()
     33  exe 'sign place 41 line=3 name=Sign1 buffer=' . bn
     34  1
     35  bot split
     36  exe 'sign jump 41 buffer=' . bufnr('%')
     37  call assert_equal('c', getline('.'))
     38  call assert_equal(3, winnr())
     39  call assert_equal(bn, bufnr('%'))
     40  call assert_notequal(wn, winnr())
     41 
     42  " Create a new buffer and check that ":sign jump" switches to the old buffer.
     43  1
     44  new foo
     45  call assert_notequal(bn, bufnr('%'))
     46  exe 'sign jump 41 buffer=' . bn
     47  call assert_equal(bn, bufnr('%'))
     48  call assert_equal('c', getline('.'))
     49 
     50  " Redraw to make sure that screen redraw with sign gets exercised,
     51  " with and without 'rightleft'.
     52  if has('rightleft')
     53    set rightleft
     54    redraw
     55    set norightleft
     56  endif
     57  redraw
     58 
     59  " Check that we can't change sign.
     60  call assert_fails("sign place 40 name=Sign1 buffer=" . bufnr('%'), 'E885:')
     61 
     62  " Check placed signs
     63  let a=execute('sign place')
     64  call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n" .
     65 	\ "    line=3  id=41  name=Sign1  priority=10", a)
     66 
     67  " Unplace the sign and try jumping to it again should fail.
     68  sign unplace 41
     69  1
     70  call assert_fails("sign jump 41 buffer=" . bufnr('%'), 'E157:')
     71  call assert_equal('a', getline('.'))
     72 
     73  " Unplace sign on current line.
     74  exe 'sign place 42 line=4 name=Sign2 buffer=' . bufnr('%')
     75  4
     76  sign unplace
     77  let a=execute('sign place')
     78  call assert_equal("\n--- Signs ---", a)
     79 
     80  " Try again to unplace sign on current line, it should fail this time.
     81  call assert_fails('sign unplace', 'E159:')
     82 
     83  " Unplace all signs.
     84  exe 'sign place 41 line=3 name=Sign1 buffer=' . bufnr('%')
     85  sign unplace *
     86  let a=execute('sign place')
     87  call assert_equal("\n--- Signs ---", a)
     88 
     89  " Place a sign without specifying the filename or buffer
     90  sign place 77 line=9 name=Sign2
     91  let a=execute('sign place')
     92  " Nvim: sign line clamped to buffer length
     93  call assert_equal("\n--- Signs ---\nSigns for [NULL]:\n" .
     94 	\ "    line=4  id=77  name=Sign2  priority=10", a)
     95  sign unplace *
     96 
     97  " Check :jump with file=...
     98  edit foo
     99  call setline(1, ['A', 'B', 'C', 'D'])
    100 
    101  call Sign_command_ignore_error('sign define Sign3 text=y texthl=DoesNotExist linehl=DoesNotExist icon=doesnotexist.xpm')
    102 
    103  let fn = expand('%:p')
    104  exe 'sign place 43 line=2 name=Sign3 file=' . fn
    105  edit bar
    106  call assert_notequal(fn, expand('%:p'))
    107  exe 'sign jump 43 file=' . fn
    108  call assert_equal('B', getline('.'))
    109 
    110  " Check for jumping to a sign in a hidden buffer
    111  enew! | only!
    112  edit foo
    113  call setline(1, ['A', 'B', 'C', 'D'])
    114  let fn = expand('%:p')
    115  exe 'sign place 21 line=3 name=Sign3 file=' . fn
    116  hide edit bar
    117  exe 'sign jump 21 file=' . fn
    118  call assert_equal('C', getline('.'))
    119 
    120  " can't define a sign with a non-printable character as text
    121  call assert_fails("sign define Sign4 text=\e linehl=Comment", 'E239:')
    122  call assert_fails("sign define Sign4 text=a\e linehl=Comment", 'E239:')
    123  call assert_fails("sign define Sign4 text=\ea linehl=Comment", 'E239:')
    124 
    125  " Only 0, 1 or 2 character text is allowed
    126  call assert_fails("sign define Sign4 text=abc linehl=Comment", 'E239:')
    127  " call assert_fails("sign define Sign4 text= linehl=Comment", 'E239:')
    128  call assert_fails("sign define Sign4 text=\\ ab  linehl=Comment", 'E239:')
    129 
    130  " an empty highlight argument for an existing sign clears it
    131  sign define SignY texthl=TextHl culhl=CulHl linehl=LineHl numhl=NumHl
    132  let sl = sign_getdefined('SignY')[0]
    133  call assert_equal('TextHl', sl.texthl)
    134  call assert_equal('CulHl', sl.culhl)
    135  call assert_equal('LineHl', sl.linehl)
    136  call assert_equal('NumHl', sl.numhl)
    137 
    138  sign define SignY texthl= culhl=CulHl linehl=LineHl numhl=NumHl
    139  let sl = sign_getdefined('SignY')[0]
    140  call assert_false(has_key(sl, 'texthl'))
    141  call assert_equal('CulHl', sl.culhl)
    142  call assert_equal('LineHl', sl.linehl)
    143  call assert_equal('NumHl', sl.numhl)
    144 
    145  sign define SignY linehl=
    146  let sl = sign_getdefined('SignY')[0]
    147  call assert_false(has_key(sl, 'linehl'))
    148  call assert_equal('CulHl', sl.culhl)
    149  call assert_equal('NumHl', sl.numhl)
    150 
    151  sign define SignY culhl=
    152  let sl = sign_getdefined('SignY')[0]
    153  call assert_false(has_key(sl, 'culhl'))
    154  call assert_equal('NumHl', sl.numhl)
    155 
    156  sign define SignY numhl=
    157  let sl = sign_getdefined('SignY')[0]
    158  call assert_false(has_key(sl, 'numhl'))
    159 
    160  sign undefine SignY
    161 
    162  " define sign with whitespace
    163  sign define Sign4 text=\ X linehl=Comment
    164  sign undefine Sign4
    165  sign define Sign4 linehl=Comment text=\ X
    166  sign undefine Sign4
    167 
    168  sign define Sign5 text=X\  linehl=Comment
    169  sign undefine Sign5
    170  sign define Sign5 linehl=Comment text=X\ 
    171  sign undefine Sign5
    172 
    173  " define sign with backslash
    174  sign define Sign4 text=\\\\ linehl=Comment
    175  sign undefine Sign4
    176  sign define Sign4 text=\\ linehl=Comment
    177  sign undefine Sign4
    178 
    179  " define a sign with a leading 0 in the name
    180  sign unplace *
    181  sign define 004 text=#> linehl=Comment
    182  let a = execute('sign list 4')
    183  call assert_equal("\nsign 4 text=#> linehl=Comment", a)
    184  exe 'sign place 20 line=3 name=004 buffer=' . bufnr('')
    185  let a = execute('sign place')
    186  call assert_equal("\n--- Signs ---\nSigns for foo:\n" .
    187 	\ "    line=3  id=20  name=4  priority=10", a)
    188  exe 'sign unplace 20 buffer=' . bufnr('')
    189  sign undefine 004
    190  call assert_fails('sign list 4', 'E155:')
    191 
    192  " After undefining the sign, we should no longer be able to place it.
    193  sign undefine Sign1
    194  sign undefine Sign2
    195  sign undefine Sign3
    196  call assert_fails("sign place 41 line=3 name=Sign1 buffer=" .
    197 		  \ bufnr('%'), 'E155:')
    198 
    199  " Defining a sign without attributes is allowed.
    200  sign define Sign1
    201  call assert_equal([{'name': 'Sign1'}], sign_getdefined())
    202  sign undefine Sign1
    203 endfunc
    204 
    205 func Test_sign_many_bytes()
    206  new
    207  set signcolumn=number
    208  set number
    209  call setline(1, 'some text')
    210  " composing characters can use many bytes, check for overflow
    211  sign define manyBytes text=▶᷄᷅᷆◀᷄᷅᷆᷇
    212  sign place 17 line=1 name=manyBytes
    213  redraw
    214 
    215  bwipe!
    216  sign undefine manyBytes
    217 endfunc
    218 
    219 " Undefining placed sign is not recommended.
    220 " Quoting :help sign
    221 "
    222 " :sign undefine {name}
    223 "                Deletes a previously defined sign.  If signs with this {name}
    224 "                are still placed this will cause trouble.
    225 func Test_sign_undefine_still_placed()
    226  new foobar
    227  sign define Sign text=x
    228  exe 'sign place 41 line=1 name=Sign buffer=' . bufnr('%')
    229  sign undefine Sign
    230 
    231  " Listing placed sign should show that sign is deleted.
    232  let a=execute('sign place')
    233  call assert_equal("\n--- Signs ---\nSigns for foobar:\n" .
    234 	\ "    line=1  id=41  name=[Deleted]  priority=10", a)
    235 
    236  sign unplace 41
    237  let a=execute('sign place')
    238  call assert_equal("\n--- Signs ---", a)
    239 endfunc
    240 
    241 func Test_sign_completion()
    242  sign define Sign1 text=x
    243  sign define Sign2 text=y
    244 
    245  call feedkeys(":sign \<C-A>\<C-B>\"\<CR>", 'tx')
    246  call assert_equal('"sign define jump list place undefine unplace', @:)
    247 
    248  call feedkeys(":sign define Sign \<C-A>\<C-B>\"\<CR>", 'tx')
    249  call assert_equal('"sign define Sign culhl= icon= linehl= numhl= priority= text= texthl=', @:)
    250 
    251  for hl in ['culhl', 'linehl', 'numhl', 'texthl']
    252    call feedkeys(":sign define Sign "..hl.."=Spell\<C-A>\<C-B>\"\<CR>", 'tx')
    253    call assert_equal('"sign define Sign '..hl..'=SpellBad SpellCap ' .
    254                \ 'SpellLocal SpellRare', @:)
    255  endfor
    256 
    257  call writefile(repeat(["Sun is shining"], 30), "XsignOne", 'D')
    258  call writefile(repeat(["Sky is blue"], 30), "XsignTwo", 'D')
    259  call feedkeys(":sign define Sign icon=Xsig\<C-A>\<C-B>\"\<CR>", 'tx')
    260  call assert_equal('"sign define Sign icon=XsignOne XsignTwo', @:)
    261 
    262  " Test for completion of arguments to ':sign undefine'
    263  call feedkeys(":sign undefine \<C-A>\<C-B>\"\<CR>", 'tx')
    264  call assert_equal('"sign undefine Sign1 Sign2', @:)
    265 
    266  call feedkeys(":sign place 1 \<C-A>\<C-B>\"\<CR>", 'tx')
    267  call assert_equal('"sign place 1 buffer= file= group= line= name= priority=',
    268       \ @:)
    269 
    270  call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
    271  call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
    272 
    273  edit XsignOne
    274  sign place 1 name=Sign1 line=5
    275  sign place 1 name=Sign1 group=g1 line=10
    276  edit XsignTwo
    277  sign place 1 name=Sign2 group=g2 line=15
    278 
    279  " Test for completion of group= and file= arguments to ':sign place'
    280  call feedkeys(":sign place 1 name=Sign1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
    281  call assert_equal('"sign place 1 name=Sign1 file=XsignOne XsignTwo', @:)
    282  call feedkeys(":sign place 1 name=Sign1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
    283  call assert_equal('"sign place 1 name=Sign1 group=g1 g2', @:)
    284 
    285  " Test for completion of arguments to 'sign place' without sign identifier
    286  call feedkeys(":sign place \<C-A>\<C-B>\"\<CR>", 'tx')
    287  call assert_equal('"sign place buffer= file= group=', @:)
    288  call feedkeys(":sign place file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
    289  call assert_equal('"sign place file=XsignOne XsignTwo', @:)
    290  call feedkeys(":sign place group=\<C-A>\<C-B>\"\<CR>", 'tx')
    291  call assert_equal('"sign place group=g1 g2', @:)
    292  call feedkeys(":sign place group=g1 file=\<C-A>\<C-B>\"\<CR>", 'tx')
    293  call assert_equal('"sign place group=g1 file=XsignOne XsignTwo', @:)
    294 
    295  " Test for completion of arguments to ':sign unplace'
    296  call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
    297  call assert_equal('"sign unplace 1 buffer= file= group=', @:)
    298  call feedkeys(":sign unplace 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
    299  call assert_equal('"sign unplace 1 file=XsignOne XsignTwo', @:)
    300  call feedkeys(":sign unplace 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
    301  call assert_equal('"sign unplace 1 group=g1 g2', @:)
    302  call feedkeys(":sign unplace 1 group=g2 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
    303  call assert_equal('"sign unplace 1 group=g2 file=XsignOne XsignTwo', @:)
    304 
    305  " Test for completion of arguments to ':sign list'
    306  call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
    307  call assert_equal('"sign list Sign1 Sign2', @:)
    308 
    309  " Test for completion of arguments to ':sign jump'
    310  call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
    311  call assert_equal('"sign jump 1 buffer= file= group=', @:)
    312  call feedkeys(":sign jump 1 file=Xsign\<C-A>\<C-B>\"\<CR>", 'tx')
    313  call assert_equal('"sign jump 1 file=XsignOne XsignTwo', @:)
    314  call feedkeys(":sign jump 1 group=\<C-A>\<C-B>\"\<CR>", 'tx')
    315  call assert_equal('"sign jump 1 group=g1 g2', @:)
    316 
    317  " Error cases
    318  call feedkeys(":sign here\<C-A>\<C-B>\"\<CR>", 'tx')
    319  call assert_equal('"sign here', @:)
    320  call feedkeys(":sign define Sign here=\<C-A>\<C-B>\"\<CR>", 'tx')
    321  call assert_equal("\"sign define Sign here=\<C-A>", @:)
    322  call feedkeys(":sign place 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
    323  call assert_equal("\"sign place 1 here=\<C-A>", @:)
    324  call feedkeys(":sign jump 1 here=\<C-A>\<C-B>\"\<CR>", 'tx')
    325  call assert_equal("\"sign jump 1 here=\<C-A>", @:)
    326  call feedkeys(":sign here there\<C-A>\<C-B>\"\<CR>", 'tx')
    327  call assert_equal("\"sign here there\<C-A>", @:)
    328  call feedkeys(":sign here there=\<C-A>\<C-B>\"\<CR>", 'tx')
    329  call assert_equal("\"sign here there=\<C-A>", @:)
    330 
    331  sign unplace * group=*
    332  sign undefine Sign1
    333  sign undefine Sign2
    334  enew
    335 endfunc
    336 
    337 func Test_sign_invalid_commands()
    338  sign define Sign1 text=x
    339 
    340  call assert_fails('sign', 'E471:')
    341  call assert_fails('sign jump', 'E471:')
    342  call assert_fails('sign xxx', 'E160:')
    343  call assert_fails('sign define', 'E156:')
    344  call assert_fails('sign define Sign1 xxx', 'E475:')
    345  call assert_fails('sign undefine', 'E156:')
    346  call assert_fails('sign list xxx', 'E155:')
    347  call assert_fails('sign place 1 buffer=999', 'E158:')
    348  call assert_fails('sign place 1 name=Sign1 buffer=999', 'E158:')
    349  call assert_fails('sign place buffer=999', 'E158:')
    350  call assert_fails('sign jump buffer=999', 'E158:')
    351  call assert_fails('sign jump 1 file=', 'E158:')
    352  call assert_fails('sign jump 1 group=', 'E474:')
    353  call assert_fails('sign jump 1 name=', 'E474:')
    354  call assert_fails('sign jump 1 name=Sign1', 'E474:')
    355  call assert_fails('sign jump 1 line=100', '474:')
    356  " call assert_fails('sign define Sign2 text=', 'E239:')
    357  " Non-numeric identifier for :sign place
    358  call assert_fails("sign place abc line=3 name=Sign1 buffer=" . bufnr(''),
    359 							\ 'E474:')
    360  " Non-numeric identifier for :sign unplace
    361  call assert_fails("sign unplace abc name=Sign1 buffer=" . bufnr(''),
    362 							\ 'E474:')
    363  " Number followed by an alphabet as sign identifier for :sign place
    364  call assert_fails("sign place 1abc line=3 name=Sign1 buffer=" . bufnr(''),
    365 							\ 'E474:')
    366  " Number followed by an alphabet as sign identifier for :sign unplace
    367  call assert_fails("sign unplace 2abc name=Sign1 buffer=" . bufnr(''),
    368 							\ 'E474:')
    369  " Sign identifier and '*' for :sign unplace
    370  call assert_fails("sign unplace 2 *", 'E474:')
    371  " Trailing characters after buffer number for :sign place
    372  call assert_fails("sign place 1 line=3 name=Sign1 buffer=" .
    373 					\ bufnr('%') . 'xxx', 'E488:')
    374  " Trailing characters after buffer number for :sign unplace
    375  call assert_fails("sign unplace 1 buffer=" . bufnr('%') . 'xxx', 'E488:')
    376  call assert_fails("sign unplace * buffer=" . bufnr('%') . 'xxx', 'E488:')
    377  call assert_fails("sign unplace 1 xxx", 'E474:')
    378  call assert_fails("sign unplace * xxx", 'E474:')
    379  call assert_fails("sign unplace xxx", 'E474:')
    380  " Placing a sign without line number
    381  call assert_fails("sign place name=Sign1 buffer=" . bufnr('%'), 'E474:')
    382  " Placing a sign without sign name
    383  call assert_fails("sign place line=10 buffer=" . bufnr('%'), 'E474:')
    384  " Unplacing a sign with line number
    385  call assert_fails("sign unplace 2 line=10 buffer=" . bufnr('%'), 'E474:')
    386  " Unplacing a sign with sign name
    387  call assert_fails("sign unplace 2 name=Sign1 buffer=" . bufnr('%'), 'E474:')
    388  " Placing a sign without sign name
    389  call assert_fails("sign place 2 line=3 buffer=" . bufnr('%'), 'E474:')
    390  " Placing a sign with only sign identifier
    391  call assert_fails("sign place 2", 'E474:')
    392  " Placing a sign with only a name
    393  call assert_fails("sign place abc", 'E474:')
    394  " Placing a sign with only line number
    395  call assert_fails("sign place 5 line=3", 'E474:')
    396  " Placing a sign with only sign group
    397  call assert_fails("sign place 5 group=g1", 'E474:')
    398  call assert_fails("sign place 5 group=*", 'E474:')
    399  " Placing a sign with only sign priority
    400  call assert_fails("sign place 5 priority=10", 'E474:')
    401 
    402  sign undefine Sign1
    403 endfunc
    404 
    405 func Test_sign_delete_buffer()
    406  new
    407  sign define Sign text=x
    408  let bufnr = bufnr('%')
    409  new
    410  exe 'bd ' . bufnr
    411  exe 'sign place 61 line=3 name=Sign buffer=' . bufnr
    412  call assert_fails('sign jump 61 buffer=' . bufnr, 'E934:')
    413  sign unplace 61
    414  sign undefine Sign
    415 endfunc
    416 
    417 " Ignore error: E255: Couldn't read in sign data!
    418 " This error can happen when running in the GUI.
    419 " Some gui like Motif do not support the png icon format.
    420 func Sign_command_ignore_error(cmd)
    421  try
    422    exe a:cmd
    423  catch /E255:/
    424  endtry
    425 endfunc
    426 
    427 " ignore error: E255: Couldn't read in sign data!
    428 " This error can happen when running in gui.
    429 func Sign_define_ignore_error(name, attr)
    430  try
    431    call sign_define(a:name, a:attr)
    432  catch /E255:/
    433  endtry
    434 endfunc
    435 
    436 " Test for Vim script functions for managing signs
    437 func Test_sign_funcs()
    438  " Remove all the signs
    439  call sign_unplace('*')
    440  call sign_undefine()
    441 
    442  " Tests for sign_define()
    443  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error',
    444              \ 'culhl': 'Visual', 'numhl': 'Number'}
    445  call assert_equal(0, "sign1"->sign_define(attr))
    446  call assert_equal([{'name' : 'sign1', 'texthl' : 'Error', 'linehl' : 'Search',
    447              \ 'culhl' : 'Visual', 'numhl': 'Number', 'text' : '=>'}],
    448              \ sign_getdefined())
    449 
    450  " Define a new sign without attributes and then update it
    451  call sign_define("sign2")
    452  let attr = {'text' : '!!', 'linehl' : 'DiffAdd', 'texthl' : 'DiffChange',
    453       \ 'culhl': 'DiffDelete', 'numhl': 'Number', 'icon' : 'sign2.ico'}
    454  call Sign_define_ignore_error("sign2", attr)
    455  call assert_equal([{'name' : 'sign2', 'texthl' : 'DiffChange',
    456       \ 'linehl' : 'DiffAdd', 'culhl' : 'DiffDelete', 'text' : '!!',
    457              \ 'numhl': 'Number', 'icon' : 'sign2.ico'}],
    458              \ "sign2"->sign_getdefined())
    459 
    460  " Test for a sign name with digits
    461  call assert_equal(0, sign_define(0002, {'linehl' : 'StatusLine'}))
    462  call assert_equal([{'name' : '2', 'linehl' : 'StatusLine'}],
    463       \ sign_getdefined(0002))
    464  eval 0002->sign_undefine()
    465 
    466  " Tests for invalid arguments to sign_define()
    467  call assert_fails('call sign_define("sign4", {"text" : "===>"})', 'E239:')
    468  " call assert_fails('call sign_define("sign5", {"text" : ""})', 'E239:')
    469  call assert_fails('call sign_define({})', 'E731:')
    470  call assert_fails('call sign_define("sign6", [])', 'E1206:')
    471 
    472  " Tests for sign_getdefined()
    473  call assert_equal([], sign_getdefined("none"))
    474  call assert_fails('call sign_getdefined({})', 'E731:')
    475 
    476  " Tests for sign_place()
    477  call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
    478  edit Xsign
    479 
    480  call assert_equal(10, sign_place(10, '', 'sign1', 'Xsign',
    481       \ {'lnum' : 20}))
    482  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    483       \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
    484       \ 'priority' : 10}]}], sign_getplaced('Xsign'))
    485  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    486       \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
    487       \ 'priority' : 10}]}],
    488       \ '%'->sign_getplaced({'lnum' : 20}))
    489  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    490       \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
    491       \ 'priority' : 10}]}],
    492       \ sign_getplaced('', {'id' : 10}))
    493 
    494  " Tests for invalid arguments to sign_place()
    495  call assert_fails('call sign_place([], "", "mySign", 1)', 'E745:')
    496  call assert_fails('call sign_place(5, "", "mySign", -1)', 'E158:')
    497  call assert_fails('call sign_place(-1, "", "sign1", "Xsign", [])', 'E1206:')
    498  call assert_fails('call sign_place(-1, "", "sign1", "Xsign",
    499       \ {"lnum" : 30})', 'E474:')
    500  call assert_fails('call sign_place(10, "", "xsign1x", "Xsign",
    501       \ {"lnum" : 30})', 'E155:')
    502  call assert_fails('call sign_place(10, "", "", "Xsign",
    503       \ {"lnum" : 30})', 'E155:')
    504  call assert_fails('call sign_place(10, "", [], "Xsign",
    505       \ {"lnum" : 30})', 'E730:')
    506  call assert_fails('call sign_place(5, "", "sign1", "abcxyz.xxx",
    507       \ {"lnum" : 10})', 'E158:')
    508  call assert_fails('call sign_place(5, "", "sign1", "@", {"lnum" : 10})',
    509       \ 'E158:')
    510  call assert_fails('call sign_place(5, "", "sign1", [], {"lnum" : 10})',
    511       \ 'E730:')
    512  call assert_fails('call sign_place(21, "", "sign1", "Xsign",
    513       \ {"lnum" : -1})', 'E474:')
    514  call assert_fails('call sign_place(22, "", "sign1", "Xsign",
    515       \ {"lnum" : 0})', 'E474:')
    516  call assert_fails('call sign_place(22, "", "sign1", "Xsign",
    517       \ {"lnum" : []})', 'E745:')
    518  call assert_equal(-1, sign_place(1, "*", "sign1", "Xsign", {"lnum" : 10}))
    519 
    520  " Tests for sign_getplaced()
    521  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    522       \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
    523       \ 'priority' : 10}]}],
    524       \ sign_getplaced(bufnr('Xsign')))
    525  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    526       \ [{'id' : 10, 'group' : '', 'lnum' : 20, 'name' : 'sign1',
    527       \ 'priority' : 10}]}],
    528       \ sign_getplaced())
    529  call assert_fails("call sign_getplaced('dummy.sign')", 'E158:')
    530  call assert_fails('call sign_getplaced("&")', 'E158:')
    531  call assert_fails('call sign_getplaced(-1)', 'E158:')
    532  call assert_fails('call sign_getplaced("Xsign", [])', 'E1206:')
    533  call assert_equal([{'bufnr' : bufnr(''), 'signs' : []}],
    534       \ sign_getplaced('Xsign', {'lnum' : 1000000}))
    535  call assert_fails("call sign_getplaced('Xsign', {'lnum' : []})",
    536       \ 'E745:')
    537  call assert_equal([{'bufnr' : bufnr(''), 'signs' : []}],
    538       \ sign_getplaced('Xsign', {'id' : 44}))
    539  call assert_fails("call sign_getplaced('Xsign', {'id' : []})",
    540       \ 'E745:')
    541 
    542  " Tests for sign_unplace()
    543  eval 20->sign_place('', 'sign2', 'Xsign', {"lnum" : 30})
    544  call assert_equal(0, sign_unplace('',
    545       \ {'id' : 20, 'buffer' : 'Xsign'}))
    546  call assert_equal(-1, ''->sign_unplace(
    547       \ {'id' : 30, 'buffer' : 'Xsign'}))
    548  call sign_place(20, '', 'sign2', 'Xsign', {"lnum" : 30})
    549  call assert_fails("call sign_unplace('',
    550       \ {'id' : 20, 'buffer' : 'buffer.c'})", 'E158:')
    551  call assert_fails("call sign_unplace('',
    552       \ {'id' : 20, 'buffer' : '&'})", 'E158:')
    553  call assert_fails("call sign_unplace('g1',
    554       \ {'id' : 20, 'buffer' : 200})", 'E158:')
    555  call assert_fails("call sign_unplace('g1', 'mySign')", 'E1206:')
    556 
    557  call sign_unplace('*')
    558 
    559  " Test for modifying a placed sign
    560  call assert_equal(15, sign_place(15, '', 'sign1', 'Xsign', {'lnum' : 20}))
    561  call assert_equal(15, sign_place(15, '', 'sign2', 'Xsign'))
    562  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    563       \ [{'id' : 15, 'group' : '', 'lnum' : 20, 'name' : 'sign2',
    564       \ 'priority' : 10}]}],
    565       \ sign_getplaced())
    566 
    567  " Tests for sign_undefine()
    568  call assert_equal(0, sign_undefine("sign1"))
    569  call assert_equal([], sign_getdefined("sign1"))
    570  call assert_fails('call sign_undefine("none")', 'E155:')
    571  call assert_fails('call sign_undefine({})', 'E731:')
    572 
    573  " Test for using '.' as the line number for sign_place()
    574  call Sign_define_ignore_error("sign1", attr)
    575  call cursor(22, 1)
    576  call assert_equal(15, sign_place(15, '', 'sign1', 'Xsign',
    577       \ {'lnum' : '.'}))
    578  call assert_equal([{'bufnr' : bufnr(''), 'signs' :
    579       \ [{'id' : 15, 'group' : '', 'lnum' : 22, 'name' : 'sign1',
    580       \ 'priority' : 10}]}],
    581       \ sign_getplaced('%', {'lnum' : 22}))
    582 
    583  call sign_unplace('*')
    584  call sign_undefine()
    585  enew | only
    586 endfunc
    587 
    588 " Tests for sign groups
    589 func Test_sign_group()
    590  enew | only
    591  " Remove all the signs
    592  call sign_unplace('*')
    593  call sign_undefine()
    594 
    595  call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
    596 
    597  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
    598  call assert_equal(0, sign_define("sign1", attr))
    599 
    600  edit Xsign
    601  let bnum = bufnr('%')
    602 
    603  " Error case
    604  call assert_fails("call sign_place(5, [], 'sign1', 'Xsign',
    605       \ {'lnum' : 30})", 'E730:')
    606 
    607  " place three signs with the same identifier. One in the global group and
    608  " others in the named groups
    609  call assert_equal(5, sign_place(5, '', 'sign1', 'Xsign',
    610       \ {'lnum' : 10}))
    611  call assert_equal(5, sign_place(5, 'g1', 'sign1', bnum, {'lnum' : 20}))
    612  call assert_equal(5, sign_place(5, 'g2', 'sign1', bnum, {'lnum' : 30}))
    613 
    614  " Test for sign_getplaced() with group
    615  let s = sign_getplaced('Xsign')
    616  call assert_equal(1, len(s[0].signs))
    617  call assert_equal(s[0].signs[0].group, '')
    618  let s = sign_getplaced(bnum, {'group' : ''})
    619  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
    620       \ 'priority' : 10}], s[0].signs)
    621  call assert_equal(1, len(s[0].signs))
    622  let s = sign_getplaced(bnum, {'group' : 'g2'})
    623  call assert_equal('g2', s[0].signs[0].group)
    624  let s = sign_getplaced(bnum, {'group' : 'g3'})
    625  call assert_equal([], s[0].signs)
    626  let s = sign_getplaced(bnum, {'group' : '*'})
    627  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
    628       \ 'priority' : 10},
    629       \ {'id' : 5, 'group' : 'g1', 'name' : 'sign1', 'lnum' : 20,
    630       \  'priority' : 10},
    631       \ {'id' : 5, 'group' : 'g2', 'name' : 'sign1', 'lnum' : 30,
    632       \  'priority' : 10}],
    633       \ s[0].signs)
    634 
    635  " Test for sign_getplaced() with id
    636  let s = sign_getplaced(bnum, {'id' : 5})
    637  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
    638       \ 'priority' : 10}],
    639       \ s[0].signs)
    640  let s = sign_getplaced(bnum, {'id' : 5, 'group' : 'g2'})
    641  call assert_equal(
    642       \ [{'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
    643       \ 'priority' : 10}],
    644       \ s[0].signs)
    645  let s = sign_getplaced(bnum, {'id' : 5, 'group' : '*'})
    646  call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
    647       \ 'priority' : 10},
    648       \ {'id' : 5, 'group' : 'g1', 'name' : 'sign1', 'lnum' : 20,
    649       \ 'priority' : 10},
    650       \ {'id' : 5, 'group' : 'g2', 'name' : 'sign1', 'lnum' : 30,
    651       \ 'priority' : 10}],
    652       \ s[0].signs)
    653  let s = sign_getplaced(bnum, {'id' : 5, 'group' : 'g3'})
    654  call assert_equal([], s[0].signs)
    655 
    656  " Test for sign_getplaced() with lnum
    657  let s = sign_getplaced(bnum, {'lnum' : 20})
    658  call assert_equal([], s[0].signs)
    659  let s = sign_getplaced(bnum, {'lnum' : 20, 'group' : 'g1'})
    660  call assert_equal(
    661       \ [{'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : 'g1',
    662       \ 'priority' : 10}],
    663       \ s[0].signs)
    664  let s = sign_getplaced(bnum, {'lnum' : 30, 'group' : '*'})
    665  call assert_equal(
    666       \ [{'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
    667       \ 'priority' : 10}],
    668       \ s[0].signs)
    669  let s = sign_getplaced(bnum, {'lnum' : 40, 'group' : '*'})
    670  call assert_equal([], s[0].signs)
    671 
    672  " Error case
    673  call assert_fails("call sign_getplaced(bnum, {'group' : []})",
    674       \ 'E730:')
    675 
    676  " Clear the sign in global group
    677  call sign_unplace('', {'id' : 5, 'buffer' : bnum})
    678  let s = sign_getplaced(bnum, {'group' : '*'})
    679  call assert_equal([
    680       \ {'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : 'g1',
    681       \ 'priority' : 10},
    682       \ {'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
    683       \ 'priority' : 10}],
    684       \ s[0].signs)
    685 
    686  " Clear the sign in one of the groups
    687  call sign_unplace('g1', {'buffer' : 'Xsign'})
    688  let s = sign_getplaced(bnum, {'group' : '*'})
    689  call assert_equal([
    690       \ {'id' : 5, 'name' : 'sign1', 'lnum' : 30, 'group' : 'g2',
    691       \ 'priority' : 10}],
    692       \ s[0].signs)
    693 
    694  " Clear all the signs from the buffer
    695  call sign_unplace('*', {'buffer' : bnum})
    696  call assert_equal([], sign_getplaced(bnum, {'group' : '*'})[0].signs)
    697 
    698  " Clear sign across groups using an identifier
    699  call sign_place(25, '', 'sign1', bnum, {'lnum' : 10})
    700  call sign_place(25, 'g1', 'sign1', bnum, {'lnum' : 11})
    701  call sign_place(25, 'g2', 'sign1', bnum, {'lnum' : 12})
    702  call assert_equal(0, sign_unplace('*', {'id' : 25}))
    703  call assert_equal([], sign_getplaced(bnum, {'group' : '*'})[0].signs)
    704 
    705  " Error case
    706  call assert_fails("call sign_unplace({})", 'E1174:')
    707 
    708  " Place a sign in the global group and try to delete it using a group
    709  call assert_equal(5, sign_place(5, '', 'sign1', bnum, {'lnum' : 10}))
    710  call assert_equal(-1, sign_unplace('g1', {'id' : 5}))
    711 
    712  " Place signs in multiple groups and delete all the signs in one of the
    713  " group
    714  call assert_equal(5, sign_place(5, '', 'sign1', bnum, {'lnum' : 10}))
    715  call assert_equal(6, sign_place(6, '', 'sign1', bnum, {'lnum' : 11}))
    716  call assert_equal(5, sign_place(5, 'g1', 'sign1', bnum, {'lnum' : 10}))
    717  call assert_equal(5, sign_place(5, 'g2', 'sign1', bnum, {'lnum' : 10}))
    718  call assert_equal(6, sign_place(6, 'g1', 'sign1', bnum, {'lnum' : 11}))
    719  call assert_equal(6, sign_place(6, 'g2', 'sign1', bnum, {'lnum' : 11}))
    720  call assert_equal(0, sign_unplace('g1'))
    721  let s = sign_getplaced(bnum, {'group' : 'g1'})
    722  call assert_equal([], s[0].signs)
    723  let s = sign_getplaced(bnum)
    724  call assert_equal(2, len(s[0].signs))
    725  let s = sign_getplaced(bnum, {'group' : 'g2'})
    726  call assert_equal('g2', s[0].signs[0].group)
    727  call assert_equal(0, sign_unplace('', {'id' : 5}))
    728  call assert_equal(0, sign_unplace('', {'id' : 6}))
    729  let s = sign_getplaced(bnum, {'group' : 'g2'})
    730  call assert_equal('g2', s[0].signs[0].group)
    731  call assert_equal(0, sign_unplace('', {'buffer' : bnum}))
    732 
    733  call sign_unplace('*')
    734 
    735  " Test for :sign command and groups
    736  sign place 5 line=10 name=sign1 file=Xsign
    737  sign place 5 group=g1 line=10 name=sign1 file=Xsign
    738  sign place 5 group=g2 line=10 name=sign1 file=Xsign
    739 
    740  " Tests for the ':sign place' command
    741 
    742  " :sign place file={fname}
    743  let a = execute('sign place file=Xsign')
    744  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    745       \ "    line=10  id=5  name=sign1  priority=10", a)
    746 
    747  " :sign place group={group} file={fname}
    748  let a = execute('sign place group=g2 file=Xsign')
    749  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    750       \ "    line=10  id=5  group=g2  name=sign1  priority=10", a)
    751 
    752  " :sign place group=* file={fname}
    753  let a = execute('sign place group=* file=Xsign')
    754  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    755       \ "    line=10  id=5  group=g2  name=sign1  priority=10\n" .
    756       \ "    line=10  id=5  group=g1  name=sign1  priority=10\n" .
    757       \ "    line=10  id=5  name=sign1  priority=10", a)
    758 
    759  " Error case: non-existing group
    760  let a = execute('sign place group=xyz file=Xsign')
    761  call assert_equal("\n--- Signs ---\nSigns for Xsign:", a)
    762 
    763  call sign_unplace('*')
    764  let bnum = bufnr('Xsign')
    765  exe 'sign place 5 line=10 name=sign1 buffer=' . bnum
    766  exe 'sign place 5 group=g1 line=11 name=sign1 buffer=' . bnum
    767  exe 'sign place 5 group=g2 line=12 name=sign1 buffer=' . bnum
    768 
    769  " :sign place buffer={fname}
    770  let a = execute('sign place buffer=' . bnum)
    771  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    772       \ "    line=10  id=5  name=sign1  priority=10", a)
    773 
    774  " :sign place group={group} buffer={fname}
    775  let a = execute('sign place group=g2 buffer=' . bnum)
    776  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    777       \ "    line=12  id=5  group=g2  name=sign1  priority=10", a)
    778 
    779  " :sign place group=* buffer={fname}
    780  let a = execute('sign place group=* buffer=' . bnum)
    781  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    782       \ "    line=10  id=5  name=sign1  priority=10\n" .
    783       \ "    line=11  id=5  group=g1  name=sign1  priority=10\n" .
    784       \ "    line=12  id=5  group=g2  name=sign1  priority=10", a)
    785 
    786  " Error case: non-existing group
    787  let a = execute('sign place group=xyz buffer=' . bnum)
    788  call assert_equal("\n--- Signs ---\nSigns for Xsign:", a)
    789 
    790  " :sign place
    791  let a = execute('sign place')
    792  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    793       \ "    line=10  id=5  name=sign1  priority=10", a)
    794 
    795  " Place signs in more than one buffer and list the signs
    796  split foo
    797  set buftype=nofile
    798  sign place 25 line=76 name=sign1 priority=99 file=foo
    799  let a = execute('sign place')
    800  " Nvim: sign line clamped to buffer length
    801  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    802       \ "    line=10  id=5  name=sign1  priority=10\n" .
    803       \ "Signs for foo:\n" .
    804       \ "    line=1  id=25  name=sign1  priority=99", a)
    805  close
    806  bwipe foo
    807 
    808  " :sign place group={group}
    809  let a = execute('sign place group=g1')
    810  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    811       \ "    line=11  id=5  group=g1  name=sign1  priority=10", a)
    812 
    813  " :sign place group=*
    814  let a = execute('sign place group=*')
    815  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
    816       \ "    line=10  id=5  name=sign1  priority=10\n" .
    817       \ "    line=11  id=5  group=g1  name=sign1  priority=10\n" .
    818       \ "    line=12  id=5  group=g2  name=sign1  priority=10", a)
    819 
    820  " Test for ':sign jump' command with groups
    821  sign jump 5 group=g1 file=Xsign
    822  call assert_equal(11, line('.'))
    823  call assert_equal('Xsign', bufname(''))
    824  sign jump 5 group=g2 file=Xsign
    825  call assert_equal(12, line('.'))
    826 
    827  " Test for :sign jump command without the filename or buffer
    828  sign jump 5
    829  call assert_equal(10, line('.'))
    830  sign jump 5 group=g1
    831  call assert_equal(11, line('.'))
    832 
    833  " Error cases
    834  call assert_fails("sign place 3 group= name=sign1 buffer=" . bnum, 'E474:')
    835 
    836  call sign_unplace('*')
    837  call sign_undefine()
    838  enew | only
    839 endfunc
    840 
    841 " Place signs used for ":sign unplace" command test
    842 func Place_signs_for_test()
    843  call sign_unplace('*')
    844 
    845  sign place 3 line=10 name=sign1 file=Xsign1
    846  sign place 3 group=g1 line=11 name=sign1 file=Xsign1
    847  sign place 3 group=g2 line=12 name=sign1 file=Xsign1
    848  sign place 4 line=15 name=sign1 file=Xsign1
    849  sign place 4 group=g1 line=16 name=sign1 file=Xsign1
    850  sign place 4 group=g2 line=17 name=sign1 file=Xsign1
    851  sign place 5 line=20 name=sign1 file=Xsign2
    852  sign place 5 group=g1 line=21 name=sign1 file=Xsign2
    853  sign place 5 group=g2 line=22 name=sign1 file=Xsign2
    854  sign place 6 line=25 name=sign1 file=Xsign2
    855  sign place 6 group=g1 line=26 name=sign1 file=Xsign2
    856  sign place 6 group=g2 line=27 name=sign1 file=Xsign2
    857 endfunc
    858 
    859 " Place multiple signs in a single line for test
    860 func Place_signs_at_line_for_test()
    861  call sign_unplace('*')
    862  sign place 3 line=13 name=sign1 file=Xsign1
    863  sign place 3 group=g1 line=13 name=sign1 file=Xsign1
    864  sign place 3 group=g2 line=13 name=sign1 file=Xsign1
    865  sign place 4 line=13 name=sign1 file=Xsign1
    866  sign place 4 group=g1 line=13 name=sign1 file=Xsign1
    867  sign place 4 group=g2 line=13 name=sign1 file=Xsign1
    868 endfunc
    869 
    870 " Tests for the ':sign unplace' command
    871 func Test_sign_unplace()
    872  enew | only
    873  " Remove all the signs
    874  call sign_unplace('*')
    875  call sign_undefine()
    876 
    877  " Create two files and define signs
    878  call writefile(repeat(["Sun is shining"], 30), "Xsign1", 'D')
    879  call writefile(repeat(["It is beautiful"], 30), "Xsign2", 'D')
    880 
    881  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
    882  call sign_define("sign1", attr)
    883 
    884  edit Xsign1
    885  let bnum1 = bufnr('%')
    886  split Xsign2
    887  let bnum2 = bufnr('%')
    888 
    889  let signs1 = [{'id' : 3, 'name' : 'sign1', 'lnum' : 10, 'group' : '',
    890       \ 'priority' : 10},
    891       \ {'id' : 3, 'name' : 'sign1', 'lnum' : 11, 'group' : 'g1',
    892       \ 'priority' : 10},
    893       \ {'id' : 3, 'name' : 'sign1', 'lnum' : 12, 'group' : 'g2',
    894       \ 'priority' : 10},
    895       \ {'id' : 4, 'name' : 'sign1', 'lnum' : 15, 'group' : '',
    896       \ 'priority' : 10},
    897       \ {'id' : 4, 'name' : 'sign1', 'lnum' : 16, 'group' : 'g1',
    898       \ 'priority' : 10},
    899       \ {'id' : 4, 'name' : 'sign1', 'lnum' : 17, 'group' : 'g2',
    900       \ 'priority' : 10},]
    901  let signs2 = [{'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : '',
    902       \ 'priority' : 10},
    903       \ {'id' : 5, 'name' : 'sign1', 'lnum' : 21, 'group' : 'g1',
    904       \ 'priority' : 10},
    905       \ {'id' : 5, 'name' : 'sign1', 'lnum' : 22, 'group' : 'g2',
    906       \ 'priority' : 10},
    907       \ {'id' : 6, 'name' : 'sign1', 'lnum' : 25, 'group' : '',
    908       \ 'priority' : 10},
    909       \ {'id' : 6, 'name' : 'sign1', 'lnum' : 26, 'group' : 'g1',
    910       \ 'priority' : 10},
    911       \ {'id' : 6, 'name' : 'sign1', 'lnum' : 27, 'group' : 'g2',
    912       \ 'priority' : 10},]
    913 
    914  " Test for :sign unplace {id} file={fname}
    915  call Place_signs_for_test()
    916  sign unplace 3 file=Xsign1
    917  sign unplace 6 file=Xsign2
    918  call assert_equal(
    919       \ filter(copy(signs1),
    920       \     {idx, val -> val.id != 3 || val.group != ''}),
    921       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
    922  call assert_equal(
    923       \ filter(copy(signs2),
    924       \     {idx, val -> val.id != 6 || val.group != ''}),
    925       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
    926 
    927  " Test for :sign unplace {id} group={group} file={fname}
    928  call Place_signs_for_test()
    929  sign unplace 4 group=g1 file=Xsign1
    930  sign unplace 5 group=g2 file=Xsign2
    931  call assert_equal(
    932       \ filter(copy(signs1),
    933       \     {idx, val -> val.id != 4 || val.group != 'g1'}),
    934       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
    935  call assert_equal(
    936       \ filter(copy(signs2),
    937       \     {idx, val -> val.id != 5 || val.group != 'g2'}),
    938       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
    939 
    940  " Test for :sign unplace {id} group=* file={fname}
    941  call Place_signs_for_test()
    942  sign unplace 3 group=* file=Xsign1
    943  sign unplace 6 group=* file=Xsign2
    944  call assert_equal(
    945       \ filter(copy(signs1),
    946       \     {idx, val -> val.id != 3}),
    947       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
    948  call assert_equal(
    949       \ filter(copy(signs2),
    950       \     {idx, val -> val.id != 6}),
    951       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
    952 
    953  " Test for :sign unplace * file={fname}
    954  call Place_signs_for_test()
    955  sign unplace * file=Xsign1
    956  call assert_equal(
    957       \ filter(copy(signs1),
    958       \     {idx, val -> val.group != ''}),
    959       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
    960  call assert_equal(signs2, sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
    961 
    962  " Test for :sign unplace * group={group} file={fname}
    963  call Place_signs_for_test()
    964  sign unplace * group=g1 file=Xsign1
    965  sign unplace * group=g2 file=Xsign2
    966  call assert_equal(
    967       \ filter(copy(signs1),
    968       \     {idx, val -> val.group != 'g1'}),
    969       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
    970  call assert_equal(
    971       \ filter(copy(signs2),
    972       \     {idx, val -> val.group != 'g2'}),
    973       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
    974 
    975  " Test for :sign unplace * group=* file={fname}
    976  call Place_signs_for_test()
    977  sign unplace * group=* file=Xsign2
    978  call assert_equal(signs1, sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
    979  call assert_equal([], sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
    980 
    981  " Test for :sign unplace {id} buffer={nr}
    982  call Place_signs_for_test()
    983  exe 'sign unplace 3 buffer=' . bnum1
    984  exe 'sign unplace 6 buffer=' . bnum2
    985  call assert_equal(
    986       \ filter(copy(signs1),
    987       \     {idx, val -> val.id != 3 || val.group != ''}),
    988       \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
    989  call assert_equal(
    990       \ filter(copy(signs2),
    991       \     {idx, val -> val.id != 6 || val.group != ''}),
    992       \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
    993 
    994  " Test for :sign unplace {id} group={group} buffer={nr}
    995  call Place_signs_for_test()
    996  exe 'sign unplace 4 group=g1 buffer=' . bnum1
    997  exe 'sign unplace 5 group=g2 buffer=' . bnum2
    998  call assert_equal(
    999       \ filter(copy(signs1),
   1000       \     {idx, val -> val.id != 4 || val.group != 'g1'}),
   1001       \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
   1002  call assert_equal(
   1003       \ filter(copy(signs2),
   1004       \     {idx, val -> val.id != 5 || val.group != 'g2'}),
   1005       \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
   1006 
   1007  " Test for :sign unplace {id} group=* buffer={nr}
   1008  call Place_signs_for_test()
   1009  exe 'sign unplace 3 group=* buffer=' . bnum1
   1010  exe 'sign unplace 6 group=* buffer=' . bnum2
   1011  call assert_equal(
   1012       \ filter(copy(signs1),
   1013       \     {idx, val -> val.id != 3}),
   1014       \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
   1015  call assert_equal(
   1016       \ filter(copy(signs2),
   1017       \     {idx, val -> val.id != 6}),
   1018       \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
   1019 
   1020  " Test for :sign unplace * buffer={nr}
   1021  call Place_signs_for_test()
   1022  exe 'sign unplace * buffer=' . bnum1
   1023  call assert_equal(
   1024       \ filter(copy(signs1),
   1025       \     {idx, val -> val.group != ''}),
   1026       \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
   1027  call assert_equal(signs2, sign_getplaced(bnum2, {'group' : '*'})[0].signs)
   1028 
   1029  " Test for :sign unplace * group={group} buffer={nr}
   1030  call Place_signs_for_test()
   1031  exe 'sign unplace * group=g1 buffer=' . bnum1
   1032  exe 'sign unplace * group=g2 buffer=' . bnum2
   1033  call assert_equal(
   1034       \ filter(copy(signs1),
   1035       \     {idx, val -> val.group != 'g1'}),
   1036       \ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
   1037  call assert_equal(
   1038       \ filter(copy(signs2),
   1039       \     {idx, val -> val.group != 'g2'}),
   1040       \ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
   1041 
   1042  " Test for :sign unplace * group=* buffer={nr}
   1043  call Place_signs_for_test()
   1044  exe 'sign unplace * group=* buffer=' . bnum2
   1045  call assert_equal(signs1, sign_getplaced(bnum1, {'group' : '*'})[0].signs)
   1046  call assert_equal([], sign_getplaced(bnum2, {'group' : '*'})[0].signs)
   1047 
   1048  " Test for :sign unplace {id}
   1049  call Place_signs_for_test()
   1050  sign unplace 4
   1051  sign unplace 6
   1052  call assert_equal(
   1053       \ filter(copy(signs1),
   1054       \     {idx, val -> val.id != 4 || val.group != ''}),
   1055       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1056  call assert_equal(
   1057       \ filter(copy(signs2),
   1058       \     {idx, val -> val.id != 6 || val.group != ''}),
   1059       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1060 
   1061  " Test for :sign unplace {id} group={group}
   1062  call Place_signs_for_test()
   1063  sign unplace 4 group=g1
   1064  sign unplace 6 group=g2
   1065  call assert_equal(
   1066       \ filter(copy(signs1),
   1067       \     {idx, val -> val.id != 4 || val.group != 'g1'}),
   1068       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1069  call assert_equal(
   1070       \ filter(copy(signs2),
   1071       \     {idx, val -> val.id != 6 || val.group != 'g2'}),
   1072       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1073 
   1074  " Test for :sign unplace {id} group=*
   1075  call Place_signs_for_test()
   1076  sign unplace 3 group=*
   1077  sign unplace 5 group=*
   1078  call assert_equal(
   1079       \ filter(copy(signs1),
   1080       \     {idx, val -> val.id != 3}),
   1081       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1082  call assert_equal(
   1083       \ filter(copy(signs2),
   1084       \     {idx, val -> val.id != 5}),
   1085       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1086 
   1087  " Test for :sign unplace *
   1088  call Place_signs_for_test()
   1089  sign unplace *
   1090  call assert_equal(
   1091       \ filter(copy(signs1),
   1092       \     {idx, val -> val.group != ''}),
   1093       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1094  call assert_equal(
   1095       \ filter(copy(signs2),
   1096       \     {idx, val -> val.group != ''}),
   1097       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1098 
   1099  " Test for :sign unplace * group={group}
   1100  call Place_signs_for_test()
   1101  sign unplace * group=g1
   1102  call assert_equal(
   1103       \ filter(copy(signs1),
   1104       \     {idx, val -> val.group != 'g1'}),
   1105       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1106  call assert_equal(
   1107       \ filter(copy(signs2),
   1108       \     {idx, val -> val.group != 'g1'}),
   1109       \ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1110 
   1111  " Test for :sign unplace * group=*
   1112  call Place_signs_for_test()
   1113  sign unplace * group=*
   1114  call assert_equal([], sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1115  call assert_equal([], sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1116 
   1117  " Negative test cases
   1118  call Place_signs_for_test()
   1119  sign unplace 3 group=xy file=Xsign1
   1120  sign unplace * group=xy file=Xsign1
   1121  silent! sign unplace * group=* file=FileNotPresent
   1122  call assert_equal(signs1, sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1123  call assert_equal(signs2, sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
   1124 
   1125  " Tests for removing sign at the current cursor position
   1126 
   1127  " Test for ':sign unplace'
   1128  let signs1 = [{'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g2',
   1129       \ 'priority' : 10},
   1130       \ {'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g1',
   1131       \ 'priority' : 10},
   1132       \ {'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : '',
   1133       \ 'priority' : 10},
   1134       \ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g2',
   1135       \ 'priority' : 10},
   1136       \ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g1',
   1137       \ 'priority' : 10},
   1138       \ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : '',
   1139       \ 'priority' : 10},]
   1140  exe bufwinnr('Xsign1') . 'wincmd w'
   1141  call cursor(13, 1)
   1142 
   1143  " Should remove only one sign in the global group
   1144  call Place_signs_at_line_for_test()
   1145  sign unplace
   1146  call assert_equal(
   1147       \ filter(copy(signs1),
   1148       \     {idx, val -> val.id != 4 || val.group != ''}),
   1149       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1150  " Should remove the second sign in the global group
   1151  sign unplace
   1152  call assert_equal(
   1153       \ filter(copy(signs1),
   1154       \     {idx, val -> val.group != ''}),
   1155       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1156 
   1157  " Test for ':sign unplace group={group}'
   1158  call Place_signs_at_line_for_test()
   1159  " Should remove only one sign in group g1
   1160  sign unplace group=g1
   1161  call assert_equal(
   1162       \ filter(copy(signs1),
   1163       \     {idx, val -> val.id != 4 || val.group != 'g1'}),
   1164       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1165  sign unplace group=g2
   1166  call assert_equal(
   1167       \ filter(copy(signs1),
   1168       \     {idx, val -> val.id != 4 || val.group == ''}),
   1169       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1170 
   1171  " Test for ':sign unplace group=*'
   1172  call Place_signs_at_line_for_test()
   1173  sign unplace group=*
   1174  sign unplace group=*
   1175  sign unplace group=*
   1176  call assert_equal(
   1177       \ filter(copy(signs1),
   1178       \     {idx, val -> val.id != 4}),
   1179       \ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1180  sign unplace group=*
   1181  sign unplace group=*
   1182  sign unplace group=*
   1183  call assert_equal([], sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
   1184 
   1185  call sign_unplace('*')
   1186  call sign_undefine()
   1187  enew | only
   1188 endfunc
   1189 
   1190 " Tests for auto-generating the sign identifier.
   1191 func Test_aaa_sign_id_autogen()
   1192  enew | only
   1193  call sign_unplace('*')
   1194  call sign_undefine()
   1195 
   1196  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
   1197  call assert_equal(0, sign_define("sign1", attr))
   1198 
   1199  call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
   1200  edit Xsign
   1201 
   1202  call assert_equal(1, sign_place(0, '', 'sign1', 'Xsign',
   1203       \ {'lnum' : 10}))
   1204  call assert_equal(2, sign_place(2, '', 'sign1', 'Xsign',
   1205       \ {'lnum' : 12}))
   1206  call assert_equal(3, sign_place(0, '', 'sign1', 'Xsign',
   1207       \ {'lnum' : 14}))
   1208  call sign_unplace('', {'buffer' : 'Xsign', 'id' : 2})
   1209  call assert_equal(4, sign_place(0, '', 'sign1', 'Xsign',
   1210       \ {'lnum' : 12}))
   1211 
   1212  call assert_equal(1, sign_place(0, 'g1', 'sign1', 'Xsign',
   1213       \ {'lnum' : 11}))
   1214  " Check for the next generated sign id in this group
   1215  call assert_equal(2, sign_place(0, 'g1', 'sign1', 'Xsign',
   1216       \ {'lnum' : 12}))
   1217  call assert_equal(0, sign_unplace('g1', {'id' : 1}))
   1218  call assert_equal(10,
   1219       \ sign_getplaced('Xsign', {'id' : 1})[0].signs[0].lnum)
   1220 
   1221  call sign_unplace('*')
   1222  call sign_undefine()
   1223  enew | only
   1224 endfunc
   1225 
   1226 " Test for sign priority
   1227 func Test_sign_priority()
   1228  enew | only
   1229  call sign_unplace('*')
   1230  call sign_undefine()
   1231 
   1232  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Search'}
   1233  call sign_define("sign1", attr)
   1234  call sign_define("sign2", attr)
   1235  call sign_define("sign3", attr)
   1236  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Search', 'priority': 60}
   1237  call sign_define("sign4", attr)
   1238 
   1239  " Test for :sign list
   1240  let a = execute('sign list')
   1241  call assert_equal("\nsign sign1 text==> linehl=Search texthl=Search\n" .
   1242      \ "sign sign2 text==> linehl=Search texthl=Search\n" .
   1243      \ "sign sign3 text==> linehl=Search texthl=Search\n" .
   1244      \ "sign sign4 text==> priority=60 linehl=Search texthl=Search", a)
   1245 
   1246  " Test for sign_getdefined()
   1247  let s = sign_getdefined()
   1248  call assert_equal([
   1249      \ {'name': 'sign1', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'},
   1250      \ {'name': 'sign2', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'},
   1251      \ {'name': 'sign3', 'texthl': 'Search', 'linehl': 'Search', 'text': '=>'},
   1252      \ {'name': 'sign4', 'priority': 60, 'texthl': 'Search', 'linehl': 'Search',
   1253      \ 'text': '=>'}],
   1254      \ s)
   1255 
   1256  " Place three signs with different priority in the same line
   1257  call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
   1258  edit Xsign
   1259 
   1260  call sign_place(1, 'g1', 'sign1', 'Xsign',
   1261       \ {'lnum' : 11, 'priority' : 50})
   1262  call sign_place(2, 'g2', 'sign2', 'Xsign',
   1263       \ {'lnum' : 11, 'priority' : 100})
   1264  call sign_place(3, '', 'sign3', 'Xsign', {'lnum' : 11})
   1265  let s = sign_getplaced('Xsign', {'group' : '*'})
   1266  call assert_equal([
   1267       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 11, 'group' : 'g2',
   1268       \ 'priority' : 100},
   1269       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : 'g1',
   1270       \ 'priority' : 50},
   1271       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 11, 'group' : '',
   1272       \ 'priority' : 10}],
   1273       \ s[0].signs)
   1274 
   1275  call sign_unplace('*')
   1276 
   1277  " Three signs on different lines with changing priorities
   1278  call sign_place(1, '', 'sign1', 'Xsign',
   1279       \ {'lnum' : 11, 'priority' : 50})
   1280  call sign_place(2, '', 'sign2', 'Xsign',
   1281       \ {'lnum' : 12, 'priority' : 60})
   1282  call sign_place(3, '', 'sign3', 'Xsign',
   1283       \ {'lnum' : 13, 'priority' : 70})
   1284  call sign_place(2, '', 'sign2', 'Xsign',
   1285       \ {'lnum' : 12, 'priority' : 40})
   1286  call sign_place(3, '', 'sign3', 'Xsign',
   1287       \ {'lnum' : 13, 'priority' : 30})
   1288  call sign_place(1, '', 'sign1', 'Xsign',
   1289       \ {'lnum' : 11, 'priority' : 50})
   1290  let s = sign_getplaced('Xsign', {'group' : '*'})
   1291  call assert_equal([
   1292       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11, 'group' : '',
   1293       \ 'priority' : 50},
   1294       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 12, 'group' : '',
   1295       \ 'priority' : 40},
   1296       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 13, 'group' : '',
   1297       \ 'priority' : 30}],
   1298       \ s[0].signs)
   1299 
   1300  call sign_unplace('*')
   1301 
   1302  " Two signs on the same line with changing priorities
   1303  call sign_place(1, '', 'sign1', 'Xsign',
   1304       \ {'lnum' : 4, 'priority' : 20})
   1305  call sign_place(2, '', 'sign2', 'Xsign',
   1306       \ {'lnum' : 4, 'priority' : 30})
   1307  let s = sign_getplaced('Xsign', {'group' : '*'})
   1308  call assert_equal([
   1309       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1310       \ 'priority' : 30},
   1311       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1312       \ 'priority' : 20}],
   1313       \ s[0].signs)
   1314  " Change the priority of the last sign to highest
   1315  call sign_place(1, '', 'sign1', 'Xsign',
   1316       \ {'lnum' : 4, 'priority' : 40})
   1317  let s = sign_getplaced('Xsign', {'group' : '*'})
   1318  call assert_equal([
   1319       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1320       \ 'priority' : 40},
   1321       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1322       \ 'priority' : 30}],
   1323       \ s[0].signs)
   1324  " Change the priority of the first sign to lowest
   1325  call sign_place(1, '', 'sign1', 'Xsign',
   1326       \ {'lnum' : 4, 'priority' : 25})
   1327  let s = sign_getplaced('Xsign', {'group' : '*'})
   1328  call assert_equal([
   1329       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1330       \ 'priority' : 30},
   1331       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1332       \ 'priority' : 25}],
   1333       \ s[0].signs)
   1334  call sign_place(1, '', 'sign1', 'Xsign',
   1335       \ {'lnum' : 4, 'priority' : 45})
   1336  call sign_place(2, '', 'sign2', 'Xsign',
   1337       \ {'lnum' : 4, 'priority' : 55})
   1338  let s = sign_getplaced('Xsign', {'group' : '*'})
   1339  call assert_equal([
   1340       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1341       \ 'priority' : 55},
   1342       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1343       \ 'priority' : 45}],
   1344       \ s[0].signs)
   1345 
   1346  call sign_unplace('*')
   1347 
   1348  " Three signs on the same line with changing priorities
   1349  call sign_place(1, '', 'sign1', 'Xsign',
   1350       \ {'lnum' : 4, 'priority' : 40})
   1351  call sign_place(2, '', 'sign2', 'Xsign',
   1352       \ {'lnum' : 4, 'priority' : 30})
   1353  call sign_place(3, '', 'sign3', 'Xsign',
   1354       \ {'lnum' : 4, 'priority' : 20})
   1355  let s = sign_getplaced('Xsign', {'group' : '*'})
   1356  call assert_equal([
   1357       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1358       \ 'priority' : 40},
   1359       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1360       \ 'priority' : 30},
   1361       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1362       \ 'priority' : 20}],
   1363       \ s[0].signs)
   1364 
   1365  " Change the priority of the middle sign to the highest
   1366  call sign_place(2, '', 'sign2', 'Xsign',
   1367       \ {'lnum' : 4, 'priority' : 50})
   1368  let s = sign_getplaced('Xsign', {'group' : '*'})
   1369  call assert_equal([
   1370       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1371       \ 'priority' : 50},
   1372       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1373       \ 'priority' : 40},
   1374       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1375       \ 'priority' : 20}],
   1376       \ s[0].signs)
   1377 
   1378  " Change the priority of the middle sign to the lowest
   1379  call sign_place(1, '', 'sign1', 'Xsign',
   1380       \ {'lnum' : 4, 'priority' : 15})
   1381  let s = sign_getplaced('Xsign', {'group' : '*'})
   1382  call assert_equal([
   1383       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1384       \ 'priority' : 50},
   1385       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1386       \ 'priority' : 20},
   1387       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1388       \ 'priority' : 15}],
   1389       \ s[0].signs)
   1390 
   1391  " Change the priority of the last sign to the highest
   1392  call sign_place(1, '', 'sign1', 'Xsign',
   1393       \ {'lnum' : 4, 'priority' : 55})
   1394  let s = sign_getplaced('Xsign', {'group' : '*'})
   1395  call assert_equal([
   1396       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1397       \ 'priority' : 55},
   1398       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1399       \ 'priority' : 50},
   1400       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1401       \ 'priority' : 20}],
   1402       \ s[0].signs)
   1403 
   1404  " Change the priority of the first sign to the lowest
   1405  call sign_place(1, '', 'sign1', 'Xsign',
   1406       \ {'lnum' : 4, 'priority' : 15})
   1407  let s = sign_getplaced('Xsign', {'group' : '*'})
   1408  call assert_equal([
   1409       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1410       \ 'priority' : 50},
   1411       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1412       \ 'priority' : 20},
   1413       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1414       \ 'priority' : 15}],
   1415       \ s[0].signs)
   1416 
   1417  call sign_unplace('*')
   1418 
   1419  " Three signs on the same line with changing priorities along with other
   1420  " signs
   1421  call sign_place(1, '', 'sign1', 'Xsign',
   1422       \ {'lnum' : 2, 'priority' : 10})
   1423  call sign_place(2, '', 'sign1', 'Xsign',
   1424       \ {'lnum' : 4, 'priority' : 30})
   1425  call sign_place(3, '', 'sign2', 'Xsign',
   1426       \ {'lnum' : 4, 'priority' : 20})
   1427  call sign_place(4, '', 'sign3', 'Xsign',
   1428       \ {'lnum' : 4, 'priority' : 25})
   1429  call sign_place(5, '', 'sign2', 'Xsign',
   1430       \ {'lnum' : 6, 'priority' : 80})
   1431  let s = sign_getplaced('Xsign', {'group' : '*'})
   1432  call assert_equal([
   1433       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
   1434       \ 'priority' : 10},
   1435       \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1436       \ 'priority' : 30},
   1437       \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1438       \ 'priority' : 25},
   1439       \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1440       \ 'priority' : 20},
   1441       \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
   1442       \ 'priority' : 80}],
   1443       \ s[0].signs)
   1444 
   1445  " Change the priority of the first sign to lowest
   1446  call sign_place(2, '', 'sign1', 'Xsign',
   1447       \ {'lnum' : 4, 'priority' : 15})
   1448  let s = sign_getplaced('Xsign', {'group' : '*'})
   1449  call assert_equal([
   1450       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
   1451       \ 'priority' : 10},
   1452       \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1453       \ 'priority' : 25},
   1454       \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1455       \ 'priority' : 20},
   1456       \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1457       \ 'priority' : 15},
   1458       \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
   1459       \ 'priority' : 80}],
   1460       \ s[0].signs)
   1461 
   1462  " Change the priority of the last sign to highest
   1463  call sign_place(2, '', 'sign1', 'Xsign',
   1464       \ {'lnum' : 4, 'priority' : 30})
   1465  let s = sign_getplaced('Xsign', {'group' : '*'})
   1466  call assert_equal([
   1467       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
   1468       \ 'priority' : 10},
   1469       \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1470       \ 'priority' : 30},
   1471       \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1472       \ 'priority' : 25},
   1473       \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1474       \ 'priority' : 20},
   1475       \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
   1476       \ 'priority' : 80}],
   1477       \ s[0].signs)
   1478 
   1479  " Change the priority of the middle sign to lowest
   1480  call sign_place(4, '', 'sign3', 'Xsign',
   1481       \ {'lnum' : 4, 'priority' : 15})
   1482  let s = sign_getplaced('Xsign', {'group' : '*'})
   1483  call assert_equal([
   1484       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
   1485       \ 'priority' : 10},
   1486       \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1487       \ 'priority' : 30},
   1488       \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1489       \ 'priority' : 20},
   1490       \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1491       \ 'priority' : 15},
   1492       \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
   1493       \ 'priority' : 80}],
   1494       \ s[0].signs)
   1495 
   1496  " Change the priority of the middle sign to highest
   1497  call sign_place(3, '', 'sign2', 'Xsign',
   1498       \ {'lnum' : 4, 'priority' : 35})
   1499  let s = sign_getplaced('Xsign', {'group' : '*'})
   1500  call assert_equal([
   1501       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 2, 'group' : '',
   1502       \ 'priority' : 10},
   1503       \ {'id' : 3, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1504       \ 'priority' : 35},
   1505       \ {'id' : 2, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1506       \ 'priority' : 30},
   1507       \ {'id' : 4, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1508       \ 'priority' : 15},
   1509       \ {'id' : 5, 'name' : 'sign2', 'lnum' : 6, 'group' : '',
   1510       \ 'priority' : 80}],
   1511       \ s[0].signs)
   1512 
   1513  call sign_unplace('*')
   1514 
   1515  " Multiple signs with the same priority on the same line
   1516  call sign_place(1, '', 'sign1', 'Xsign',
   1517              \ {'lnum' : 4, 'priority' : 20})
   1518  call sign_place(2, '', 'sign2', 'Xsign',
   1519              \ {'lnum' : 4, 'priority' : 20})
   1520  call sign_place(3, '', 'sign3', 'Xsign',
   1521              \ {'lnum' : 4, 'priority' : 20})
   1522  let s = sign_getplaced('Xsign', {'group' : '*'})
   1523  let se = [
   1524              \ {'id' : 3, 'name' : 'sign3', 'lnum' : 4, 'group' : '',
   1525              \ 'priority' : 20},
   1526              \ {'id' : 2, 'name' : 'sign2', 'lnum' : 4, 'group' : '',
   1527              \ 'priority' : 20},
   1528              \ {'id' : 1, 'name' : 'sign1', 'lnum' : 4, 'group' : '',
   1529              \ 'priority' : 20}]
   1530  call assert_equal(se, s[0].signs)
   1531 
   1532  " Nvim: signs are always sorted lnum->priority->sign_id->last_modified
   1533  " Last modified does not take precedence over sign_id here.
   1534 
   1535  " Place the last sign again with the same priority
   1536  call sign_place(1, '', 'sign1', 'Xsign',
   1537              \ {'lnum' : 4, 'priority' : 20})
   1538  let s = sign_getplaced('Xsign', {'group' : '*'})
   1539  call assert_equal(se, s[0].signs)
   1540  " Place the first sign again with the same priority
   1541  call sign_place(1, '', 'sign1', 'Xsign',
   1542              \ {'lnum' : 4, 'priority' : 20})
   1543  let s = sign_getplaced('Xsign', {'group' : '*'})
   1544  call assert_equal(se, s[0].signs)
   1545  " Place the middle sign again with the same priority
   1546  call sign_place(3, '', 'sign3', 'Xsign',
   1547              \ {'lnum' : 4, 'priority' : 20})
   1548  let s = sign_getplaced('Xsign', {'group' : '*'})
   1549  call assert_equal(se, s[0].signs)
   1550 
   1551  call sign_unplace('*')
   1552 
   1553  " Place multiple signs with same id on a line with different priority
   1554  call sign_place(1, '', 'sign1', 'Xsign',
   1555       \ {'lnum' : 5, 'priority' : 20})
   1556  call sign_place(1, '', 'sign2', 'Xsign',
   1557       \ {'lnum' : 5, 'priority' : 10})
   1558  let s = sign_getplaced('Xsign', {'lnum' : 5})
   1559  call assert_equal([
   1560       \ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '',
   1561       \ 'priority' : 10}],
   1562       \ s[0].signs)
   1563  call sign_place(1, '', 'sign2', 'Xsign',
   1564       \ {'lnum' : 5, 'priority' : 5})
   1565  let s = sign_getplaced('Xsign', {'lnum' : 5})
   1566  call assert_equal([
   1567       \ {'id' : 1, 'name' : 'sign2', 'lnum' : 5, 'group' : '',
   1568       \ 'priority' : 5}],
   1569       \ s[0].signs)
   1570 
   1571  " Error case
   1572  call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign', [])", 'E1206:')
   1573  call assert_fails("call sign_place(1, 'g1', 'sign1', 'Xsign',
   1574       \ {'priority' : []})", 'E745:')
   1575  call sign_unplace('*')
   1576 
   1577  " Tests for the :sign place command with priority
   1578  sign place 5 line=10 name=sign1 priority=30 file=Xsign
   1579  sign place 5 group=g1 line=10 name=sign1 priority=20 file=Xsign
   1580  sign place 5 group=g2 line=10 name=sign1 priority=25 file=Xsign
   1581  let a = execute('sign place group=*')
   1582  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
   1583       \ "    line=10  id=5  name=sign1  priority=30\n" .
   1584       \ "    line=10  id=5  group=g2  name=sign1  priority=25\n" .
   1585       \ "    line=10  id=5  group=g1  name=sign1  priority=20", a)
   1586 
   1587  " Test for :sign place group={group}
   1588  let a = execute('sign place group=g1')
   1589  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
   1590       \ "    line=10  id=5  group=g1  name=sign1  priority=20", a)
   1591 
   1592  call sign_unplace('*')
   1593 
   1594  " Test for sign with default priority.
   1595  call sign_place(1, 'g1', 'sign4', 'Xsign', {'lnum' : 3})
   1596  sign place 2 line=5 name=sign4 group=g1 file=Xsign
   1597 
   1598  let s = sign_getplaced('Xsign', {'group' : '*'})
   1599  call assert_equal([
   1600       \ {'id' : 1, 'name' : 'sign4', 'lnum' : 3, 'group' : 'g1',
   1601       \ 'priority' : 60},
   1602       \ {'id' : 2, 'name' : 'sign4', 'lnum' : 5, 'group' : 'g1',
   1603       \ 'priority' : 60}],
   1604       \ s[0].signs)
   1605 
   1606  let a = execute('sign place group=g1')
   1607  call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
   1608       \ "    line=3  id=1  group=g1  name=sign4  priority=60\n" .
   1609       \ "    line=5  id=2  group=g1  name=sign4  priority=60", a)
   1610 
   1611  call sign_unplace('*')
   1612  call sign_undefine()
   1613  enew | only
   1614 endfunc
   1615 
   1616 " Tests for memory allocation failures in sign functions
   1617 func Test_sign_memfailures()
   1618  CheckFunction test_alloc_fail
   1619  call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
   1620  edit Xsign
   1621 
   1622  call test_alloc_fail(GetAllocId('sign_getdefined'), 0, 0)
   1623  call assert_fails('call sign_getdefined("sign1")', 'E342:')
   1624  call test_alloc_fail(GetAllocId('sign_getplaced'), 0, 0)
   1625  call assert_fails('call sign_getplaced("Xsign")', 'E342:')
   1626  call test_alloc_fail(GetAllocId('sign_define_by_name'), 0, 0)
   1627  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
   1628  call assert_fails('call sign_define("sign1", attr)', 'E342:')
   1629 
   1630  let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
   1631  call sign_define("sign1", attr)
   1632  call test_alloc_fail(GetAllocId('sign_getlist'), 0, 0)
   1633  call assert_fails('call sign_getdefined("sign1")', 'E342:')
   1634 
   1635  call sign_place(3, 'g1', 'sign1', 'Xsign', {'lnum' : 10})
   1636  call test_alloc_fail(GetAllocId('sign_getplaced_dict'), 0, 0)
   1637  call assert_fails('call sign_getplaced("Xsign")', 'E342:')
   1638  call test_alloc_fail(GetAllocId('sign_getplaced_list'), 0, 0)
   1639  call assert_fails('call sign_getplaced("Xsign")', 'E342:')
   1640 
   1641  call test_alloc_fail(GetAllocId('insert_sign'), 0, 0)
   1642  call assert_fails('call sign_place(4, "g1", "sign1", "Xsign", {"lnum" : 11})',
   1643 							\ 'E342:')
   1644 
   1645  call test_alloc_fail(GetAllocId('sign_getinfo'), 0, 0)
   1646  call assert_fails('call getbufinfo()', 'E342:')
   1647  call sign_place(4, 'g1', 'sign1', 'Xsign', {'lnum' : 11})
   1648  call test_alloc_fail(GetAllocId('sign_getinfo'), 0, 0)
   1649  call assert_fails('let binfo=getbufinfo("Xsign")', 'E342:')
   1650  call assert_equal([{'lnum': 11, 'id': 4, 'name': 'sign1',
   1651       \ 'priority': 10, 'group': 'g1'}], binfo[0].signs)
   1652 
   1653  call sign_unplace('*')
   1654  call sign_undefine()
   1655  enew | only
   1656 endfunc
   1657 
   1658 " Test for auto-adjusting the line number of a placed sign.
   1659 func Test_sign_lnum_adjust()
   1660  enew! | only!
   1661 
   1662  sign define sign1 text=#> linehl=Comment
   1663  call setline(1, ['A', 'B', 'C', 'D', 'E'])
   1664  exe 'sign place 5 line=3 name=sign1 buffer=' . bufnr('')
   1665  let l = sign_getplaced(bufnr(''))
   1666  call assert_equal(3, l[0].signs[0].lnum)
   1667 
   1668  " Add some lines before the sign and check the sign line number
   1669  call append(2, ['BA', 'BB', 'BC'])
   1670  let l = sign_getplaced(bufnr(''))
   1671  call assert_equal(6, l[0].signs[0].lnum)
   1672 
   1673  " Delete some lines before the sign and check the sign line number
   1674  call deletebufline('%', 1, 2)
   1675  let l = sign_getplaced(bufnr(''))
   1676  call assert_equal(4, l[0].signs[0].lnum)
   1677 
   1678  " Insert some lines after the sign and check the sign line number
   1679  call append(5, ['DA', 'DB'])
   1680  let l = sign_getplaced(bufnr(''))
   1681  call assert_equal(4, l[0].signs[0].lnum)
   1682 
   1683  " Delete some lines after the sign and check the sign line number
   1684  call deletebufline('', 6, 7)
   1685  let l = sign_getplaced(bufnr(''))
   1686  call assert_equal(4, l[0].signs[0].lnum)
   1687 
   1688  " Break the undo. Otherwise the undo operation below will undo all the
   1689  " changes made by this function.
   1690  let &g:undolevels=&g:undolevels
   1691 
   1692  " Nvim: deleting a line removes the signs along with it.
   1693 
   1694  " " Delete the line with the sign
   1695  " call deletebufline('', 4)
   1696  " let l = sign_getplaced(bufnr(''))
   1697  " call assert_equal(4, l[0].signs[0].lnum)
   1698 
   1699  " " Undo the delete operation
   1700  " undo
   1701  " let l = sign_getplaced(bufnr(''))
   1702  " call assert_equal(5, l[0].signs[0].lnum)
   1703 
   1704  " " Break the undo
   1705  " let &g:undolevels=&g:undolevels
   1706 
   1707  " " Delete few lines at the end of the buffer including the line with the sign
   1708  " " Sign line number should not change (as it is placed outside of the buffer)
   1709  " call deletebufline('', 3, 6)
   1710  " let l = sign_getplaced(bufnr(''))
   1711  " call assert_equal(5, l[0].signs[0].lnum)
   1712 
   1713  " " Undo the delete operation. Sign should be restored to the previous line
   1714  " undo
   1715  " let l = sign_getplaced(bufnr(''))
   1716  " call assert_equal(5, l[0].signs[0].lnum)
   1717 
   1718  " set signcolumn&
   1719 
   1720  sign unplace * group=*
   1721  sign undefine sign1
   1722  enew!
   1723 endfunc
   1724 
   1725 " Test for changing the type of a placed sign
   1726 func Test_sign_change_type()
   1727  enew! | only!
   1728 
   1729  sign define sign1 text=#> linehl=Comment
   1730  sign define sign2 text=@@ linehl=Comment
   1731 
   1732  call setline(1, ['A', 'B', 'C', 'D'])
   1733  exe 'sign place 4 line=3 name=sign1 buffer=' . bufnr('')
   1734  let l = sign_getplaced(bufnr(''))
   1735  call assert_equal('sign1', l[0].signs[0].name)
   1736  exe 'sign place 4 name=sign2 buffer=' . bufnr('')
   1737  let l = sign_getplaced(bufnr(''))
   1738  call assert_equal('sign2', l[0].signs[0].name)
   1739  call sign_place(4, '', 'sign1', '')
   1740  let l = sign_getplaced(bufnr(''))
   1741  call assert_equal('sign1', l[0].signs[0].name)
   1742 
   1743  exe 'sign place 4 group=g1 line=4 name=sign1 buffer=' . bufnr('')
   1744  let l = sign_getplaced(bufnr(''), {'group' : 'g1'})
   1745  call assert_equal('sign1', l[0].signs[0].name)
   1746  exe 'sign place 4 group=g1 name=sign2 buffer=' . bufnr('')
   1747  let l = sign_getplaced(bufnr(''), {'group' : 'g1'})
   1748  call assert_equal('sign2', l[0].signs[0].name)
   1749  call sign_place(4, 'g1', 'sign1', '')
   1750  let l = sign_getplaced(bufnr(''), {'group' : 'g1'})
   1751  call assert_equal('sign1', l[0].signs[0].name)
   1752 
   1753  sign unplace * group=*
   1754  sign undefine sign1
   1755  sign undefine sign2
   1756  enew!
   1757 endfunc
   1758 
   1759 " Test for the sign_jump() function
   1760 func Test_sign_jump_func()
   1761  enew! | only!
   1762 
   1763  sign define sign1 text=#> linehl=Comment
   1764 
   1765  edit foo
   1766  set buftype=nofile
   1767  call setline(1, ['A', 'B', 'C', 'D', 'E'])
   1768  call sign_place(5, '', 'sign1', '', {'lnum' : 2})
   1769  call sign_place(5, 'g1', 'sign1', '', {'lnum' : 3})
   1770  call sign_place(6, '', 'sign1', '', {'lnum' : 4})
   1771  call sign_place(6, 'g1', 'sign1', '', {'lnum' : 5})
   1772  split bar
   1773  set buftype=nofile
   1774  call setline(1, ['P', 'Q', 'R', 'S', 'T'])
   1775  call sign_place(5, '', 'sign1', '', {'lnum' : 2})
   1776  call sign_place(5, 'g1', 'sign1', '', {'lnum' : 3})
   1777  call sign_place(6, '', 'sign1', '', {'lnum' : 4})
   1778  call sign_place(6, 'g1', 'sign1', '', {'lnum' : 5})
   1779 
   1780  let r = sign_jump(5, '', 'foo')
   1781  call assert_equal(2, r)
   1782  call assert_equal(2, line('.'))
   1783  let r = 6->sign_jump('g1', 'foo')
   1784  call assert_equal(5, r)
   1785  call assert_equal(5, line('.'))
   1786  let r = sign_jump(5, '', 'bar')
   1787  call assert_equal(2, r)
   1788  call assert_equal(2, line('.'))
   1789 
   1790  " Error cases
   1791  call assert_fails("call sign_jump(99, '', 'bar')", 'E157:')
   1792  call assert_fails("call sign_jump(0, '', 'foo')", 'E474:')
   1793  call assert_fails("call sign_jump(5, 'g5', 'foo')", 'E157:')
   1794  call assert_fails('call sign_jump([], "", "foo")', 'E745:')
   1795  call assert_fails('call sign_jump(2, [], "foo")', 'E730:')
   1796  call assert_fails('call sign_jump(2, "", {})', 'E731:')
   1797  call assert_fails('call sign_jump(2, "", "baz")', 'E158:')
   1798 
   1799  sign unplace * group=*
   1800  sign undefine sign1
   1801  enew! | only!
   1802 endfunc
   1803 
   1804 " Test for correct cursor position after the sign column appears or disappears.
   1805 func Test_sign_cursor_position()
   1806  CheckScreendump
   1807  CheckRunVimInTerminal
   1808 
   1809  let lines =<< trim END
   1810 call setline(1, [repeat('x', 75), 'mmmm', 'yyyy'])
   1811 call cursor(2,1)
   1812 sign define s1 texthl=Search text==>
   1813 sign define s2 linehl=Pmenu
   1814 redraw
   1815 sign place 10 line=2 name=s1
   1816  END
   1817  call writefile(lines, 'XtestSigncolumn', 'D')
   1818  let buf = RunVimInTerminal('-S XtestSigncolumn', {'rows': 6})
   1819  call VerifyScreenDump(buf, 'Test_sign_cursor_1', {})
   1820 
   1821  " Change the sign text
   1822  call term_sendkeys(buf, ":sign define s1 text=-)\<CR>")
   1823  call VerifyScreenDump(buf, 'Test_sign_cursor_2', {})
   1824 
   1825  " Also place a line HL sign
   1826  call term_sendkeys(buf, ":sign place 11 line=2 name=s2\<CR>")
   1827  call VerifyScreenDump(buf, 'Test_sign_cursor_3', {})
   1828 
   1829  " update cursor position calculation
   1830  call term_sendkeys(buf, "lh")
   1831  call term_sendkeys(buf, ":sign unplace 11\<CR>")
   1832  call term_sendkeys(buf, ":sign unplace 10\<CR>")
   1833  call VerifyScreenDump(buf, 'Test_sign_cursor_4', {})
   1834 
   1835  " clean up
   1836  call StopVimInTerminal(buf)
   1837 endfunc
   1838 
   1839 " Return the 'len' characters in screen starting from (row,col)
   1840 func s:ScreenLine(row, col, len)
   1841  let s = ''
   1842  for i in range(a:len)
   1843    let s .= nr2char(screenchar(a:row, a:col + i))
   1844  endfor
   1845  return s
   1846 endfunc
   1847 
   1848 " Test for 'signcolumn' set to 'number'.
   1849 func Test_sign_numcol()
   1850  new
   1851  call append(0, "01234")
   1852  " With 'signcolumn' set to 'number', make sure sign is displayed in the
   1853  " number column and line number is not displayed.
   1854  set numberwidth=2
   1855  set number
   1856  set signcolumn=number
   1857  sign define sign1 text==>
   1858  sign define sign2 text=   1859  sign place 10 line=1 name=sign1
   1860  redraw!
   1861  call assert_equal("=> 01234", s:ScreenLine(1, 1, 8))
   1862 
   1863  " With 'signcolumn' set to 'number', when there is no sign, make sure line
   1864  " number is displayed in the number column
   1865  sign unplace 10
   1866  redraw!
   1867  call assert_equal("1 01234", s:ScreenLine(1, 1, 7))
   1868 
   1869  " Disable number column. Check whether sign is displayed in the sign column
   1870  set numberwidth=4
   1871  set nonumber
   1872  sign place 10 line=1 name=sign1
   1873  redraw!
   1874  call assert_equal("=>01234", s:ScreenLine(1, 1, 7))
   1875 
   1876  " Enable number column. Check whether sign is displayed in the number column
   1877  set number
   1878  redraw!
   1879  call assert_equal(" => 01234", s:ScreenLine(1, 1, 9))
   1880 
   1881  " Disable sign column. Make sure line number is displayed
   1882  set signcolumn=no
   1883  redraw!
   1884  call assert_equal("  1 01234", s:ScreenLine(1, 1, 9))
   1885 
   1886  " Enable auto sign column. Make sure both sign and line number are displayed
   1887  set signcolumn=auto
   1888  redraw!
   1889  call assert_equal("=>  1 01234", s:ScreenLine(1, 1, 11))
   1890 
   1891  " Test displaying signs in the number column with width 1
   1892  call sign_unplace('*')
   1893  call append(1, "abcde")
   1894  call append(2, "01234")
   1895  " Enable number column with width 1
   1896  set number numberwidth=1 signcolumn=auto
   1897  redraw!
   1898  call assert_equal("3 01234", s:ScreenLine(3, 1, 7))
   1899  " Place a sign and make sure number column width remains the same
   1900  sign place 20 line=2 name=sign1
   1901  redraw!
   1902  call assert_equal("=>2 abcde", s:ScreenLine(2, 1, 9))
   1903  call assert_equal("  3 01234", s:ScreenLine(3, 1, 9))
   1904  " Set 'signcolumn' to 'number', make sure the number column width increases
   1905  set signcolumn=number
   1906  redraw!
   1907  call assert_equal("=> abcde", s:ScreenLine(2, 1, 8))
   1908  call assert_equal(" 3 01234", s:ScreenLine(3, 1, 8))
   1909  " Set 'signcolumn' to 'auto', make sure the number column width is 1.
   1910  set signcolumn=auto
   1911  redraw!
   1912  call assert_equal("=>2 abcde", s:ScreenLine(2, 1, 9))
   1913  call assert_equal("  3 01234", s:ScreenLine(3, 1, 9))
   1914  " Set 'signcolumn' to 'number', make sure the number column width is 2.
   1915  set signcolumn=number
   1916  redraw!
   1917  call assert_equal("=> abcde", s:ScreenLine(2, 1, 8))
   1918  call assert_equal(" 3 01234", s:ScreenLine(3, 1, 8))
   1919  " Disable 'number' column
   1920  set nonumber
   1921  redraw!
   1922  call assert_equal("=>abcde", s:ScreenLine(2, 1, 7))
   1923  call assert_equal("  01234", s:ScreenLine(3, 1, 7))
   1924  " Enable 'number' column
   1925  set number
   1926  redraw!
   1927  call assert_equal("=> abcde", s:ScreenLine(2, 1, 8))
   1928  call assert_equal(" 3 01234", s:ScreenLine(3, 1, 8))
   1929  " Remove the sign and make sure the width of the number column is 1.
   1930  call sign_unplace('', {'id' : 20})
   1931  redraw!
   1932  call assert_equal("3 01234", s:ScreenLine(3, 1, 7))
   1933  " When the first sign is placed with 'signcolumn' set to number, verify that
   1934  " the number column width increases
   1935  sign place 30 line=1 name=sign1
   1936  redraw!
   1937  call assert_equal("=> 01234", s:ScreenLine(1, 1, 8))
   1938  call assert_equal(" 2 abcde", s:ScreenLine(2, 1, 8))
   1939  " Add sign with multi-byte text
   1940  set numberwidth=4
   1941  sign place 40 line=2 name=sign2
   1942  redraw!
   1943  call assert_equal(" => 01234", s:ScreenLine(1, 1, 9))
   1944  call assert_equal(" V abcde", s:ScreenLine(2, 1, 9))
   1945 
   1946  sign unplace * group=*
   1947  sign undefine sign1
   1948  set signcolumn&
   1949  set number&
   1950  enew!  | close
   1951 endfunc
   1952 
   1953 " Test for managing multiple signs using the sign functions
   1954 func Test_sign_funcs_multi()
   1955  call writefile(repeat(["Sun is shining"], 30), "Xsign", 'D')
   1956  edit Xsign
   1957  let bnum = bufnr('')
   1958 
   1959  " Define multiple signs at once
   1960  call assert_equal([0, 0, 0, 0], sign_define([
   1961       \ {'name' : 'sign1', 'text' : '=>', 'linehl' : 'Search',
   1962       \ 'texthl' : 'Search'},
   1963       \ {'name' : 'sign2', 'text' : '=>', 'linehl' : 'Search',
   1964       \ 'texthl' : 'Search'},
   1965       \ {'name' : 'sign3', 'text' : '=>', 'linehl' : 'Search',
   1966       \ 'texthl' : 'Search'},
   1967       \ {'name' : 'sign4', 'text' : '=>', 'linehl' : 'Search',
   1968       \ 'texthl' : 'Search'}]))
   1969 
   1970  " Negative cases for sign_define()
   1971  call assert_equal([], sign_define([]))
   1972  call assert_equal([-1], sign_define([{}]))
   1973  call assert_fails('call sign_define([6])', 'E715:')
   1974  call assert_fails('call sign_define(["abc"])', 'E715:')
   1975  call assert_fails('call sign_define([[]])', 'E715:')
   1976 
   1977  " Place multiple signs at once with specific sign identifier
   1978  let l = sign_placelist([{'id' : 1, 'group' : 'g1', 'name' : 'sign1',
   1979       \ 'buffer' : 'Xsign', 'lnum' : 11, 'priority' : 50},
   1980       \ {'id' : 2, 'group' : 'g2', 'name' : 'sign2',
   1981       \ 'buffer' : 'Xsign', 'lnum' : 11, 'priority' : 100},
   1982       \ {'id' : 3, 'group' : '', 'name' : 'sign3',
   1983       \ 'buffer' : 'Xsign', 'lnum' : 11}])
   1984  call assert_equal([1, 2, 3], l)
   1985  let s = sign_getplaced('Xsign', {'group' : '*'})
   1986  call assert_equal([
   1987       \ {'id' : 2, 'name' : 'sign2', 'lnum' : 11,
   1988       \ 'group' : 'g2', 'priority' : 100},
   1989       \ {'id' : 1, 'name' : 'sign1', 'lnum' : 11,
   1990       \ 'group' : 'g1', 'priority' : 50},
   1991       \ {'id' : 3, 'name' : 'sign3', 'lnum' : 11,
   1992       \ 'group' : '', 'priority' : 10}], s[0].signs)
   1993 
   1994  call sign_unplace('*')
   1995 
   1996  " Place multiple signs at once with auto-generated sign identifier
   1997  " Nvim: next sign id is not reset and is always incremented
   1998  call assert_equal([2, 3, 4], sign_placelist([
   1999       \ {'group' : 'g1', 'name' : 'sign1',
   2000       \ 'buffer' : 'Xsign', 'lnum' : 11},
   2001       \ {'group' : 'g2', 'name' : 'sign2',
   2002       \ 'buffer' : 'Xsign', 'lnum' : 11},
   2003       \ {'group' : '', 'name' : 'sign3',
   2004       \ 'buffer' : 'Xsign', 'lnum' : 11}]))
   2005  let s = sign_getplaced('Xsign', {'group' : '*'})
   2006  call assert_equal([
   2007       \ {'id' : 4, 'name' : 'sign3', 'lnum' : 11,
   2008       \ 'group' : '', 'priority' : 10},
   2009       \ {'id' : 3, 'name' : 'sign2', 'lnum' : 11,
   2010       \ 'group' : 'g2', 'priority' : 10},
   2011       \ {'id' : 2, 'name' : 'sign1', 'lnum' : 11,
   2012       \ 'group' : 'g1', 'priority' : 10}], s[0].signs)
   2013 
   2014  " Change an existing sign without specifying the group
   2015  call assert_equal([4], [{'id' : 4, 'name' : 'sign1', 'buffer' : 'Xsign'}]->sign_placelist())
   2016  let s = sign_getplaced('Xsign', {'id' : 4, 'group' : ''})
   2017  call assert_equal([{'id' : 4, 'name' : 'sign1', 'lnum' : 11,
   2018       \ 'group' : '', 'priority' : 10}], s[0].signs)
   2019 
   2020  " Place a sign using '.' as the line number
   2021  call cursor(23, 1)
   2022  call assert_equal([7], sign_placelist([
   2023       \ {'id' : 7, 'name' : 'sign1', 'buffer' : '%', 'lnum' : '.'}]))
   2024  let s = sign_getplaced('%', {'lnum' : '.'})
   2025  call assert_equal([{'id' : 7, 'name' : 'sign1', 'lnum' : 23,
   2026       \ 'group' : '', 'priority' : 10}], s[0].signs)
   2027 
   2028  " Place sign without a sign name
   2029  call assert_equal([-1], sign_placelist([{'id' : 10, 'buffer' : 'Xsign',
   2030       \ 'lnum' : 12, 'group' : ''}]))
   2031 
   2032  " Place sign without a buffer
   2033  call assert_equal([-1], sign_placelist([{'id' : 10, 'name' : 'sign1',
   2034       \ 'lnum' : 12, 'group' : ''}]))
   2035 
   2036  " Invalid arguments
   2037  call assert_equal([], sign_placelist([]))
   2038  call assert_fails('call sign_placelist({})', "E714:")
   2039  call assert_fails('call sign_placelist([[]])', "E715:")
   2040  call assert_fails('call sign_placelist(["abc"])', "E715:")
   2041  call assert_fails('call sign_placelist([100])', "E715:")
   2042 
   2043  " Unplace multiple signs
   2044  call assert_equal([0, 0, 0], sign_unplacelist([{'id' : 4},
   2045       \ {'id' : 2, 'group' : 'g1'}, {'id' : 3, 'group' : 'g2'}]))
   2046 
   2047  " Invalid arguments
   2048  call assert_equal([], []->sign_unplacelist())
   2049  call assert_fails('call sign_unplacelist({})', "E714:")
   2050  call assert_fails('call sign_unplacelist([[]])', "E715:")
   2051  call assert_fails('call sign_unplacelist(["abc"])', "E715:")
   2052  call assert_fails('call sign_unplacelist([100])', "E715:")
   2053  call assert_fails("call sign_unplacelist([{'id' : -1}])", 'E474')
   2054 
   2055  call assert_equal([0, 0, 0, 0],
   2056       \ sign_undefine(['sign1', 'sign2', 'sign3', 'sign4']))
   2057  call assert_equal([], sign_getdefined())
   2058 
   2059  " Invalid arguments
   2060  call assert_equal([], sign_undefine([]))
   2061  call assert_fails('call sign_undefine([[]])', 'E730:')
   2062  call assert_fails('call sign_undefine([{}])', 'E731:')
   2063  call assert_fails('call sign_undefine(["1abc2"])', 'E155:')
   2064 
   2065  call sign_unplace('*')
   2066  call sign_undefine()
   2067  enew!
   2068 endfunc
   2069 
   2070 func Test_sign_null_list()
   2071  eval v:_null_list->sign_define()
   2072  eval v:_null_list->sign_placelist()
   2073  eval v:_null_list->sign_undefine()
   2074  eval v:_null_list->sign_unplacelist()
   2075 endfunc
   2076 
   2077 func Test_sign_number_without_signtext()
   2078  CheckScreendump
   2079  CheckRunVimInTerminal
   2080 
   2081  let lines =<< trim END
   2082      set number signcolumn=number
   2083      call setline(1, ['a', 'b', 'c'])
   2084      sign define SignA text=>> texthl=Search numhl=Error
   2085      sign define SignB numhl=Error
   2086      sign place 1 line=1 name=SignA buffer=1
   2087      sign place 2 line=2 name=SignB  buffer=1
   2088  END
   2089  call writefile(lines, 'XtestSigncolumnNumber', 'D')
   2090  let buf = RunVimInTerminal('-S XtestSigncolumnNumber', {'rows': 5})
   2091  call VerifyScreenDump(buf, 'Test_sign_number_without_signtext', {})
   2092 
   2093  call StopVimInTerminal(buf)
   2094 endfunc
   2095 
   2096 " vim: shiftwidth=2 sts=2 expandtab