vim-patch:8.1.0658: deleting signs and completion for :sign is insufficient

Problem:    Deleting signs and completion for :sign is insufficient.
Solution:   Add deleting signs in a specified or any group from the current
            cursor location.  Add group and priority to sign command
            completion. Add tests for different sign unplace commands. Update
            help text.  Add tests for sign jump with group. Update help for
            sign jump. (Yegappan Lakshmanan, closes vim/vim#3731)
7d83bf4f2b
This commit is contained in:
Andrej Zieger
2019-05-16 21:27:41 +02:00
parent 3ee55edd2e
commit 09c236ba5c
5 changed files with 514 additions and 154 deletions

View File

@@ -244,13 +244,24 @@ See |sign_unplace()| for the equivalent Vim script function.
all the files it appears in. all the files it appears in.
:sign unplace * :sign unplace *
Remove all placed signs in the global group. Remove placed signs in the global group from all the files.
:sign unplace * group={group}
Remove placed signs in group {group} from all the files.
:sign unplace * group=* :sign unplace * group=*
Remove all placed signs in all the groups. Remove placed signs in all the groups from all the files.
:sign unplace :sign unplace
Remove the placed sign at the cursor position. Remove a placed sign at the cursor position. If multiple signs
are placed in the line, then only one is removed.
:sign unplace group={group}
Remove a placed sign in group {group} at the cursor
position.
:sign unplace group=*
Remove a placed sign in any group at the cursor position.
LISTING PLACED SIGNS *:sign-place-list* LISTING PLACED SIGNS *:sign-place-list*
@@ -264,17 +275,25 @@ See |sign_getplaced()| for the equivalent Vim script function.
:sign place group={group} file={fname} :sign place group={group} file={fname}
List signs in group {group} placed in file {fname}. List signs in group {group} placed in file {fname}.
:sign place group=* file={fname}
List signs in all the groups placed in file {fname}.
:sign place buffer={nr} :sign place buffer={nr}
List signs placed in buffer {nr}. List signs placed in buffer {nr}.
:sign place group={group} buffer={nr} :sign place group={group} buffer={nr}
List signs in group {group} placed in buffer {nr}. List signs in group {group} placed in buffer {nr}.
:sign place List placed signs in all files. :sign place group=* buffer={nr}
List signs in all the groups placed in buffer {nr}.
:sign place group={group} :sign place group={group}
List placed signs in all sign groups in all the files. List placed signs in all sign groups in all the files.
:sign place group=*
List placed signs in all sign groups in all files.
JUMPING TO A SIGN *:sign-jump* *E157* JUMPING TO A SIGN *:sign-jump* *E157*
@@ -285,9 +304,15 @@ JUMPING TO A SIGN *:sign-jump* *E157*
If the file isn't displayed in window and the current file can If the file isn't displayed in window and the current file can
not be |abandon|ed this fails. not be |abandon|ed this fails.
:sign jump {id} group={group} file={fname}
Same but jump to the sign in group {group}
:sign jump {id} buffer={nr} *E934* :sign jump {id} buffer={nr} *E934*
Same, but use buffer {nr}. This fails if buffer {nr} does not Same, but use buffer {nr}. This fails if buffer {nr} does not
have a name. have a name.
:sign jump {id} group={group} buffer={nr}
Same but jump to the sign in group {group}
vim:tw=78:ts=8:noet:ft=help:norl: vim:tw=78:ts=8:noet:ft=help:norl:

View File

@@ -5548,10 +5548,10 @@ static void insert_sign_by_lnum_prio(
*/ */
int sign_in_group(signlist_T *sign, char_u *group) int sign_in_group(signlist_T *sign, char_u *group)
{ {
return ((group != NULL && STRCMP(group, "*") == 0) || return ((group != NULL && STRCMP(group, "*") == 0)
(group == NULL && sign->group == NULL) || || (group == NULL && sign->group == NULL)
(group != NULL && sign->group != NULL && || (group != NULL && sign->group != NULL
STRCMP(group, sign->group->sg_name) == 0)); && STRCMP(group, sign->group->sg_name) == 0));
} }
/* /*
@@ -5704,45 +5704,55 @@ int buf_getsigntype(buf_T *buf, linenr_T lnum, SignType type,
*/ */
linenr_T buf_delsign( linenr_T buf_delsign(
buf_T *buf, // buffer sign is stored in buf_T *buf, // buffer sign is stored in
linenr_T atlnum, // sign at this line, 0 - at any line
int id, // sign id int id, // sign id
char_u *group// sign group char_u *group// sign group
) )
{ {
signlist_T **lastp; // pointer to pointer to current sign signlist_T **lastp; // pointer to pointer to current sign
signlist_T *sign; // a sign in a b_signlist signlist_T *sign; // a sign in a b_signlist
signlist_T *next; // the next sign in a b_signlist signlist_T *next; // the next sign in a b_signlist
linenr_T lnum; // line number whose sign was deleted linenr_T lnum; // line number whose sign was deleted
buf->b_signcols_max = -1; buf->b_signcols_max = -1;
lastp = &buf->b_signlist; lastp = &buf->b_signlist;
lnum = 0; lnum = 0;
for (sign = buf->b_signlist; sign != NULL; sign = next) { for (sign = buf->b_signlist; sign != NULL; sign = next) {
next = sign->next; next = sign->next;
if ((id == 0 || sign->id == id) && sign_in_group(sign, group)) { if ((id == 0 || sign->id == id) &&
*lastp = next; (atlnum == 0 || sign->lnum == atlnum) &&
if (next != NULL) { sign_in_group(sign, group)) {
next->prev = sign->prev; *lastp = next;
} if (next != NULL) {
lnum = sign->lnum; next->prev = sign->prev;
if (sign->group != NULL) }
sign_group_unref(sign->group->sg_name); lnum = sign->lnum;
xfree(sign); if (sign->group != NULL)
// Check whether only one sign needs to be deleted sign_group_unref(sign->group->sg_name);
if (group == NULL || (*group != '*' && id != 0)) xfree(sign);
break; redraw_buf_line_later(buf, lnum);
} else { // Check whether only one sign needs to be deleted
lastp = &sign->next; // If deleting a sign with a specific identifer in a particular
} // group or deleting any sign at a particular line number, delete
// only one sign.
if (group == NULL
|| (*group != '*' && id != 0)
|| (*group == '*' && atlnum != 0)) {
break;
}
} else {
lastp = &sign->next;
} }
}
/* When deleted the last sign needs to redraw the windows to remove the /* When deleted the last sign needs to redraw the windows to remove the
* sign column. */ * sign column. */
if (buf->b_signlist == NULL) { if (buf->b_signlist == NULL) {
redraw_buf_later(buf, NOT_VALID); redraw_buf_later(buf, NOT_VALID);
changed_cline_bef_curs(); changed_cline_bef_curs();
} }
return lnum; return lnum;
} }
@@ -5770,17 +5780,18 @@ int buf_findsign(
/* /*
* Return the sign at line 'lnum' in buffer 'buf'. Returns NULL if a sign is * Return the sign at line 'lnum' in buffer 'buf'. Returns NULL if a sign is
* not found at the line. * not found at the line. If 'groupname' is NULL, searches in the global group.
*/ */
static signlist_T * buf_getsign_at_line( static signlist_T * buf_getsign_at_line(
buf_T *buf, // buffer whose sign we are searching for buf_T *buf, // buffer whose sign we are searching for
linenr_T lnum // line number of sign linenr_T lnum, // line number of sign
char_u *groupname // sign group name
) )
{ {
signlist_T *sign; // a sign in the signlist signlist_T *sign; // a sign in the signlist
FOR_ALL_SIGNS_IN_BUF(buf, sign) { FOR_ALL_SIGNS_IN_BUF(buf, sign) {
if (sign->lnum == lnum) { if (sign->lnum == lnum && sign_in_group(sign, groupname)) {
return sign; return sign;
} }
} }
@@ -5813,12 +5824,13 @@ signlist_T *buf_getsign_with_id(
*/ */
int buf_findsign_id( int buf_findsign_id(
buf_T *buf, // buffer whose sign we are searching for buf_T *buf, // buffer whose sign we are searching for
linenr_T lnum // line number of sign linenr_T lnum, // line number of sign
char_u *groupname // sign group name
) )
{ {
signlist_T *sign; // a sign in the signlist signlist_T *sign; // a sign in the signlist
sign = buf_getsign_at_line(buf, lnum); sign = buf_getsign_at_line(buf, lnum, groupname);
if (sign != NULL) { if (sign != NULL) {
return sign->id; return sign->id;
} }
@@ -5865,11 +5877,11 @@ void buf_delete_signs(buf_T *buf, char_u *group)
/* /*
* Delete all signs in all buffers. * Delete all signs in all buffers.
*/ */
void buf_delete_all_signs(void) void buf_delete_all_signs(char_u *groupname)
{ {
FOR_ALL_BUFFERS(buf) { FOR_ALL_BUFFERS(buf) {
if (buf->b_signlist != NULL) { if (buf->b_signlist != NULL) {
buf_delete_signs(buf, (char_u *)"*"); buf_delete_signs(buf, groupname);
} }
} }
} }

View File

@@ -15739,12 +15739,12 @@ f_sign_unplace(typval_T *argvars, typval_T *rettv)
{ {
// Delete the sign in all the buffers // Delete the sign in all the buffers
FOR_ALL_BUFFERS(buf) FOR_ALL_BUFFERS(buf)
if (sign_unplace(sign_id, group, buf) == OK) if (sign_unplace(sign_id, group, buf, 0) == OK)
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
} }
else else
{ {
if (sign_unplace(sign_id, group, buf) == OK) if (sign_unplace(sign_id, group, buf, 0) == OK)
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
} }
xfree(group); xfree(group);

View File

@@ -5828,7 +5828,7 @@ int sign_place(
* Unplace the specified sign * Unplace the specified sign
*/ */
int int
sign_unplace(int sign_id, char_u *sign_group, buf_T *buf) sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum)
{ {
if (sign_id == 0) if (sign_id == 0)
{ {
@@ -5839,15 +5839,31 @@ sign_unplace(int sign_id, char_u *sign_group, buf_T *buf)
linenr_T lnum; linenr_T lnum;
// Delete only the specified signs // Delete only the specified signs
lnum = buf_delsign(buf, sign_id, sign_group); lnum = buf_delsign(buf, atlnum, sign_id, sign_group);
if (lnum == 0) { if (lnum == 0) {
return FAIL; return FAIL;
update_debug_sign(buf, lnum);
} }
redraw_buf_line_later(buf, lnum); redraw_buf_line_later(buf, lnum);
} }
return OK; return OK;
} }
/*
* Unplace the sign at the current cursor line.
*/
static void sign_unplace_at_cursor(char_u *groupname)
{
int id = -1;
id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum, groupname);
if (id > 0) {
sign_unplace(id, groupname, curwin->w_buffer, curwin->w_cursor.lnum);
} else {
EMSG(_("E159: Missing sign number"));
}
}
/* /*
* ":sign" command * ":sign" command
@@ -5962,12 +5978,7 @@ void ex_sign(exarg_T *eap)
sign_list_placed(NULL, NULL); sign_list_placed(NULL, NULL);
} else if (idx == SIGNCMD_UNPLACE) { } else if (idx == SIGNCMD_UNPLACE) {
// ":sign unplace": remove placed sign at cursor // ":sign unplace": remove placed sign at cursor
id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum); sign_unplace_at_cursor(NULL);
if (id > 0) {
sign_unplace(id, NULL, curwin->w_buffer);
} else {
EMSG(_("E159: Missing sign number"));
}
} else { } else {
EMSG(_(e_argreq)); EMSG(_(e_argreq));
} }
@@ -5976,7 +5987,7 @@ void ex_sign(exarg_T *eap)
if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL) { if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL) {
// ":sign unplace *": remove all placed signs // ":sign unplace *": remove all placed signs
buf_delete_all_signs(); buf_delete_all_signs(NULL);
return; return;
} }
@@ -5992,7 +6003,7 @@ void ex_sign(exarg_T *eap)
if (idx == SIGNCMD_UNPLACE && *arg == NUL) { if (idx == SIGNCMD_UNPLACE && *arg == NUL) {
// ":sign unplace {id}": remove placed sign by number // ":sign unplace {id}": remove placed sign by number
FOR_ALL_BUFFERS(buf) { FOR_ALL_BUFFERS(buf) {
sign_unplace(id, NULL, buf); sign_unplace(id, NULL, buf, 0);
} }
return; return;
} }
@@ -6075,6 +6086,7 @@ void ex_sign(exarg_T *eap)
} }
} else if (idx == SIGNCMD_JUMP) { } else if (idx == SIGNCMD_JUMP) {
// ":sign jump {id} file={fname}" // ":sign jump {id} file={fname}"
// ":sign jump {id} group={group} file={fname}"
if (lnum >= 0 || sign_name != NULL || buf == NULL){ if (lnum >= 0 || sign_name != NULL || buf == NULL){
EMSG(_(e_invarg)); EMSG(_(e_invarg));
} else if ((lnum = buf_findsign(buf, id, group)) > 0) { } else if ((lnum = buf_findsign(buf, id, group)) > 0) {
@@ -6108,7 +6120,7 @@ void ex_sign(exarg_T *eap)
} else if (id == -2) { } else if (id == -2) {
if (buf != NULL) { if (buf != NULL) {
// ":sign unplace * file={fname}" // ":sign unplace * file={fname}"
sign_unplace(0, group, buf); sign_unplace(0, group, buf, 0);
} else { } else {
// ":sign unplace * group=*": remove all placed signs // ":sign unplace * group=*": remove all placed signs
FOR_ALL_BUFFERS(buf) { FOR_ALL_BUFFERS(buf) {
@@ -6122,14 +6134,21 @@ void ex_sign(exarg_T *eap)
// ":sign unplace {id} file={fname}" // ":sign unplace {id} file={fname}"
// ":sign unplace {id} group={group} file={fname}" // ":sign unplace {id} group={group} file={fname}"
// ":sign unplace {id} group=* file={fname}" // ":sign unplace {id} group=* file={fname}"
sign_unplace(id, group, buf); sign_unplace(id, group, buf, 0);
} else { } else {
// ":sign unplace {id} group={group}": if (id == -1) {
// ":sign unplace {id} group=*": // ":sign unplace group={group}":
// remove all placed signs in this group. // ":sign unplace group=*":
FOR_ALL_BUFFERS(buf) { // remove sign in the current line in specified group
if (buf->b_signlist != NULL) { sign_unplace_at_cursor(group);
sign_unplace(id, group, buf); } else {
// ":sign unplace {id} group={group}":
// ":sign unplace {id} group=*":
// remove all placed signs in this group.
FOR_ALL_BUFFERS(buf) {
if (buf->b_signlist != NULL) {
sign_unplace(id, group, buf, 0);
}
} }
} }
} }
@@ -6426,11 +6445,12 @@ char_u * get_sign_name(expand_T *xp, int idx)
return (char_u *)define_arg[idx]; return (char_u *)define_arg[idx];
} }
case EXP_PLACE: { case EXP_PLACE: {
char *place_arg[] = { "line=", "name=", "file=", "buffer=", NULL }; char *place_arg[] = { "line=", "name=", "group=", "priority=", "file=",
"buffer=", NULL };
return (char_u *)place_arg[idx]; return (char_u *)place_arg[idx];
} }
case EXP_UNPLACE: { case EXP_UNPLACE: {
char *unplace_arg[] = { "file=", "buffer=", NULL }; char *unplace_arg[] = { "group=", "file=", "buffer=", NULL };
return (char_u *)unplace_arg[idx]; return (char_u *)unplace_arg[idx];
} }
case EXP_SIGN_NAMES: { case EXP_SIGN_NAMES: {

View File

@@ -28,8 +28,8 @@ func Test_sign()
let a=execute('sign list Sign1') let a=execute('sign list Sign1')
call assert_equal("\nsign Sign1 text=x ", a) call assert_equal("\nsign Sign1 text=x ", a)
" Split the window to the bottom to verify sign jump will stay in the current window " Split the window to the bottom to verify sign jump will stay in the
" if the buffer is displayed there. " current window if the buffer is displayed there.
let bn = bufnr('%') let bn = bufnr('%')
let wn = winnr() let wn = winnr()
exe 'sign place 41 line=3 name=Sign1 buffer=' . bn exe 'sign place 41 line=3 name=Sign1 buffer=' . bn
@@ -211,19 +211,20 @@ func Test_sign_completion()
call assert_equal('"sign undefine Sign1 Sign2', @:) call assert_equal('"sign undefine Sign1 Sign2', @:)
call feedkeys(":sign place 1 \<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":sign place 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 buffer= file= line= name=', @:) call assert_equal('"sign place 1 buffer= file= group= line= name= priority=',
\ @:)
call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":sign place 1 name=\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign place 1 name=Sign1 Sign2', @:) call assert_equal('"sign place 1 name=Sign1 Sign2', @:)
call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":sign unplace 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign unplace 1 buffer= file=', @:) call assert_equal('"sign unplace 1 buffer= file= group=', @:)
call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":sign list \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign list Sign1 Sign2', @:) call assert_equal('"sign list Sign1 Sign2', @:)
call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx') call feedkeys(":sign jump 1 \<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"sign jump 1 buffer= file=', @:) call assert_equal('"sign jump 1 buffer= file= group=', @:)
sign undefine Sign1 sign undefine Sign1
sign undefine Sign2 sign undefine Sign2
@@ -449,7 +450,6 @@ func Test_sign_group()
edit Xsign edit Xsign
let bnum = bufnr('%') let bnum = bufnr('%')
let fname = fnamemodify('Xsign', ':p')
" Error case " Error case
call assert_fails("call sign_place(5, [], 'sign1', 'Xsign', call assert_fails("call sign_place(5, [], 'sign1', 'Xsign',
@@ -466,6 +466,10 @@ func Test_sign_group()
let s = sign_getplaced('Xsign') let s = sign_getplaced('Xsign')
call assert_equal(1, len(s[0].signs)) call assert_equal(1, len(s[0].signs))
call assert_equal(s[0].signs[0].group, '') call assert_equal(s[0].signs[0].group, '')
let s = sign_getplaced(bnum, {'group' : ''})
call assert_equal([{'id' : 5, 'group' : '', 'name' : 'sign1', 'lnum' : 10,
\ 'priority' : 10}], s[0].signs)
call assert_equal(1, len(s[0].signs))
let s = sign_getplaced(bnum, {'group' : 'g2'}) let s = sign_getplaced(bnum, {'group' : 'g2'})
call assert_equal('g2', s[0].signs[0].group) call assert_equal('g2', s[0].signs[0].group)
let s = sign_getplaced(bnum, {'group' : 'g3'}) let s = sign_getplaced(bnum, {'group' : 'g3'})
@@ -584,126 +588,75 @@ func Test_sign_group()
sign place 5 group=g1 line=10 name=sign1 file=Xsign sign place 5 group=g1 line=10 name=sign1 file=Xsign
sign place 5 group=g2 line=10 name=sign1 file=Xsign sign place 5 group=g2 line=10 name=sign1 file=Xsign
" Test for :sign place group={group} file={fname} " Tests for the ':sign place' command
" :sign place file={fname}
let a = execute('sign place file=Xsign') let a = execute('sign place file=Xsign')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=10 id=5 name=sign1 priority=10\n", a) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=10 id=5 name=sign1 priority=10\n", a)
" :sign place group={group} file={fname}
let a = execute('sign place group=g2 file=Xsign') let a = execute('sign place group=g2 file=Xsign')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=10 id=5 group=g2 name=sign1 priority=10\n", a) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=10 id=5 group=g2 name=sign1 priority=10\n", a)
" :sign place group=* file={fname}
let a = execute('sign place group=* file=Xsign') let a = execute('sign place group=* file=Xsign')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 group=g2 name=sign1 priority=10\n" . \ " line=10 id=5 group=g2 name=sign1 priority=10\n" .
\ " line=10 id=5 group=g1 name=sign1 priority=10\n" . \ " line=10 id=5 group=g1 name=sign1 priority=10\n" .
\ " line=10 id=5 name=sign1 priority=10\n", a) \ " line=10 id=5 name=sign1 priority=10\n", a)
" Error case: non-existing group
let a = execute('sign place group=xyz file=Xsign') let a = execute('sign place group=xyz file=Xsign')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a)
call sign_unplace('*') call sign_unplace('*')
" Test for :sign place group={group} buffer={nr}
let bnum = bufnr('Xsign') let bnum = bufnr('Xsign')
exe 'sign place 5 line=10 name=sign1 buffer=' . bnum exe 'sign place 5 line=10 name=sign1 buffer=' . bnum
exe 'sign place 5 group=g1 line=11 name=sign1 buffer=' . bnum exe 'sign place 5 group=g1 line=11 name=sign1 buffer=' . bnum
exe 'sign place 5 group=g2 line=12 name=sign1 buffer=' . bnum exe 'sign place 5 group=g2 line=12 name=sign1 buffer=' . bnum
" :sign place buffer={fname}
let a = execute('sign place buffer=' . bnum) let a = execute('sign place buffer=' . bnum)
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=10 id=5 name=sign1 priority=10\n", a) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=10 id=5 name=sign1 priority=10\n", a)
" :sign place group={group} buffer={fname}
let a = execute('sign place group=g2 buffer=' . bnum) let a = execute('sign place group=g2 buffer=' . bnum)
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=12 id=5 group=g2 name=sign1 priority=10\n", a) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n line=12 id=5 group=g2 name=sign1 priority=10\n", a)
" :sign place group=* buffer={fname}
let a = execute('sign place group=* buffer=' . bnum) let a = execute('sign place group=* buffer=' . bnum)
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 name=sign1 priority=10\n" . \ " line=10 id=5 name=sign1 priority=10\n" .
\ " line=11 id=5 group=g1 name=sign1 priority=10\n" . \ " line=11 id=5 group=g1 name=sign1 priority=10\n" .
\ " line=12 id=5 group=g2 name=sign1 priority=10\n", a) \ " line=12 id=5 group=g2 name=sign1 priority=10\n", a)
" Error case: non-existing group
let a = execute('sign place group=xyz buffer=' . bnum) let a = execute('sign place group=xyz buffer=' . bnum)
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a)
" :sign place
let a = execute('sign place')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 name=sign1 priority=10\n", a)
" :sign place group={group}
let a = execute('sign place group=g1')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=11 id=5 group=g1 name=sign1 priority=10\n", a)
" :sign place group=*
let a = execute('sign place group=*') let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 name=sign1 priority=10\n" . \ " line=10 id=5 name=sign1 priority=10\n" .
\ " line=11 id=5 group=g1 name=sign1 priority=10\n" . \ " line=11 id=5 group=g1 name=sign1 priority=10\n" .
\ " line=12 id=5 group=g2 name=sign1 priority=10\n", a) \ " line=12 id=5 group=g2 name=sign1 priority=10\n", a)
" Test for :sign unplace " Test for ':sign jump' command with groups
sign unplace 5 group=g2 file=Xsign sign jump 5 group=g1 file=Xsign
call assert_equal([], sign_getplaced(bnum, {'group' : 'g2'})[0].signs) call assert_equal(11, line('.'))
call assert_equal('Xsign', bufname(''))
exe 'sign unplace 5 group=g1 buffer=' . bnum sign jump 5 group=g2 file=Xsign
call assert_equal([], sign_getplaced(bnum, {'group' : 'g1'})[0].signs) call assert_equal(12, line('.'))
sign unplace 5 group=xy file=Xsign
call assert_equal(1, len(sign_getplaced(bnum, {'group' : '*'})[0].signs))
" Test for removing all the signs. Place the signs again for this test
sign place 5 group=g1 line=11 name=sign1 file=Xsign
sign place 5 group=g2 line=12 name=sign1 file=Xsign
sign place 6 line=20 name=sign1 file=Xsign
sign place 6 group=g1 line=21 name=sign1 file=Xsign
sign place 6 group=g2 line=22 name=sign1 file=Xsign
sign unplace 5 group=* file=Xsign
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=20 id=6 name=sign1 priority=10\n" .
\ " line=21 id=6 group=g1 name=sign1 priority=10\n" .
\ " line=22 id=6 group=g2 name=sign1 priority=10\n", a)
" Remove all the signs from the global group
sign unplace * file=Xsign
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=21 id=6 group=g1 name=sign1 priority=10\n" .
\ " line=22 id=6 group=g2 name=sign1 priority=10\n", a)
" Remove all the signs from a particular group
sign place 5 line=10 name=sign1 file=Xsign
sign place 5 group=g1 line=11 name=sign1 file=Xsign
sign place 5 group=g2 line=12 name=sign1 file=Xsign
sign unplace * group=g1 file=Xsign
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=10 id=5 name=sign1 priority=10\n" .
\ " line=12 id=5 group=g2 name=sign1 priority=10\n" .
\ " line=22 id=6 group=g2 name=sign1 priority=10\n", a)
" Remove all the signs from all the groups in a file
sign place 5 group=g1 line=11 name=sign1 file=Xsign
sign place 6 line=20 name=sign1 file=Xsign
sign place 6 group=g1 line=21 name=sign1 file=Xsign
sign unplace * group=* file=Xsign
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\n", a)
" Remove a particular sign id in a group from all the files
sign place 5 group=g1 line=11 name=sign1 file=Xsign
sign unplace 5 group=g1
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\n", a)
" Remove a particular sign id in all the groups from all the files
sign place 5 line=10 name=sign1 file=Xsign
sign place 5 group=g1 line=11 name=sign1 file=Xsign
sign place 5 group=g2 line=12 name=sign1 file=Xsign
sign place 6 line=20 name=sign1 file=Xsign
sign place 6 group=g1 line=21 name=sign1 file=Xsign
sign place 6 group=g2 line=22 name=sign1 file=Xsign
sign unplace 5 group=*
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" .
\ " line=20 id=6 name=sign1 priority=10\n" .
\ " line=21 id=6 group=g1 name=sign1 priority=10\n" .
\ " line=22 id=6 group=g2 name=sign1 priority=10\n", a)
" Remove all the signs from all the groups in all the files
sign place 5 line=10 name=sign1 file=Xsign
sign place 5 group=g1 line=11 name=sign1 file=Xsign
sign unplace * group=*
let a = execute('sign place group=*')
call assert_equal("\n--- Signs ---\n", a)
" Error cases " Error cases
call assert_fails("sign place 3 group= name=sign1 buffer=" . bnum, 'E474:') call assert_fails("sign place 3 group= name=sign1 buffer=" . bnum, 'E474:')
@@ -714,6 +667,357 @@ func Test_sign_group()
enew | only enew | only
endfunc endfunc
" Place signs used for ":sign unplace" command test
func Place_signs_for_test()
call sign_unplace('*')
sign place 3 line=10 name=sign1 file=Xsign1
sign place 3 group=g1 line=11 name=sign1 file=Xsign1
sign place 3 group=g2 line=12 name=sign1 file=Xsign1
sign place 4 line=15 name=sign1 file=Xsign1
sign place 4 group=g1 line=16 name=sign1 file=Xsign1
sign place 4 group=g2 line=17 name=sign1 file=Xsign1
sign place 5 line=20 name=sign1 file=Xsign2
sign place 5 group=g1 line=21 name=sign1 file=Xsign2
sign place 5 group=g2 line=22 name=sign1 file=Xsign2
sign place 6 line=25 name=sign1 file=Xsign2
sign place 6 group=g1 line=26 name=sign1 file=Xsign2
sign place 6 group=g2 line=27 name=sign1 file=Xsign2
endfunc
" Place multiple signs in a single line for test
func Place_signs_at_line_for_test()
call sign_unplace('*')
sign place 3 line=13 name=sign1 file=Xsign1
sign place 3 group=g1 line=13 name=sign1 file=Xsign1
sign place 3 group=g2 line=13 name=sign1 file=Xsign1
sign place 4 line=13 name=sign1 file=Xsign1
sign place 4 group=g1 line=13 name=sign1 file=Xsign1
sign place 4 group=g2 line=13 name=sign1 file=Xsign1
endfunc
" Tests for the ':sign unplace' command
func Test_sign_unplace()
enew | only
" Remove all the signs
call sign_unplace('*')
call sign_undefine()
" Create two files and define signs
call writefile(repeat(["Sun is shining"], 30), "Xsign1")
call writefile(repeat(["It is beautiful"], 30), "Xsign2")
let attr = {'text' : '=>', 'linehl' : 'Search', 'texthl' : 'Error'}
call sign_define("sign1", attr)
edit Xsign1
let bnum1 = bufnr('%')
split Xsign2
let bnum2 = bufnr('%')
let signs1 = [{'id' : 3, 'name' : 'sign1', 'lnum' : 10, 'group' : '',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign1', 'lnum' : 11, 'group' : 'g1',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign1', 'lnum' : 12, 'group' : 'g2',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign1', 'lnum' : 15, 'group' : '',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign1', 'lnum' : 16, 'group' : 'g1',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign1', 'lnum' : 17, 'group' : 'g2',
\ 'priority' : 10},]
let signs2 = [{'id' : 5, 'name' : 'sign1', 'lnum' : 20, 'group' : '',
\ 'priority' : 10},
\ {'id' : 5, 'name' : 'sign1', 'lnum' : 21, 'group' : 'g1',
\ 'priority' : 10},
\ {'id' : 5, 'name' : 'sign1', 'lnum' : 22, 'group' : 'g2',
\ 'priority' : 10},
\ {'id' : 6, 'name' : 'sign1', 'lnum' : 25, 'group' : '',
\ 'priority' : 10},
\ {'id' : 6, 'name' : 'sign1', 'lnum' : 26, 'group' : 'g1',
\ 'priority' : 10},
\ {'id' : 6, 'name' : 'sign1', 'lnum' : 27, 'group' : 'g2',
\ 'priority' : 10},]
" Test for :sign unplace {id} file={fname}
call Place_signs_for_test()
sign unplace 3 file=Xsign1
sign unplace 6 file=Xsign2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 3 || val.group != ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 6 || val.group != ''}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace {id} group={group} file={fname}
call Place_signs_for_test()
sign unplace 4 group=g1 file=Xsign1
sign unplace 5 group=g2 file=Xsign2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group != 'g1'}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 5 || val.group != 'g2'}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace {id} group=* file={fname}
call Place_signs_for_test()
sign unplace 3 group=* file=Xsign1
sign unplace 6 group=* file=Xsign2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 3}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 6}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace * file={fname}
call Place_signs_for_test()
sign unplace * file=Xsign1
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(signs2, sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace * group={group} file={fname}
call Place_signs_for_test()
sign unplace * group=g1 file=Xsign1
sign unplace * group=g2 file=Xsign2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != 'g1'}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.group != 'g2'}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace * group=* file={fname}
call Place_signs_for_test()
sign unplace * group=* file=Xsign2
call assert_equal(signs1, sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal([], sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace {id} buffer={nr}
call Place_signs_for_test()
exe 'sign unplace 3 buffer=' . bnum1
exe 'sign unplace 6 buffer=' . bnum2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 3 || val.group != ''}),
\ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 6 || val.group != ''}),
\ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
" Test for :sign unplace {id} group={group} buffer={nr}
call Place_signs_for_test()
exe 'sign unplace 4 group=g1 buffer=' . bnum1
exe 'sign unplace 5 group=g2 buffer=' . bnum2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group != 'g1'}),
\ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 5 || val.group != 'g2'}),
\ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
" Test for :sign unplace {id} group=* buffer={nr}
call Place_signs_for_test()
exe 'sign unplace 3 group=* buffer=' . bnum1
exe 'sign unplace 6 group=* buffer=' . bnum2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 3}),
\ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 6}),
\ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
" Test for :sign unplace * buffer={nr}
call Place_signs_for_test()
exe 'sign unplace * buffer=' . bnum1
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != ''}),
\ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
call assert_equal(signs2, sign_getplaced(bnum2, {'group' : '*'})[0].signs)
" Test for :sign unplace * group={group} buffer={nr}
call Place_signs_for_test()
exe 'sign unplace * group=g1 buffer=' . bnum1
exe 'sign unplace * group=g2 buffer=' . bnum2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != 'g1'}),
\ sign_getplaced(bnum1, {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.group != 'g2'}),
\ sign_getplaced(bnum2, {'group' : '*'})[0].signs)
" Test for :sign unplace * group=* buffer={nr}
call Place_signs_for_test()
exe 'sign unplace * group=* buffer=' . bnum2
call assert_equal(signs1, sign_getplaced(bnum1, {'group' : '*'})[0].signs)
call assert_equal([], sign_getplaced(bnum2, {'group' : '*'})[0].signs)
" Test for :sign unplace {id}
call Place_signs_for_test()
sign unplace 4
sign unplace 6
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group != ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 6 || val.group != ''}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace {id} group={group}
call Place_signs_for_test()
sign unplace 4 group=g1
sign unplace 6 group=g2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group != 'g1'}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 6 || val.group != 'g2'}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace {id} group=*
call Place_signs_for_test()
sign unplace 3 group=*
sign unplace 5 group=*
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 3}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.id != 5}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace *
call Place_signs_for_test()
sign unplace *
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.group != ''}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace * group={group}
call Place_signs_for_test()
sign unplace * group=g1
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != 'g1'}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(
\ filter(copy(signs2),
\ {idx, val -> val.group != 'g1'}),
\ sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Test for :sign unplace * group=*
call Place_signs_for_test()
sign unplace * group=*
call assert_equal([], sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal([], sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Negative test cases
call Place_signs_for_test()
sign unplace 3 group=xy file=Xsign1
sign unplace * group=xy file=Xsign1
silent! sign unplace * group=* file=FileNotPresent
call assert_equal(signs1, sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call assert_equal(signs2, sign_getplaced('Xsign2', {'group' : '*'})[0].signs)
" Tests for removing sign at the current cursor position
" Test for ':sign unplace'
let signs1 = [{'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g2',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g1',
\ 'priority' : 10},
\ {'id' : 4, 'name' : 'sign1', 'lnum' : 13, 'group' : '',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g2',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : 'g1',
\ 'priority' : 10},
\ {'id' : 3, 'name' : 'sign1', 'lnum' : 13, 'group' : '',
\ 'priority' : 10},]
exe bufwinnr('Xsign1') . 'wincmd w'
call cursor(13, 1)
" Should remove only one sign in the global group
call Place_signs_at_line_for_test()
sign unplace
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group != ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
" Should remove the second sign in the global group
sign unplace
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.group != ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
" Test for ':sign unplace group={group}'
call Place_signs_at_line_for_test()
" Should remove only one sign in group g1
sign unplace group=g1
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group != 'g1'}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
sign unplace group=g2
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4 || val.group == ''}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
" Test for ':sign unplace group=*'
call Place_signs_at_line_for_test()
sign unplace group=*
sign unplace group=*
sign unplace group=*
call assert_equal(
\ filter(copy(signs1),
\ {idx, val -> val.id != 4}),
\ sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
sign unplace group=*
sign unplace group=*
sign unplace group=*
call assert_equal([], sign_getplaced('Xsign1', {'group' : '*'})[0].signs)
call sign_unplace('*')
call sign_undefine()
enew | only
call delete("Xsign1")
call delete("Xsign2")
endfunc
" Tests for auto-generating the sign identifier " Tests for auto-generating the sign identifier
func Test_sign_id_autogen() func Test_sign_id_autogen()
enew | only enew | only
@@ -762,7 +1066,6 @@ func Test_sign_priority()
" Place three signs with different priority in the same line " Place three signs with different priority in the same line
call writefile(repeat(["Sun is shining"], 30), "Xsign") call writefile(repeat(["Sun is shining"], 30), "Xsign")
edit Xsign edit Xsign
let fname = fnamemodify('Xsign', ':p')
call sign_place(1, 'g1', 'sign1', 'Xsign', call sign_place(1, 'g1', 'sign1', 'Xsign',
\ {'lnum' : 11, 'priority' : 50}) \ {'lnum' : 11, 'priority' : 50})