diff options
-rw-r--r-- | runtime/doc/eval.txt | 219 | ||||
-rw-r--r-- | runtime/doc/sign.txt | 99 | ||||
-rw-r--r-- | runtime/doc/usr_41.txt | 8 | ||||
-rw-r--r-- | src/alloc.h | 8 | ||||
-rw-r--r-- | src/buffer.c | 316 | ||||
-rw-r--r-- | src/evalfunc.c | 342 | ||||
-rw-r--r-- | src/ex_cmds.c | 668 | ||||
-rw-r--r-- | src/globals.h | 4 | ||||
-rw-r--r-- | src/list.c | 14 | ||||
-rw-r--r-- | src/misc2.c | 13 | ||||
-rw-r--r-- | src/netbeans.c | 4 | ||||
-rw-r--r-- | src/proto/buffer.pro | 17 | ||||
-rw-r--r-- | src/proto/ex_cmds.pro | 7 | ||||
-rw-r--r-- | src/proto/list.pro | 1 | ||||
-rw-r--r-- | src/proto/misc2.pro | 1 | ||||
-rw-r--r-- | src/structs.h | 5 | ||||
-rw-r--r-- | src/testdir/test_signs.vim | 626 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/workshop.c | 2 |
19 files changed, 2071 insertions, 285 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index afc4fe134b..f76af3848a 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2408,6 +2408,15 @@ shellescape({string} [, {special}]) String escape {string} for use as shell command argument shiftwidth([{col}]) Number effective value of 'shiftwidth' +sign_define({name} [, {dict}]) Number define or update a sign +sign_getdefined([{name}]) List get a list of defined signs +sign_getplaced([{expr} [, {dict}]]) + List get a list of placed signs +sign_place({id}, {group}, {name}, {expr} [, {dict}]) + Number place a sign +sign_undefine([{name}]) Number undefine a sign +sign_unplace({group} [, {dict}]) + Number unplace a sign simplify({filename}) String simplify filename as much as possible sin({expr}) Float sine of {expr} sinh({expr}) Float hyperbolic sine of {expr} @@ -7858,7 +7867,217 @@ shiftwidth([{col}]) *shiftwidth()* 'vartabstop' feature. If the 'vartabstop' setting is enabled and no {col} argument is given, column 1 will be assumed. +sign_define({name} [, {dict}]) *sign_define()* + Define a new sign named {name} or modify the attributes of an + existing sign. This is similar to the |:sign-define| command. + Prefix {name} with a unique text to avoid name collisions. + There is no {group} like with placing signs. + + The {name} can be a String or a Number. The optional {dict} + argument specifies the sign attributes. The following values + are supported: + icon full path to the bitmap file for the sign. + linehl highlight group used for the whole line the + sign is placed in. + text text that is displayed when there is no icon + or the GUI is not being used. + texthl highlight group used for the text item + For an existing sign, the attributes are updated. + + Returns 0 on success and -1 on failure. + + Examples: > + call sign_define("mySign", {"text" : "=>", "texthl" : + \ "Error", "linehl" : "Search"}) +< +sign_getdefined([{name}]) *sign_getdefined()* + Get a list of defined signs and their attributes. + This is similar to the |:sign-list| command. + + If the {name} is not supplied, then a list of all the defined + signs is returned. Otherwise the attribute of the specified + sign is returned. + + Each list item in the returned value is a dictionary with the + following entries: + icon full path to the bitmap file of the sign + linehl highlight group used for the whole line the + sign is placed in. + name name of the sign + text text that is displayed when there is no icon + or the GUI is not being used. + texthl highlight group used for the text item + + Returns an empty List if there are no signs and when {name} is + not found. + + Examples: > + " Get a list of all the defined signs + echo sign_getdefined() + + " Get the attribute of the sign named mySign + echo sign_getdefined("mySign") +< +sign_getplaced([{expr} [, {dict}]]) *sign_getplaced()* + Return a list of signs placed in a buffer or all the buffers. + This is similar to the |:sign-place-list| command. + + If the optional buffer name {expr} is specified, then only the + list of signs placed in that buffer is returned. For the use + of {expr}, see |bufname()|. The optional {dict} can contain + the following entries: + group select only signs in this group + id select sign with this identifier + lnum select signs placed in this line. For the use + of {lnum}, see |line()|. + If {group} is '*', then signs in all the groups including the + global group are returned. If {group} is not supplied, then + only signs in the global group are returned. If no arguments + are supplied, then signs in the global group placed in all the + buffers are returned. + + Each list item in the returned value is a dictionary with the + following entries: + bufnr number of the buffer with the sign + signs list of signs placed in {bufnr}. Each list + item is a dictionary with the below listed + entries + + The dictionary for each sign contains the following entries: + group sign group. Set to '' for the global group. + id identifier of the sign + lnum line number where the sign is placed + name name of the defined sign + priority sign priority + + Returns an empty list on failure. + + Examples: > + " Get a List of signs placed in eval.c in the + " global group + echo sign_getplaced("eval.c") + + " Get a List of signs in group 'g1' placed in eval.c + echo sign_getplaced("eval.c", {'group' : 'g1'}) + + " Get a List of signs placed at line 10 in eval.c + echo sign_getplaced("eval.c", {'lnum' : 10}) + + " Get sign with identifier 10 placed in a.py + echo sign_getplaced("a.py", {'id' : 10'}) + + " Get sign with id 20 in group 'g1' placed in a.py + echo sign_getplaced("a.py", {'group' : 'g1', + \ 'id' : 20'}) + + " Get a List of all the placed signs + echo sign_getplaced() +< + *sign_place()* +sign_place({id}, {group}, {name}, {expr} [, {dict}]) + Place the sign defined as {name} at line {lnum} in file {expr} + and assign {id} and {group} to sign. This is similar to the + |:sign-place| command. + + If the sign identifier {id} is zero, then a new identifier is + allocated. Otherwise the specified number is used. {group} is + the sign group name. To use the global sign group, use an + empty string. {group} functions as a namespace for {id}, thus + two groups can use the same IDs. + + {name} refers to a defined sign. + {expr} refers to a buffer name or number. For the accepted + values, see |bufname()|. + + The optional {dict} argument supports the following entries: + lnum line number in the buffer {expr} where + the sign is to be placed. For the + accepted values, see |line()|. + priority priority of the sign. See + |sign-priority| for more information. + + If the optional {dict} is not specified, then it modifies the + placed sign {id} in group {group} to use the defined sign + {name}. + + Returns the sign identifier on success and -1 on failure. + + Examples: > + " Place a sign named sign1 with id 5 at line 20 in + " buffer json.c + call sign_place(5, '', 'sign1', 'json.c', + \ {'lnum' : 20}) + + " Updates sign 5 in buffer json.c to use sign2 + call sign_place(5, '', 'sign2', 'json.c') + + " Place a sign named sign3 at line 30 in + " buffer json.c with a new identifier + let id = sign_place(0, '', 'sign3', 'json.c', + \ {'lnum' : 30}) + + " Place a sign named sign4 with id 10 in group 'g3' + " at line 40 in buffer json.c with priority 90 + call sign_place(10, 'g3', 'sign4', 'json.c', + \ {'lnum' : 40, 'priority' : 90}) +< +sign_undefine([{name}]) *sign_undefine()* + Deletes a previously defined sign {name}. This is similar to + the |:sign-undefine| command. If {name} is not supplied, then + deletes all the defined signs. + + Returns 0 on success and -1 on failure. + + Examples: > + " Delete a sign named mySign + call sign_undefine("mySign") + + " Delete all the signs + call sign_undefine() +< +sign_unplace({group} [, {dict}]) *sign_unplace()* + Remove a previously placed sign in one or more buffers. This + is similar to the |:sign-unplace()| command. + + {group} is the sign group name. To use the global sign group, + use an empty string. If {group} is set to '*', then all the + groups including the global group are used. + The signs in {group} are selected based on the entries in + {dict}. The following optional entries in {dict} are + supported: + buffer buffer name or number. See |bufname()|. + id sign identifier + If {dict} is not supplied, then all the signs in {group} are + removed. + + Returns 0 on success and -1 on failure. + + Examples: > + " Remove sign 10 from buffer a.vim + call sign_unplace('', {'buffer' : "a.vim", 'id' : 10}) + + " Remove sign 20 in group 'g1' from buffer 3 + call sign_unplace('g1', {'buffer' : 3, 'id' : 20}) + + " Remove all the signs in group 'g2' from buffer 10 + call sign_unplace('g2', {'buffer' : 10}) + + " Remove sign 30 in group 'g3' from all the buffers + call sign_unplace('g3', {'id' : 30}) + + " Remove all the signs placed in buffer 5 + call sign_unplace('*', {'buffer' : 5}) + + " Remove the signs in group 'g4' from all the buffers + call sign_unplace('g4') + + " Remove sign 40 from all the buffers + call sign_unplace('*', {'id' : 40}) + + " Remove all the placed signs from all the buffers + call sign_unplace('*') +< simplify({filename}) *simplify()* Simplify the file name as much as possible without changing the meaning. Shortcuts (on MS-Windows) or symbolic links (on diff --git a/runtime/doc/sign.txt b/runtime/doc/sign.txt index bd63ea9ade..115e1faa45 100644 --- a/runtime/doc/sign.txt +++ b/runtime/doc/sign.txt @@ -1,4 +1,4 @@ -*sign.txt* For Vim version 8.1. Last change: 2016 Aug 17 +*sign.txt* For Vim version 8.1. Last change: 2018 Dec 21 VIM REFERENCE MANUAL by Gordon Prieur @@ -51,6 +51,20 @@ The color of the column is set with the SignColumn group |hl-SignColumn|. Example to set the color: > :highlight SignColumn guibg=darkgrey +< + *sign-group* +Each sign can be assigned to either the global group or a named group. When +placing a sign, if a group name is not supplied, or an empty string is used, +then the sign is placed in the global group. Otherwise the sign is placed in +the named group. The sign identifier is unique within a group. The sign group +allows Vim plugins to use unique signs without interfering with other plugins +using signs. + + *sign-priority* +Each placed sign is assigned a priority value. When multiple signs are placed +on the same line, the attributes of the sign with the highest priority is used +independent of the sign group. The default priority for a sign is 10. The +priority is assigned at the time of placing a sign. ============================================================================== 2. Commands *sign-commands* *:sig* *:sign* @@ -69,6 +83,8 @@ comment. If you do need that, use the |:execute| command. DEFINING A SIGN. *:sign-define* *E255* *E160* *E612* +See |sign_define()| for the equivalent Vim script function. + :sign define {name} {argument}... Define a new sign or set attributes for an existing sign. The {name} can either be a number (all digits) or a name @@ -106,13 +122,18 @@ DEFINING A SIGN. *:sign-define* *E255* *E160* *E612* DELETING A SIGN *:sign-undefine* *E155* +See |sign_undefine()| for the equivalent Vim script function. + :sign undefine {name} Deletes a previously defined sign. If signs with this {name} are still placed this will cause trouble. + LISTING SIGNS *:sign-list* *E156* +See |sign_getdefined()| for the equivalent Vim script function. + :sign list Lists all defined signs and their attributes. :sign list {name} @@ -121,6 +142,8 @@ LISTING SIGNS *:sign-list* *E156* PLACING SIGNS *:sign-place* *E158* +See |sign_place()| for the equivalent Vim script function. + :sign place {id} line={lnum} name={name} file={fname} Place sign defined as {name} at line {lnum} in file {fname}. *:sign-fname* @@ -136,6 +159,25 @@ PLACING SIGNS *:sign-place* *E158* to be done several times and making changes may not work as expected). + The following optional sign attributes can be specified before + "file=": + group={group} Place sign in sign group {group} + priority={prio} Assign priority {prio} to sign + + By default, the sign is placed in the global sign group. + + By default, the sign is assigned a default priority of 10. To + assign a different priority value, use "priority={prio}" to + specify a value. The priority is used to determine the + highlight group used when multiple signs are placed on the + same line. + + Examples: > + :sign place 5 line=3 name=sign1 file=a.py + :sign place 6 group=g2 line=2 name=sign2 file=x.py + :sign place 9 group=g2 priority=50 line=5 + \ name=sign1 file=a.py +< :sign place {id} line={lnum} name={name} buffer={nr} Same, but use buffer {nr}. @@ -146,31 +188,73 @@ PLACING SIGNS *:sign-place* *E158* This can be used to change the displayed sign without moving it (e.g., when the debugger has stopped at a breakpoint). + The optional "group={group}" attribute can be used before + "file=" to select a sign in a particular group. + :sign place {id} name={name} buffer={nr} Same, but use buffer {nr}. REMOVING SIGNS *:sign-unplace* *E159* +See |sign_unplace()| for the equivalent Vim script function. + :sign unplace {id} file={fname} Remove the previously placed sign {id} from file {fname}. See remark above about {fname} |:sign-fname|. +:sign unplace {id} group={group} file={fname} + Same but remove the sign {id} in sign group {group}. + +:sign unplace {id} group=* file={fname} + Same but remove the sign {id} from all the sign groups. + :sign unplace * file={fname} Remove all placed signs in file {fname}. +:sign unplace * group={group} file={fname} + Remove all placed signs in group {group} from file {fname}. + +:sign unplace * group=* file={fname} + Remove all placed signs in all the groups from file {fname}. + :sign unplace {id} buffer={nr} Remove the previously placed sign {id} from buffer {nr}. +:sign unplace {id} group={group} buffer={nr} + Remove the previously placed sign {id} in group {group} from + buffer {nr}. + +:sign unplace {id} group=* buffer={nr} + Remove the previously placed sign {id} in all the groups from + buffer {nr}. + :sign unplace * buffer={nr} Remove all placed signs in buffer {nr}. +:sign unplace * group={group} buffer={nr} + Remove all placed signs in group {group} from buffer {nr}. + +:sign unplace * group=* buffer={nr} + Remove all placed signs in all the groups from buffer {nr}. + :sign unplace {id} Remove the previously placed sign {id} from all files it appears in. +:sign unplace {id} group={group} + Remove the previously placed sign {id} in group {group} from + all files it appears in. + +:sign unplace {id} group=* + Remove the previously placed sign {id} in all the groups from + all the files it appears in. + :sign unplace * - Remove all placed signs. + Remove all placed signs in the global group. + +:sign unplace * group=* + Remove all placed signs in all the groups. :sign unplace Remove the placed sign at the cursor position. @@ -178,15 +262,26 @@ REMOVING SIGNS *:sign-unplace* *E159* LISTING PLACED SIGNS *:sign-place-list* +See |sign_getplaced()| for the equivalent Vim script function. + :sign place file={fname} List signs placed in file {fname}. See remark above about {fname} |:sign-fname|. +:sign place group={group} file={fname} + List signs in group {group} 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={group} + List placed signs in all sign groups in all the files. + JUMPING TO A SIGN *:sign-jump* *E157* diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt index 1ad044b324..343d476a4c 100644 --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -983,6 +983,14 @@ Jobs: *job-functions* job_info() get information about a job job_setoptions() set options for a job +Signs: *sign-functions* + sign_define() define or update a sign + sign_getdefined() get a list of defined signs + sign_getplaced() get a list of placed signs + sign_place() place a sign + sign_undefine() undefine a sign + sign_unplace() unplace a sign + Terminal window: *terminal-functions* term_start() open a terminal window and run a job term_list() get the list of terminal buffers diff --git a/src/alloc.h b/src/alloc.h index 36890054fd..8babde3bd7 100644 --- a/src/alloc.h +++ b/src/alloc.h @@ -21,5 +21,13 @@ typedef enum { aid_tagstack_items, aid_tagstack_from, aid_tagstack_details, + aid_sign_getdefined, + aid_sign_getplaced, + aid_sign_define_by_name, + aid_sign_getlist, + aid_sign_getplaced_dict, + aid_sign_getplaced_list, + aid_insert_sign, + aid_sign_getinfo, aid_last } alloc_id_T; diff --git a/src/buffer.c b/src/buffer.c index 66068d9637..4055af904f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -936,7 +936,7 @@ free_buffer_stuff( uc_clear(&buf->b_ucmds); /* clear local user commands */ #endif #ifdef FEAT_SIGNS - buf_delete_signs(buf); /* delete any signs */ + buf_delete_signs(buf, (char_u *)"*"); // delete any signs */ #endif #ifdef FEAT_NETBEANS_INTG netbeans_file_killed(buf); @@ -5866,25 +5866,34 @@ win_found: #if defined(FEAT_SIGNS) || defined(PROTO) /* - * Insert the sign into the signlist. + * Insert a new sign into the signlist for buffer 'buf' between the 'prev' and + * 'next' signs. */ static void insert_sign( - buf_T *buf, /* buffer to store sign in */ - signlist_T *prev, /* previous sign entry */ - signlist_T *next, /* next sign entry */ - int id, /* sign ID */ - linenr_T lnum, /* line number which gets the mark */ - int typenr) /* typenr of sign we are adding */ + buf_T *buf, // buffer to store sign in + signlist_T *prev, // previous sign entry + signlist_T *next, // next sign entry + int id, // sign ID + char_u *group, // sign group; NULL for global group + int prio, // sign priority + linenr_T lnum, // line number which gets the mark + int typenr) // typenr of sign we are adding { signlist_T *newsign; - newsign = (signlist_T *)lalloc((long_u)sizeof(signlist_T), FALSE); + newsign = (signlist_T *)lalloc_id((long_u)sizeof(signlist_T), FALSE, + aid_insert_sign); if (newsign != NULL) { newsign->id = id; newsign->lnum = lnum; newsign->typenr = typenr; + if (group != NULL) + newsign->group = vim_strsave(group); + else + newsign->group = NULL; + newsign->priority = prio; newsign->next = next; newsign->prev = prev; if (next != NULL) @@ -5892,15 +5901,15 @@ insert_sign( if (prev == NULL) { - /* When adding first sign need to redraw the windows to create the - * column for signs. */ + // When adding first sign need to redraw the windows to create the + // column for signs. if (buf->b_signlist == NULL) { redraw_buf_later(buf, NOT_VALID); changed_cline_bef_curs(); } - /* first sign in signlist */ + // first sign in signlist buf->b_signlist = newsign; #ifdef FEAT_NETBEANS_INTG if (netbeans_active()) @@ -5913,50 +5922,100 @@ insert_sign( } /* + * Insert a new sign sorted by line number and sign priority. + */ + static void +insert_sign_by_lnum_prio( + buf_T *buf, // buffer to store sign in + signlist_T *prev, // previous sign entry + int id, // sign ID + char_u *group, // sign group; NULL for global group + int prio, // sign priority + linenr_T lnum, // line number which gets the mark + int typenr) // typenr of sign we are adding +{ + signlist_T *sign; + + // keep signs sorted by lnum and by priority: insert new sign at + // the proper position in the list for this lnum. + while (prev != NULL && prev->lnum == lnum && prev->priority <= prio) + prev = prev->prev; + if (prev == NULL) + sign = buf->b_signlist; + else + sign = prev->next; + + insert_sign(buf, prev, sign, id, group, prio, lnum, typenr); +} + +/* + * Returns TRUE if 'sign' is in 'group'. + * A sign can either be in the global group (sign->group == NULL) + * or in a named group. If 'group' is '*', then the sign is part of the group. + */ + 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) == 0)); +} + +/* + * Return information about a sign in a Dict + */ + dict_T * +sign_get_info(signlist_T *sign) +{ + dict_T *d; + + if ((d = dict_alloc_id(aid_sign_getinfo)) == NULL) + return NULL; + dict_add_number(d, "id", sign->id); + dict_add_string(d, "group", (sign->group == NULL) ? + (char_u *)"" : sign->group); + dict_add_number(d, "lnum", sign->lnum); + dict_add_string(d, "name", sign_typenr2name(sign->typenr)); + dict_add_number(d, "priority", sign->priority); + + return d; +} + +/* * Add the sign into the signlist. Find the right spot to do it though. */ void buf_addsign( - buf_T *buf, /* buffer to store sign in */ - int id, /* sign ID */ - linenr_T lnum, /* line number which gets the mark */ - int typenr) /* typenr of sign we are adding */ + buf_T *buf, // buffer to store sign in + int id, // sign ID + char_u *group, // sign group + int prio, // sign priority + linenr_T lnum, // line number which gets the mark + int typenr) // typenr of sign we are adding { - signlist_T *sign; /* a sign in the signlist */ - signlist_T *prev; /* the previous sign */ + signlist_T *sign; // a sign in the signlist + signlist_T *prev; // the previous sign prev = NULL; - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) + FOR_ALL_SIGNS_IN_BUF(buf) { - if (lnum == sign->lnum && id == sign->id) + if (lnum == sign->lnum && id == sign->id && + sign_in_group(sign, group)) { + // Update an existing sign sign->typenr = typenr; return; } else if (lnum < sign->lnum) { - // keep signs sorted by lnum: insert new sign at head of list for - // this lnum - while (prev != NULL && prev->lnum == lnum) - prev = prev->prev; - if (prev == NULL) - sign = buf->b_signlist; - else - sign = prev->next; - insert_sign(buf, prev, sign, id, lnum, typenr); + insert_sign_by_lnum_prio(buf, prev, id, group, prio, lnum, typenr); return; } prev = sign; } - // insert new sign at head of list for this lnum - while (prev != NULL && prev->lnum == lnum) - prev = prev->prev; - if (prev == NULL) - sign = buf->b_signlist; - else - sign = prev->next; - insert_sign(buf, prev, sign, id, lnum, typenr); + insert_sign_by_lnum_prio(buf, prev, id, group, prio, lnum, typenr); return; } @@ -5967,15 +6026,16 @@ buf_addsign( */ linenr_T buf_change_sign_type( - buf_T *buf, /* buffer to store sign in */ - int markId, /* sign ID */ - int typenr) /* typenr of sign we are adding */ + buf_T *buf, // buffer to store sign in + int markId, // sign ID + char_u *group, // sign group + int typenr) // typenr of sign we are adding { - signlist_T *sign; /* a sign in the signlist */ + signlist_T *sign; // a sign in the signlist - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) + FOR_ALL_SIGNS_IN_BUF(buf) { - if (sign->id == markId) + if (sign->id == markId && sign_in_group(sign, group)) { sign->typenr = typenr; return sign->lnum; @@ -5985,6 +6045,11 @@ buf_change_sign_type( return (linenr_T)0; } +/* + * Return the type number of the sign at line number 'lnum' in buffer 'buf' + * which has the attribute specifed by 'type'. Returns 0 if a sign is not found + * at the line number or it doesn't have the specified attribute. + */ int buf_getsigntype( buf_T *buf, @@ -5993,7 +6058,7 @@ buf_getsigntype( { signlist_T *sign; /* a sign in a b_signlist */ - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) + FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum && (type == SIGN_ANY # ifdef FEAT_SIGN_ICONS @@ -6008,37 +6073,51 @@ buf_getsigntype( return 0; } - +/* + * Delete sign 'id' in group 'group' from buffer 'buf'. + * If 'id' is zero, then delete all the signs in group 'group'. Otherwise + * delete only the specified sign. + * If 'group' is '*', then delete the sign in all the groups. If 'group' is + * NULL, then delete the sign in the global group. Otherwise delete the sign in + * the specified group. + * Returns the line number of the deleted sign. If multiple signs are deleted, + * then returns the line number of the last sign deleted. + */ linenr_T buf_delsign( - buf_T *buf, /* buffer sign is stored in */ - int id) /* sign id */ + buf_T *buf, // buffer sign is stored in + int id, // sign id + char_u *group) // sign group { - signlist_T **lastp; /* pointer to pointer to current sign */ - signlist_T *sign; /* a sign in a b_signlist */ - signlist_T *next; /* the next sign in a b_signlist */ - linenr_T lnum; /* line number whose sign was deleted */ + signlist_T **lastp; // pointer to pointer to current sign + signlist_T *sign; // a sign in a b_signlist + signlist_T *next; // the next sign in a b_signlist + linenr_T lnum; // line number whose sign was deleted lastp = &buf->b_signlist; lnum = 0; for (sign = buf->b_signlist; sign != NULL; sign = next) { next = sign->next; - if (sign->id == id) + if ((id == 0 || sign->id == id) && sign_in_group(sign, group)) + { *lastp = next; if (next != NULL) next->prev = sign->prev; lnum = sign->lnum; + vim_free(sign->group); vim_free(sign); - break; + // Check whether only one sign needs to be deleted + if (group == NULL || (*group != '*' && id != 0)) + break; } else lastp = &sign->next; } - /* When deleted the last sign need to redraw the windows to remove the - * sign column. */ + // When deleted the last sign need to redraw the windows to remove the + // sign column. if (buf->b_signlist == NULL) { redraw_buf_later(buf, NOT_VALID); @@ -6050,39 +6129,78 @@ buf_delsign( /* - * Find the line number of the sign with the requested id. If the sign does - * not exist, return 0 as the line number. This will still let the correct file - * get loaded. + * Find the line number of the sign with the requested id in group 'group'. If + * the sign does not exist, return 0 as the line number. This will still let + * the correct file get loaded. */ int buf_findsign( - buf_T *buf, /* buffer to store sign in */ - int id) /* sign ID */ + buf_T *buf, // buffer to store sign in + int id, // sign ID + char_u *group) // sign group { - signlist_T *sign; /* a sign in the signlist */ + signlist_T *sign; // a sign in the signlist - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) - if (sign->id == id) + FOR_ALL_SIGNS_IN_BUF(buf) + if (sign->id == id && sign_in_group(sign, group)) return sign->lnum; return 0; } +/* + * Return the sign at line 'lnum' in buffer 'buf'. Returns NULL if a sign is + * not found at the line. + */ + static signlist_T * +buf_getsign_at_line( + buf_T *buf, // buffer whose sign we are searching for + linenr_T lnum) // line number of sign +{ + signlist_T *sign; // a sign in the signlist + + FOR_ALL_SIGNS_IN_BUF(buf) + if (sign->lnum == lnum) + return sign; + + return NULL; +} + +/* + * Return the sign with identifier 'id' in group 'group' placed in buffer 'buf' + */ + signlist_T * +buf_getsign_with_id( + buf_T *buf, // buffer whose sign we are searching for + int id, // sign identifier + char_u *group) // sign group +{ + signlist_T *sign; // a sign in the signlist + + FOR_ALL_SIGNS_IN_BUF(buf) + if (sign->id == id && sign_in_group(sign, group)) + return sign; + + return NULL; +} + +/* + * Return the identifier of the sign at line number 'lnum' in buffer 'buf'. + */ int buf_findsign_id( - buf_T *buf, /* buffer whose sign we are searching for */ - linenr_T lnum) /* line number of sign */ + buf_T *buf, // buffer whose sign we are searching for + linenr_T lnum) // line number of sign { - signlist_T *sign; /* a sign in the signlist */ + signlist_T *sign; // a sign in the signlist - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) - if (sign->lnum == lnum) - return sign->id; + sign = buf_getsign_at_line(buf, lnum); + if (sign != NULL) + return sign->id; return 0; } - # if defined(FEAT_NETBEANS_INTG) || defined(PROTO) /* * See if a given type of sign exists on a specific line. @@ -6095,7 +6213,7 @@ buf_findsigntype_id( { signlist_T *sign; /* a sign in the signlist */ - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) + FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum && sign->typenr == typenr) return sign->id; @@ -6110,10 +6228,10 @@ buf_findsigntype_id( int buf_signcount(buf_T *buf, linenr_T lnum) { - signlist_T *sign; /* a sign in the signlist */ + signlist_T *sign; // a sign in the signlist int count = 0; - for (sign = buf->b_signlist; sign != NULL; sign = sign->next) + FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum) if (sign_get_image(sign->typenr) != NULL) count++; @@ -6123,28 +6241,39 @@ buf_signcount(buf_T *buf, linenr_T lnum) # endif /* FEAT_SIGN_ICONS */ # endif /* FEAT_NETBEANS_INTG */ - /* - * Delete signs in buffer "buf". + * Delete signs in group 'group' in buffer "buf". If 'group' is '*', then + * delete all the signs. */ void -buf_delete_signs(buf_T *buf) +buf_delete_signs(buf_T *buf, char_u *group) { + signlist_T *sign; + signlist_T **lastp; // pointer to pointer to current sign signlist_T *next; - /* When deleting the last sign need to redraw the windows to remove the - * sign column. Not when curwin is NULL (this means we're exiting). */ + // When deleting the last sign need to redraw the windows to remove the + // sign column. Not when curwin is NULL (this means we're exiting). if (buf->b_signlist != NULL && curwin != NULL) { redraw_buf_later(buf, NOT_VALID); changed_cline_bef_curs(); } - while (buf->b_signlist != NULL) + lastp = &buf->b_signlist; + for (sign = buf->b_signlist; sign != NULL; sign = next) { - next = buf->b_signlist->next; - vim_free(buf->b_signlist); - buf->b_signlist = next; + next = sign->next; + if (sign_in_group(sign, group)) + { + *lastp = next; + if (next != NULL) + next->prev = sign->prev; + vim_free(sign->group); + vim_free(sign); + } + else + lastp = &sign->next; } } @@ -6158,18 +6287,19 @@ buf_delete_all_signs(void) FOR_ALL_BUFFERS(buf) if (buf->b_signlist != NULL) - buf_delete_signs(buf); + buf_delete_signs(buf, (char_u *)"*"); } /* * List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers. */ void -sign_list_placed(buf_T *rbuf) +sign_list_placed(buf_T *rbuf, char_u *sign_group) { buf_T *buf; - signlist_T *p; + signlist_T *sign; |