diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index 12b7fb63c1..166c3a48b2 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -251,13 +251,24 @@ See |sign_unplace()| for the equivalent Vim script function. all the files it appears in. :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=* - Remove all placed signs in all the groups. + Remove placed signs in all the groups from all the files. :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* @@ -271,20 +282,26 @@ See |sign_getplaced()| for the equivalent Vim script function. :sign place group={group} 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} List signs placed in buffer {nr}. :sign place group={group} 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=* - List placed signs in all sign groups in all files. +:sign place List placed signs in the global group in all files. :sign place group={group} List placed signs with sign group {group} in all files. +:sign place group=* + List placed signs in all sign groups in all files. + JUMPING TO A SIGN *:sign-jump* *E157* @@ -295,9 +312,15 @@ JUMPING TO A SIGN *:sign-jump* *E157* If the file isn't displayed in window and the current file can 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* Same, but use buffer {nr}. This fails if buffer {nr} does not 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: diff --git a/src/buffer.c b/src/buffer.c index c35477f662..07b89e3207 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -6077,10 +6077,10 @@ insert_sign_by_lnum_prio( int sign_in_group(signlist_T *sign, char_u *group) { - return ((group != NULL && STRCMP(group, "*") == 0) || - (group == NULL && sign->group == NULL) || - (group != NULL && sign->group != NULL && - STRCMP(group, sign->group->sg_name) == 0)); + return ((group != NULL && STRCMP(group, "*") == 0) + || (group == NULL && sign->group == NULL) + || (group != NULL && sign->group != NULL + && STRCMP(group, sign->group->sg_name) == 0)); } /* @@ -6207,6 +6207,7 @@ buf_getsigntype( linenr_T buf_delsign( buf_T *buf, // buffer sign is stored in + linenr_T atlnum, // sign at this line, 0 - at any line int id, // sign id char_u *group) // sign group { @@ -6220,7 +6221,9 @@ buf_delsign( for (sign = buf->b_signlist; sign != NULL; sign = next) { next = sign->next; - if ((id == 0 || sign->id == id) && sign_in_group(sign, group)) + if ((id == 0 || sign->id == id) && + (atlnum == 0 || sign->lnum == atlnum) && + sign_in_group(sign, group)) { *lastp = next; @@ -6230,8 +6233,14 @@ buf_delsign( if (sign->group != NULL) sign_group_unref(sign->group->sg_name); vim_free(sign); + update_debug_sign(buf, lnum); // Check whether only one sign needs to be deleted - if (group == NULL || (*group != '*' && id != 0)) + // 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 @@ -6272,17 +6281,18 @@ buf_findsign( /* * 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( 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 FOR_ALL_SIGNS_IN_BUF(buf, sign) - if (sign->lnum == lnum) + if (sign->lnum == lnum && sign_in_group(sign, groupname)) return sign; return NULL; @@ -6312,11 +6322,12 @@ buf_getsign_with_id( int buf_findsign_id( 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 - sign = buf_getsign_at_line(buf, lnum); + sign = buf_getsign_at_line(buf, lnum, groupname); if (sign != NULL) return sign->id; @@ -6401,16 +6412,16 @@ buf_delete_signs(buf_T *buf, char_u *group) } /* - * Delete all signs in all buffers. + * Delete all the signs in the specified group in all the buffers. */ void -buf_delete_all_signs(void) +buf_delete_all_signs(char_u *groupname) { buf_T *buf; /* buffer we are checking for signs */ FOR_ALL_BUFFERS(buf) if (buf->b_signlist != NULL) - buf_delete_signs(buf, (char_u *)"*"); + buf_delete_signs(buf, groupname); } /* diff --git a/src/evalfunc.c b/src/evalfunc.c index d94bf8d297..13e6d6e269 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -11600,12 +11600,12 @@ f_sign_unplace(typval_T *argvars, typval_T *rettv) { // Delete the sign in all the buffers 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; } else { - if (sign_unplace(sign_id, group, buf) == OK) + if (sign_unplace(sign_id, group, buf, 0) == OK) rettv->vval.v_number = 0; } vim_free(group); diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 6a79451061..b5ad3b3564 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -7895,7 +7895,7 @@ sign_place( * Unplace the specified sign */ 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) { @@ -7908,15 +7908,29 @@ sign_unplace(int sign_id, char_u *sign_group, buf_T *buf) linenr_T lnum; // 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) return FAIL; - update_debug_sign(buf, lnum); } 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 */ @@ -8047,14 +8061,8 @@ ex_sign(exarg_T *eap) sign_list_placed(NULL, NULL); } else if (idx == SIGNCMD_UNPLACE) - { /* ":sign unplace": remove placed sign at cursor */ - id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum); - if (id > 0) - sign_unplace(id, NULL, curwin->w_buffer); - else - EMSG(_("E159: Missing sign number")); - } + sign_unplace_at_cursor(NULL); else EMSG(_(e_argreq)); return; @@ -8063,7 +8071,7 @@ ex_sign(exarg_T *eap) if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL) { /* ":sign unplace *": remove all placed signs */ - buf_delete_all_signs(); + buf_delete_all_signs(NULL); return; } @@ -8084,7 +8092,7 @@ ex_sign(exarg_T *eap) { /* ":sign unplace {id}": remove placed sign by number */ FOR_ALL_BUFFERS(buf) - sign_unplace(id, NULL, buf); + sign_unplace(id, NULL, buf, 0); return; } } @@ -8183,7 +8191,8 @@ ex_sign(exarg_T *eap) } 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) EMSG(_(e_invarg)); else if ((lnum = buf_findsign(buf, id, group)) > 0) @@ -8225,7 +8234,7 @@ ex_sign(exarg_T *eap) { if (buf != NULL) // ":sign unplace * file={fname}" - sign_unplace(0, group, buf); + sign_unplace(0, group, buf, 0); else // ":sign unplace * group=*": remove all placed signs FOR_ALL_BUFFERS(buf) @@ -8238,14 +8247,26 @@ ex_sign(exarg_T *eap) // ":sign unplace {id} file={fname}" // ":sign unplace {id} group={group} file={fname}" // ":sign unplace {id} group=* file={fname}" - sign_unplace(id, group, buf); + sign_unplace(id, group, buf, 0); 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); + { + if (id == -1) + { + // ":sign unplace group={group}": + // ":sign unplace group=*": + // remove sign in the current line in specified group + sign_unplace_at_cursor(group); + } + 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); + } + } } } /* idx == SIGNCMD_PLACE */ @@ -8581,13 +8602,14 @@ get_sign_name(expand_T *xp UNUSED, int idx) { char *place_arg[] = { - "line=", "name=", "file=", "buffer=", NULL + "line=", "name=", "group=", "priority=", "file=", + "buffer=", NULL }; return (char_u *)place_arg[idx]; } case EXP_UNPLACE: { - char *unplace_arg[] = { "file=", "buffer=", NULL }; + char *unplace_arg[] = { "group=", "file=", "buffer=", NULL }; return (char_u *)unplace_arg[idx]; } case EXP_SIGN_NAMES: diff --git a/src/netbeans.c b/src/netbeans.c index 9b6b5223dd..c8084dfe64 100644 --- a/src/netbeans.c +++ b/src/netbeans.c @@ -1251,12 +1251,12 @@ nb_do_cmd( /* delete signs from the lines being deleted */ for (i = del_from_lnum; i <= del_to_lnum; i++) { - int id = buf_findsign_id(buf->bufp, (linenr_T)i); + int id = buf_findsign_id(buf->bufp, (linenr_T)i, NULL); if (id > 0) { nbdebug((" Deleting sign %d on line %d\n", id, i)); - buf_delsign(buf->bufp, id, NULL); + buf_delsign(buf->bufp, 0, id, NULL); } else { diff --git a/src/proto/buffer.pro b/src/proto/buffer.pro index 756638417a..ecc830188c 100644 --- a/src/proto/buffer.pro +++ b/src/proto/buffer.pro @@ -69,23 +69,21 @@ char_u *buf_spname(buf_T *buf); void switch_to_win_for_buf(buf_T *buf, win_T **save_curwinp, tabpage_T **save_curtabp, bufref_T *save_curbuf); void restore_win_for_buf(win_T *save_curwin, tabpage_T *save_curtab, bufref_T *save_curbuf); int find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp); -void buf_addsign(buf_T *buf, int id, char_u *group, int prio, linenr_T lnum, int typenr); -linenr_T buf_change_sign_type(buf_T *buf, int markId, char_u *group, int typenr); -int buf_getsigntype(buf_T *buf, linenr_T lnum, int type); -linenr_T buf_delsign(buf_T *buf, int id, char_u *group); -int buf_findsign(buf_T *buf, int id, char_u *group); -#ifdef FEAT_SIGNS void init_signs(void); int sign_group_get_next_signid(buf_T *buf, char_u *groupname); int sign_in_group(signlist_T *sign, char_u *group); dict_T *sign_get_info(signlist_T *sign); +void buf_addsign(buf_T *buf, int id, char_u *groupname, int prio, linenr_T lnum, int typenr); +linenr_T buf_change_sign_type(buf_T *buf, int markId, char_u *group, int typenr); +int buf_getsigntype(buf_T *buf, linenr_T lnum, int type); +linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char_u *group); +int buf_findsign(buf_T *buf, int id, char_u *group); signlist_T *buf_getsign_with_id(buf_T *buf, int id, char_u *group); -#endif -int buf_findsign_id(buf_T *buf, linenr_T lnum); +int buf_findsign_id(buf_T *buf, linenr_T lnum, char_u *groupname); int buf_findsigntype_id(buf_T *buf, linenr_T lnum, int typenr); int buf_signcount(buf_T *buf, linenr_T lnum); void buf_delete_signs(buf_T *buf, char_u *group); -void buf_delete_all_signs(void); +void buf_delete_all_signs(char_u *groupname); void sign_list_placed(buf_T *rbuf, char_u *sign_group); void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after); void set_buflisted(int on); diff --git a/src/proto/ex_cmds.pro b/src/proto/ex_cmds.pro index 00d0217e6a..0b9d687c94 100644 --- a/src/proto/ex_cmds.pro +++ b/src/proto/ex_cmds.pro @@ -54,24 +54,23 @@ void fix_help_buffer(void); void ex_exusage(exarg_T *eap); void ex_viusage(exarg_T *eap); void ex_helptags(exarg_T *eap); +int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl); +int sign_undefine_by_name(char_u *name); +int sign_place(int *sign_id, char_u *sign_group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio); +int sign_unplace(int sign_id, char_u *sign_group, buf_T *buf, linenr_T atlnum); void ex_sign(exarg_T *eap); +void sign_getlist(char_u *name, list_T *retlist); +void sign_get_placed(buf_T *buf, linenr_T lnum, int sign_id, char_u *sign_group, list_T *retlist); void sign_gui_started(void); int sign_get_attr(int typenr, int line); char_u *sign_get_text(int typenr); void *sign_get_image(int typenr); char_u *sign_typenr2name(int typenr); void free_signs(void); -void free_signs(void); char_u *get_sign_name(expand_T *xp, int idx); void set_context_in_sign_cmd(expand_T *xp, char_u *arg); void ex_smile(exarg_T *eap); void ex_drop(exarg_T *eap); char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags); void ex_oldfiles(exarg_T *eap); -int sign_define_by_name(char_u *name, char_u *icon, char_u *linehl, char_u *text, char_u *texthl); -int sign_undefine_by_name(char_u *name); -void sign_getlist(char_u *name, list_T *retlist); -int sign_place(int *sign_id, char_u *group, char_u *sign_name, buf_T *buf, linenr_T lnum, int prio); -int sign_unplace(int id, char_u *group, buf_T *buf); -void sign_get_placed(buf_T *buf, linenr_T lnum, int id, char_u *group, list_T *retlist); /* vim: set ft=c : */ diff --git a/src/testdir/test_signs.vim b/src/testdir/test_signs.vim index 57e2831495..5917fc6831 100644 --- a/src/testdir/test_signs.vim +++ b/src/testdir/test_signs.vim @@ -28,8 +28,8 @@ func Test_sign() let a=execute('sign list Sign1') call assert_equal("\nsign Sign1 text=x ", a) - " Split the window to the bottom to verify sign jump will stay in the current window - " if the buffer is displayed there. + " Split the window to the bottom to verify sign jump will stay in the + " current window if the buffer is displayed there. let bn = bufnr('%') let wn = winnr() 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 feedkeys(":sign place 1 \\\"\", '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=\\\"\", 'tx') call assert_equal('"sign place 1 name=Sign1 Sign2', @:) call feedkeys(":sign unplace 1 \\\"\", 'tx') - call assert_equal('"sign unplace 1 buffer= file=', @:) + call assert_equal('"sign unplace 1 buffer= file= group=', @:) call feedkeys(":sign list \\\"\", 'tx') call assert_equal('"sign list Sign1 Sign2', @:) call feedkeys(":sign jump 1 \\\"\", 'tx') - call assert_equal('"sign jump 1 buffer= file=', @:) + call assert_equal('"sign jump 1 buffer= file= group=', @:) sign undefine Sign1 sign undefine Sign2 @@ -449,7 +450,6 @@ func Test_sign_group() edit Xsign let bnum = bufnr('%') - let fname = fnamemodify('Xsign', ':p') " Error case call assert_fails("call sign_place(5, [], 'sign1', 'Xsign', @@ -466,6 +466,10 @@ func Test_sign_group() let s = sign_getplaced('Xsign') call assert_equal(1, len(s[0].signs)) 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'}) call assert_equal('g2', s[0].signs[0].group) 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=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') 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') 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') 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=g1 name=sign1 priority=10\n" . \ " line=10 id=5 name=sign1 priority=10\n", a) + " Error case: non-existing group let a = execute('sign place group=xyz file=Xsign') call assert_equal("\n--- Signs ---\nSigns for Xsign:\n", a) call sign_unplace('*') - - " Test for :sign place group={group} buffer={nr} let bnum = bufnr('Xsign') 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=g2 line=12 name=sign1 buffer=' . bnum + " :sign place buffer={fname} 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) + " :sign place group={group} buffer={fname} 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) + " :sign place group=* buffer={fname} let a = execute('sign place group=* buffer=' . bnum) call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . \ " line=10 id=5 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) + " Error case: non-existing group let a = execute('sign place group=xyz buffer=' . bnum) 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=*') call assert_equal("\n--- Signs ---\nSigns for Xsign:\n" . \ " line=10 id=5 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) - " Test for :sign unplace - sign unplace 5 group=g2 file=Xsign - call assert_equal([], sign_getplaced(bnum, {'group' : 'g2'})[0].signs) - - exe 'sign unplace 5 group=g1 buffer=' . bnum - call assert_equal([], sign_getplaced(bnum, {'group' : 'g1'})[0].signs) - - 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) + " Test for ':sign jump' command with groups + sign jump 5 group=g1 file=Xsign + call assert_equal(11, line('.')) + call assert_equal('Xsign', bufname('')) + sign jump 5 group=g2 file=Xsign + call assert_equal(12, line('.')) " Error cases call assert_fails("sign place 3 group= name=sign1 buffer=" . bnum, 'E474:') @@ -714,6 +667,357 @@ func Test_sign_group() enew | only 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 func Test_sign_id_autogen() enew | only @@ -762,7 +1066,6 @@ func Test_sign_priority() " Place three signs with different priority in the same line call writefile(repeat(["Sun is shining"], 30), "Xsign") edit Xsign - let fname = fnamemodify('Xsign', ':p') call sign_place(1, 'g1', 'sign1', 'Xsign', \ {'lnum' : 11, 'priority' : 50}) diff --git a/src/version.c b/src/version.c index 5852ce79e6..1772cfdc80 100644 --- a/src/version.c +++ b/src/version.c @@ -799,6 +799,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 658, /**/ 657, /**/