To: vim_dev@googlegroups.com Subject: Patch 8.1.0644 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0644 Problem: Finding next sign ID is inefficient. Solution: Add next_sign_id. (Yegappan Lakshmanan, closes #3717) Files: runtime/doc/eval.txt, src/buffer.c, src/evalfunc.c, src/ex_cmds.c, src/globals.h, src/main.c, src/proto/buffer.pro, src/structs.h, src/testdir/test_signs.vim *** ../vim-8.1.0643/runtime/doc/eval.txt 2018-12-24 23:05:08.546418665 +0100 --- runtime/doc/eval.txt 2018-12-27 00:19:40.089578543 +0100 *************** *** 7919,7928 **** 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: --- 7936,7945 ---- 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 or is an ! empty string, 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: *** ../vim-8.1.0643/src/buffer.c 2018-12-24 20:23:39.440716979 +0100 --- src/buffer.c 2018-12-27 00:19:40.089578543 +0100 *************** *** 5866,5871 **** --- 5866,5881 ---- #if defined(FEAT_SIGNS) || defined(PROTO) static hashtab_T sg_table; // sign group (signgroup_T) hashtable + static int next_sign_id = 1; // next sign id in the global group + + /* + * Initialize data needed for managing signs + */ + void + init_signs(void) + { + hash_init(&sg_table); // sign group hash table + } /* * A new sign in group 'groupname' is added. If the group is not present, *************** *** 5874,5890 **** static signgroup_T * sign_group_ref(char_u *groupname) { - static int initialized = FALSE; hash_T hash; hashitem_T *hi; signgroup_T *group; - if (!initialized) - { - initialized = TRUE; - hash_init(&sg_table); - } - hash = hash_hash(groupname); hi = hash_lookup(&sg_table, groupname, hash); if (HASHITEM_EMPTY(hi)) --- 5884,5893 ---- *************** *** 5896,5901 **** --- 5899,5905 ---- return NULL; STRCPY(group->sg_name, groupname); group->refcount = 1; + group->next_sign_id = 1; hash_add_item(&sg_table, hi, group->sg_name, hash); } else *************** *** 5933,5938 **** --- 5937,5985 ---- } /* + * Get the next free sign identifier in the specified group + */ + int + sign_group_get_next_signid(buf_T *buf, char_u *groupname) + { + int id = 1; + signgroup_T *group = NULL; + signlist_T *sign; + hashitem_T *hi; + int found = FALSE; + + if (groupname != NULL) + { + hi = hash_find(&sg_table, groupname); + if (HASHITEM_EMPTY(hi)) + return id; + group = HI2SG(hi); + } + + // Search for the next usuable sign identifier + while (!found) + { + if (group == NULL) + id = next_sign_id++; // global group + else + id = group->next_sign_id++; + + // Check whether this sign is already placed in the buffer + found = TRUE; + FOR_ALL_SIGNS_IN_BUF(buf, sign) + { + if (id == sign->id && sign_in_group(sign, groupname)) + { + found = FALSE; // sign identifier is in use + break; + } + } + } + + return id; + } + + /* * Insert a new sign into the signlist for buffer 'buf' between the 'prev' and * 'next' signs. */ *************** *** 6072,6078 **** signlist_T *prev; // the previous sign prev = NULL; ! FOR_ALL_SIGNS_IN_BUF(buf) { if (lnum == sign->lnum && id == sign->id && sign_in_group(sign, groupname)) --- 6119,6125 ---- signlist_T *prev; // the previous sign prev = NULL; ! FOR_ALL_SIGNS_IN_BUF(buf, sign) { if (lnum == sign->lnum && id == sign->id && sign_in_group(sign, groupname)) *************** *** 6107,6113 **** { signlist_T *sign; // a sign in the signlist ! FOR_ALL_SIGNS_IN_BUF(buf) { if (sign->id == markId && sign_in_group(sign, group)) { --- 6154,6160 ---- { signlist_T *sign; // a sign in the signlist ! FOR_ALL_SIGNS_IN_BUF(buf, sign) { if (sign->id == markId && sign_in_group(sign, group)) { *************** *** 6132,6138 **** { signlist_T *sign; /* a sign in a b_signlist */ ! FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum && (type == SIGN_ANY # ifdef FEAT_SIGN_ICONS --- 6179,6185 ---- { signlist_T *sign; /* a sign in a b_signlist */ ! FOR_ALL_SIGNS_IN_BUF(buf, sign) if (sign->lnum == lnum && (type == SIGN_ANY # ifdef FEAT_SIGN_ICONS *************** *** 6216,6222 **** { 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->lnum; --- 6263,6269 ---- { signlist_T *sign; // a sign in the signlist ! FOR_ALL_SIGNS_IN_BUF(buf, sign) if (sign->id == id && sign_in_group(sign, group)) return sign->lnum; *************** *** 6234,6240 **** { signlist_T *sign; // a sign in the signlist ! FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum) return sign; --- 6281,6287 ---- { signlist_T *sign; // a sign in the signlist ! FOR_ALL_SIGNS_IN_BUF(buf, sign) if (sign->lnum == lnum) return sign; *************** *** 6252,6258 **** { 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; --- 6299,6305 ---- { signlist_T *sign; // a sign in the signlist ! FOR_ALL_SIGNS_IN_BUF(buf, sign) if (sign->id == id && sign_in_group(sign, group)) return sign; *************** *** 6288,6294 **** { signlist_T *sign; /* a sign in the signlist */ ! FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum && sign->typenr == typenr) return sign->id; --- 6335,6341 ---- { signlist_T *sign; /* a sign in the signlist */ ! FOR_ALL_SIGNS_IN_BUF(buf, sign) if (sign->lnum == lnum && sign->typenr == typenr) return sign->id; *************** *** 6306,6312 **** signlist_T *sign; // a sign in the signlist int count = 0; ! FOR_ALL_SIGNS_IN_BUF(buf) if (sign->lnum == lnum) if (sign_get_image(sign->typenr) != NULL) count++; --- 6353,6359 ---- signlist_T *sign; // a sign in the signlist int count = 0; ! FOR_ALL_SIGNS_IN_BUF(buf, sign) if (sign->lnum == lnum) if (sign_get_image(sign->typenr) != NULL) count++; *************** *** 6391,6397 **** MSG_PUTS_ATTR(lbuf, HL_ATTR(HLF_D)); msg_putchar('\n'); } ! FOR_ALL_SIGNS_IN_BUF(buf) { if (got_int) break; --- 6438,6444 ---- MSG_PUTS_ATTR(lbuf, HL_ATTR(HLF_D)); msg_putchar('\n'); } ! FOR_ALL_SIGNS_IN_BUF(buf, sign) { if (got_int) break; *************** *** 6427,6433 **** { signlist_T *sign; /* a sign in a b_signlist */ ! FOR_ALL_SIGNS_IN_BUF(curbuf) { if (sign->lnum >= line1 && sign->lnum <= line2) { --- 6474,6480 ---- { signlist_T *sign; /* a sign in a b_signlist */ ! FOR_ALL_SIGNS_IN_BUF(curbuf, sign) { if (sign->lnum >= line1 && sign->lnum <= line2) { *** ../vim-8.1.0643/src/evalfunc.c 2018-12-24 23:35:09.119234692 +0100 --- src/evalfunc.c 2018-12-27 00:19:40.089578543 +0100 *************** *** 4434,4440 **** signlist_T *sign; dict_T *d; ! FOR_ALL_SIGNS_IN_BUF(buf) { if ((d = sign_get_info(sign)) != NULL) list_append_dict(l, d); --- 4434,4440 ---- signlist_T *sign; dict_T *d; ! FOR_ALL_SIGNS_IN_BUF(buf, sign) { if ((d = sign_get_info(sign)) != NULL) list_append_dict(l, d); *************** *** 11415,11420 **** --- 11415,11422 ---- group = tv_get_string_chk(&di->di_tv); if (group == NULL) return; + if (*group == '\0') // empty string means global group + group = NULL; } } } *** ../vim-8.1.0643/src/ex_cmds.c 2018-12-24 20:23:39.440716979 +0100 --- src/ex_cmds.c 2018-12-27 00:19:40.089578543 +0100 *************** *** 7871,7886 **** return FAIL; } if (*sign_id == 0) ! { ! // Allocate a new sign id ! int id = 1; ! signlist_T *sign; ! ! while ((sign = buf_getsign_with_id(buf, id, sign_group)) != NULL) ! id++; ! ! *sign_id = id; ! } if (lnum > 0) // ":sign place {id} line={lnum} name={name} file={fname}": --- 7871,7877 ---- return FAIL; } if (*sign_id == 0) ! *sign_id = sign_group_get_next_signid(buf, sign_group); if (lnum > 0) // ":sign place {id} line={lnum} name={name} file={fname}": *************** *** 8193,8199 **** else if (idx == SIGNCMD_JUMP) { /* ":sign jump {id} file={fname}" */ ! if (lnum >= 0 || sign_name != NULL) EMSG(_(e_invarg)); else if ((lnum = buf_findsign(buf, id, group)) > 0) { /* goto a sign ... */ --- 8184,8190 ---- else if (idx == SIGNCMD_JUMP) { /* ":sign jump {id} file={fname}" */ ! if (lnum >= 0 || sign_name != NULL || buf == NULL) EMSG(_(e_invarg)); else if ((lnum = buf_findsign(buf, id, group)) > 0) { /* goto a sign ... */ *************** *** 8350,8356 **** return; dict_add_list(d, "signs", l); ! FOR_ALL_SIGNS_IN_BUF(buf) { if (!sign_in_group(sign, sign_group)) continue; --- 8341,8347 ---- return; dict_add_list(d, "signs", l); ! FOR_ALL_SIGNS_IN_BUF(buf, sign) { if (!sign_in_group(sign, sign_group)) continue; *** ../vim-8.1.0643/src/globals.h 2018-12-22 17:07:45.771347741 +0100 --- src/globals.h 2018-12-27 00:19:40.089578543 +0100 *************** *** 609,615 **** #define FOR_ALL_BUFFERS(buf) for (buf = firstbuf; buf != NULL; buf = buf->b_next) // Iterate through all the signs placed in a buffer ! #define FOR_ALL_SIGNS_IN_BUF(buf) \ for (sign = buf->b_signlist; sign != NULL; sign = sign->next) /* Flag that is set when switching off 'swapfile'. It means that all blocks --- 609,615 ---- #define FOR_ALL_BUFFERS(buf) for (buf = firstbuf; buf != NULL; buf = buf->b_next) // Iterate through all the signs placed in a buffer ! #define FOR_ALL_SIGNS_IN_BUF(buf, sign) \ for (sign = buf->b_signlist; sign != NULL; sign = sign->next) /* Flag that is set when switching off 'swapfile'. It means that all blocks *** ../vim-8.1.0643/src/main.c 2018-11-10 17:33:23.087518814 +0100 --- src/main.c 2018-12-27 00:19:40.093578509 +0100 *************** *** 1032,1037 **** --- 1032,1041 ---- #ifdef FEAT_EVAL set_lang_var(); /* set v:lang and v:ctype */ #endif + + #ifdef FEAT_SIGNS + init_signs(); + #endif } /* *** ../vim-8.1.0643/src/proto/buffer.pro 2018-12-21 15:16:57.479579788 +0100 --- src/proto/buffer.pro 2018-12-27 00:19:40.093578509 +0100 *************** *** 75,80 **** --- 75,82 ---- 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); signlist_T *buf_getsign_with_id(buf_T *buf, int id, char_u *group); *** ../vim-8.1.0643/src/structs.h 2018-12-26 00:25:15.547995294 +0100 --- src/structs.h 2018-12-27 00:19:40.093578509 +0100 *************** *** 737,742 **** --- 737,743 ---- typedef struct signgroup_S { short_u refcount; // number of signs in this group + int next_sign_id; // next sign id for this group char_u sg_name[1]; // sign group name } signgroup_T; *** ../vim-8.1.0643/src/testdir/test_signs.vim 2018-12-24 20:23:39.440716979 +0100 --- src/testdir/test_signs.vim 2018-12-27 00:19:40.093578509 +0100 *************** *** 301,307 **** sign undefine Sign endfunc ! " Test for VimL functions for managing signs func Test_sign_funcs() " Remove all the signs call sign_unplace('*') --- 301,307 ---- sign undefine Sign endfunc ! " Test for Vim script functions for managing signs func Test_sign_funcs() " Remove all the signs call sign_unplace('*') *************** *** 733,739 **** call assert_equal(3, sign_place(0, '', 'sign1', 'Xsign', \ {'lnum' : 14})) call sign_unplace('', {'buffer' : 'Xsign', 'id' : 2}) ! call assert_equal(2, sign_place(0, '', 'sign1', 'Xsign', \ {'lnum' : 12})) call assert_equal(1, sign_place(0, 'g1', 'sign1', 'Xsign', --- 733,739 ---- call assert_equal(3, sign_place(0, '', 'sign1', 'Xsign', \ {'lnum' : 14})) call sign_unplace('', {'buffer' : 'Xsign', 'id' : 2}) ! call assert_equal(4, sign_place(0, '', 'sign1', 'Xsign', \ {'lnum' : 12})) call assert_equal(1, sign_place(0, 'g1', 'sign1', 'Xsign', *** ../vim-8.1.0643/src/version.c 2018-12-26 23:42:05.331769359 +0100 --- src/version.c 2018-12-27 00:22:10.868312009 +0100 *************** *** 801,802 **** --- 801,804 ---- { /* Add new patch number below this line */ + /**/ + 644, /**/ -- Over the years, I've developed my sense of deja vu so acutely that now I can remember things that *have* happened before ... /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///