comparison src/tag.c @ 16447:54ffc82f38a8 v8.1.1228

patch 8.1.1228: not possible to process tags with a function commit https://github.com/vim/vim/commit/45e18cbdc40afd8144d20dcc07ad2d981636f4c9 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Apr 28 18:05:35 2019 +0200 patch 8.1.1228: not possible to process tags with a function Problem: Not possible to process tags with a function. Solution: Add tagfunc() (Christian Brabandt, Andy Massimino, closes https://github.com/vim/vim/issues/4010)
author Bram Moolenaar <Bram@vim.org>
date Sun, 28 Apr 2019 18:15:07 +0200
parents 3d6b282e2d6e
children 826ad48af5e3
comparison
equal deleted inserted replaced
16446:cee0719a1b4b 16447:54ffc82f38a8
16 /* 16 /*
17 * Structure to hold pointers to various items in a tag line. 17 * Structure to hold pointers to various items in a tag line.
18 */ 18 */
19 typedef struct tag_pointers 19 typedef struct tag_pointers
20 { 20 {
21 /* filled in by parse_tag_line(): */ 21 // filled in by parse_tag_line():
22 char_u *tagname; /* start of tag name (skip "file:") */ 22 char_u *tagname; // start of tag name (skip "file:")
23 char_u *tagname_end; /* char after tag name */ 23 char_u *tagname_end; // char after tag name
24 char_u *fname; /* first char of file name */ 24 char_u *fname; // first char of file name
25 char_u *fname_end; /* char after file name */ 25 char_u *fname_end; // char after file name
26 char_u *command; /* first char of command */ 26 char_u *command; // first char of command
27 /* filled in by parse_match(): */ 27 // filled in by parse_match():
28 char_u *command_end; /* first char after command */ 28 char_u *command_end; // first char after command
29 char_u *tag_fname; /* file name of the tags file */ 29 char_u *tag_fname; // file name of the tags file. This is used
30 // when 'tr' is set.
30 #ifdef FEAT_EMACS_TAGS 31 #ifdef FEAT_EMACS_TAGS
31 int is_etag; /* TRUE for emacs tag */ 32 int is_etag; // TRUE for emacs tag
32 #endif 33 #endif
33 char_u *tagkind; /* "kind:" value */ 34 char_u *tagkind; // "kind:" value
34 char_u *tagkind_end; /* end of tagkind */ 35 char_u *tagkind_end; // end of tagkind
36 char_u *user_data; // user_data string
37 char_u *user_data_end; // end of user_data
35 } tagptrs_T; 38 } tagptrs_T;
36 39
37 /* 40 /*
38 * The matching tags are first stored in one of the hash tables. In 41 * The matching tags are first stored in one of the hash tables. In
39 * which one depends on the priority of the match. 42 * which one depends on the priority of the match.
76 static int find_extra(char_u **pp); 79 static int find_extra(char_u **pp);
77 static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_u **matches); 80 static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char_u **matches);
78 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL) 81 #if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
79 static int add_llist_tags(char_u *tag, int num_matches, char_u **matches); 82 static int add_llist_tags(char_u *tag, int num_matches, char_u **matches);
80 #endif 83 #endif
84 static void tagstack_clear_entry(taggy_T *item);
81 85
82 static char_u *bottommsg = (char_u *)N_("E555: at bottom of tag stack"); 86 static char_u *bottommsg = (char_u *)N_("E555: at bottom of tag stack");
83 static char_u *topmsg = (char_u *)N_("E556: at top of tag stack"); 87 static char_u *topmsg = (char_u *)N_("E556: at top of tag stack");
88 #ifdef FEAT_EVAL
89 static char_u *recurmsg = (char_u *)N_("E986: cannot modify the tag stack within tagfunc");
90 static char_u *tfu_inv_ret_msg = (char_u *)N_("E987: invalid return value from tagfunc");
91 #endif
84 92
85 static char_u *tagmatchname = NULL; /* name of last used tag */ 93 static char_u *tagmatchname = NULL; /* name of last used tag */
86 94
87 #if defined(FEAT_QUICKFIX) 95 #if defined(FEAT_QUICKFIX)
88 /* 96 /*
89 * Tag for preview window is remembered separately, to avoid messing up the 97 * Tag for preview window is remembered separately, to avoid messing up the
90 * normal tagstack. 98 * normal tagstack.
91 */ 99 */
92 static taggy_T ptag_entry = {NULL, {{0, 0, 0}, 0}, 0, 0}; 100 static taggy_T ptag_entry = {NULL, {{0, 0, 0}, 0}, 0, 0, NULL};
93 #endif 101 #endif
102
103 #ifdef FEAT_EVAL
104 static int tfu_in_use = FALSE; // disallow recursive call of tagfunc
105 #endif
106
107 // Used instead of NUL to separate tag fields in the growarrays.
108 #define TAG_SEP 0x02
94 109
95 /* 110 /*
96 * Jump to tag; handling of tag commands and tag stack 111 * Jump to tag; handling of tag commands and tag stack
97 * 112 *
98 * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack 113 * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
142 char_u **new_matches; 157 char_u **new_matches;
143 int use_tagstack; 158 int use_tagstack;
144 int skip_msg = FALSE; 159 int skip_msg = FALSE;
145 char_u *buf_ffname = curbuf->b_ffname; /* name to use for 160 char_u *buf_ffname = curbuf->b_ffname; /* name to use for
146 priority computation */ 161 priority computation */
162 int use_tfu = 1;
147 163
148 /* remember the matches for the last used tag */ 164 /* remember the matches for the last used tag */
149 static int num_matches = 0; 165 static int num_matches = 0;
150 static int max_num_matches = 0; /* limit used for match search */ 166 static int max_num_matches = 0; /* limit used for match search */
151 static char_u **matches = NULL; 167 static char_u **matches = NULL;
152 static int flags; 168 static int flags;
169
170 #ifdef FEAT_EVAL
171 if (tfu_in_use)
172 {
173 emsg(_(recurmsg));
174 return FALSE;
175 }
176 #endif
153 177
154 #ifdef EXITFREE 178 #ifdef EXITFREE
155 if (type == DT_FREE) 179 if (type == DT_FREE)
156 { 180 {
157 /* remove the list of matches */ 181 /* remove the list of matches */
166 190
167 if (type == DT_HELP) 191 if (type == DT_HELP)
168 { 192 {
169 type = DT_TAG; 193 type = DT_TAG;
170 no_regexp = TRUE; 194 no_regexp = TRUE;
195 use_tfu = 0;
171 } 196 }
172 197
173 prev_num_matches = num_matches; 198 prev_num_matches = num_matches;
174 free_string_option(nofile_fname); 199 free_string_option(nofile_fname);
175 nofile_fname = NULL; 200 nofile_fname = NULL;
185 use_tagstack = FALSE; 210 use_tagstack = FALSE;
186 new_tag = TRUE; 211 new_tag = TRUE;
187 #if defined(FEAT_QUICKFIX) 212 #if defined(FEAT_QUICKFIX)
188 if (g_do_tagpreview != 0) 213 if (g_do_tagpreview != 0)
189 { 214 {
190 vim_free(ptag_entry.tagname); 215 tagstack_clear_entry(&ptag_entry);
191 if ((ptag_entry.tagname = vim_strsave(tag)) == NULL) 216 if ((ptag_entry.tagname = vim_strsave(tag)) == NULL)
192 goto end_do_tag; 217 goto end_do_tag;
193 } 218 }
194 #endif 219 #endif
195 } 220 }
224 cur_match = ptag_entry.cur_match; 249 cur_match = ptag_entry.cur_match;
225 cur_fnum = ptag_entry.cur_fnum; 250 cur_fnum = ptag_entry.cur_fnum;
226 } 251 }
227 else 252 else
228 { 253 {
229 vim_free(ptag_entry.tagname); 254 tagstack_clear_entry(&ptag_entry);
230 if ((ptag_entry.tagname = vim_strsave(tag)) == NULL) 255 if ((ptag_entry.tagname = vim_strsave(tag)) == NULL)
231 goto end_do_tag; 256 goto end_do_tag;
232 } 257 }
233 } 258 }
234 else 259 else
237 /* 262 /*
238 * If the last used entry is not at the top, delete all tag 263 * If the last used entry is not at the top, delete all tag
239 * stack entries above it. 264 * stack entries above it.
240 */ 265 */
241 while (tagstackidx < tagstacklen) 266 while (tagstackidx < tagstacklen)
242 vim_free(tagstack[--tagstacklen].tagname); 267 tagstack_clear_entry(&tagstack[--tagstacklen]);
243 268
244 /* if the tagstack is full: remove oldest entry */ 269 /* if the tagstack is full: remove oldest entry */
245 if (++tagstacklen > TAGSTACKSIZE) 270 if (++tagstacklen > TAGSTACKSIZE)
246 { 271 {
247 tagstacklen = TAGSTACKSIZE; 272 tagstacklen = TAGSTACKSIZE;
248 vim_free(tagstack[0].tagname); 273 tagstack_clear_entry(&tagstack[0]);
249 for (i = 1; i < tagstacklen; ++i) 274 for (i = 1; i < tagstacklen; ++i)
250 tagstack[i - 1] = tagstack[i]; 275 tagstack[i - 1] = tagstack[i];
251 --tagstackidx; 276 --tagstackidx;
252 } 277 }
253 278
527 if (type == DT_CSCOPE) 552 if (type == DT_CSCOPE)
528 flags = TAG_CSCOPE; 553 flags = TAG_CSCOPE;
529 #endif 554 #endif
530 if (verbose) 555 if (verbose)
531 flags |= TAG_VERBOSE; 556 flags |= TAG_VERBOSE;
557
558 if (!use_tfu)
559 flags |= TAG_NO_TAGFUNC;
560
532 if (find_tags(name, &new_num_matches, &new_matches, flags, 561 if (find_tags(name, &new_num_matches, &new_matches, flags,
533 max_num_matches, buf_ffname) == OK 562 max_num_matches, buf_ffname) == OK
534 && new_num_matches < max_num_matches) 563 && new_num_matches < max_num_matches)
535 max_num_matches = MAXCOL; /* If less than max_num_matches 564 max_num_matches = MAXCOL; /* If less than max_num_matches
536 found: all matches found. */ 565 found: all matches found. */
645 } 674 }
646 cur_match = num_matches - 1; 675 cur_match = num_matches - 1;
647 } 676 }
648 if (use_tagstack) 677 if (use_tagstack)
649 { 678 {
679 tagptrs_T tagp;
680
650 tagstack[tagstackidx].cur_match = cur_match; 681 tagstack[tagstackidx].cur_match = cur_match;
651 tagstack[tagstackidx].cur_fnum = cur_fnum; 682 tagstack[tagstackidx].cur_fnum = cur_fnum;
683
684 // store user-provided data originating from tagfunc
685 if (use_tfu && parse_match(matches[cur_match], &tagp) == OK
686 && tagp.user_data)
687 {
688 VIM_CLEAR(tagstack[tagstackidx].user_data);
689 tagstack[tagstackidx].user_data = vim_strnsave(
690 tagp.user_data, tagp.user_data_end - tagp.user_data);
691 }
692
652 ++tagstackidx; 693 ++tagstackidx;
653 } 694 }
654 #if defined(FEAT_QUICKFIX) 695 #if defined(FEAT_QUICKFIX)
655 else if (g_do_tagpreview != 0) 696 else if (g_do_tagpreview != 0)
656 { 697 {
1240 if (has_re) 1281 if (has_re)
1241 pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0); 1282 pats->regmatch.regprog = vim_regcomp(pats->pat, p_magic ? RE_MAGIC : 0);
1242 else 1283 else
1243 pats->regmatch.regprog = NULL; 1284 pats->regmatch.regprog = NULL;
1244 } 1285 }
1286
1287 #ifdef FEAT_EVAL
1288 /*
1289 * Call the user-defined function to generate a list of tags used by
1290 * find_tags().
1291 *
1292 * Return OK if at least 1 tag has been successfully found,
1293 * NOTDONE if the function returns v:null, and FAIL otherwise.
1294 */
1295 static int
1296 find_tagfunc_tags(
1297 char_u *pat, // pattern supplied to the user-defined function
1298 garray_T *ga, // the tags will be placed here
1299 int *match_count, // here the number of tags found will be placed
1300 int flags, // flags from find_tags (TAG_*)
1301 char_u *buf_ffname) // name of buffer for priority
1302 {
1303 pos_T save_pos;
1304 list_T *taglist;
1305 listitem_T *item;
1306 int ntags = 0;
1307 int result = FAIL;
1308 typval_T args[4];
1309 typval_T rettv;
1310 char_u flagString[3];
1311 dict_T *d;
1312 taggy_T *tag = &curwin->w_tagstack[curwin->w_tagstackidx];
1313
1314 if (*curbuf->b_p_tfu == NUL)
1315 return FAIL;
1316
1317 args[0].v_type = VAR_STRING;
1318 args[0].vval.v_string = pat;
1319 args[1].v_type = VAR_STRING;
1320 args[1].vval.v_string = flagString;
1321
1322 // create 'info' dict argument
1323 if ((d = dict_alloc_lock(VAR_FIXED)) == NULL)
1324 return FAIL;
1325 if (tag->user_data != NULL)
1326 dict_add_string(d, "user_data", tag->user_data);
1327 if (buf_ffname != NULL)
1328 dict_add_string(d, "buf_ffname", buf_ffname);
1329
1330 ++d->dv_refcount;
1331 args[2].v_type = VAR_DICT;
1332 args[2].vval.v_dict = d;
1333
1334 args[3].v_type = VAR_UNKNOWN;
1335
1336 vim_snprintf((char *)flagString, sizeof(flagString),
1337 "%s%s",
1338 g_tag_at_cursor ? "c": "",
1339 flags & TAG_INS_COMP ? "i": "");
1340
1341 save_pos = curwin->w_cursor;
1342 result = call_vim_function(curbuf->b_p_tfu, 3, args, &rettv);
1343 curwin->w_cursor = save_pos; // restore the cursor position
1344 --d->dv_refcount;
1345
1346 if (result == FAIL)
1347 return FAIL;
1348 if (rettv.v_type == VAR_SPECIAL && rettv.vval.v_number == VVAL_NULL)
1349 {
1350 clear_tv(&rettv);
1351 return NOTDONE;
1352 }
1353 if (rettv.v_type != VAR_LIST || !rettv.vval.v_list)
1354 {
1355 clear_tv(&rettv);
1356 emsg(_(tfu_inv_ret_msg));
1357 return FAIL;
1358 }
1359 taglist = rettv.vval.v_list;
1360
1361 for (item = taglist->lv_first; item != NULL; item = item->li_next)
1362 {
1363 char_u *mfp;
1364 char_u *res_name, *res_fname, *res_cmd, *res_kind;
1365 int len;
1366 dict_iterator_T iter;
1367 char_u *dict_key;
1368 typval_T *tv;
1369 int has_extra = 0;
1370 int name_only = flags & TAG_NAMES;
1371
1372 if (item->li_tv.v_type != VAR_DICT)
1373 {
1374 emsg(_(tfu_inv_ret_msg));
1375 break;
1376 }
1377
1378 #ifdef FEAT_EMACS_TAGS
1379 len = 3;
1380 #else
1381 len = 2;
1382 #endif
1383 res_name = NULL;
1384 res_fname = NULL;
1385 res_cmd = NULL;
1386 res_kind = NULL;
1387
1388 dict_iterate_start(&item->li_tv, &iter);
1389 while (NULL != (dict_key = dict_iterate_next(&iter, &tv)))
1390 {
1391 if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL)
1392 continue;
1393
1394 len += STRLEN(tv->vval.v_string) + 1; // Space for "\tVALUE"
1395 if (!STRCMP(dict_key, "name"))
1396 {
1397 res_name = tv->vval.v_string;
1398 continue;
1399 }
1400 if (!STRCMP(dict_key, "filename"))
1401 {
1402 res_fname = tv->vval.v_string;
1403 continue;
1404 }
1405 if (!STRCMP(dict_key, "cmd"))
1406 {
1407 res_cmd = tv->vval.v_string;
1408 continue;
1409 }
1410 has_extra = 1;
1411 if (!STRCMP(dict_key, "kind"))
1412 {
1413 res_kind = tv->vval.v_string;
1414 continue;
1415 }
1416 // Other elements will be stored as "\tKEY:VALUE"
1417 // Allocate space for the key and the colon
1418 len += STRLEN(dict_key) + 1;
1419 }
1420
1421 if (has_extra)
1422 len += 2; // need space for ;"
1423
1424 if (!res_name || !res_fname || !res_cmd)
1425 {
1426 emsg(_(tfu_inv_ret_msg));
1427 break;
1428 }
1429
1430 if (name_only)
1431 mfp = vim_strsave(res_name);
1432 else
1433 mfp = (char_u *)alloc((int)sizeof(char_u) + len + 1);
1434
1435 if (mfp == NULL)
1436 continue;
1437
1438 if (!name_only)
1439 {
1440 char_u *p = mfp;
1441
1442 *p++ = MT_GL_OTH + 1; // mtt
1443 *p++ = TAG_SEP; // no tag file name
1444 #ifdef FEAT_EMACS_TAGS
1445 *p++ = TAG_SEP;
1446 #endif
1447
1448 STRCPY(p, res_name);
1449 p += STRLEN(p);
1450
1451 *p++ = TAB;
1452 STRCPY(p, res_fname);
1453 p += STRLEN(p);
1454
1455 *p++ = TAB;
1456 STRCPY(p, res_cmd);
1457 p += STRLEN(p);
1458
1459 if (has_extra)
1460 {
1461 STRCPY(p, ";\"");
1462 p += STRLEN(p);
1463
1464 if (res_kind)
1465 {
1466 *p++ = TAB;
1467 STRCPY(p, res_kind);
1468 p += STRLEN(p);
1469 }
1470
1471 dict_iterate_start(&item->li_tv, &iter);
1472 while (NULL != (dict_key = dict_iterate_next(&iter, &tv)))
1473 {
1474 if (tv->v_type != VAR_STRING || tv->vval.v_string == NULL)
1475 continue;
1476
1477 if (!STRCMP(dict_key, "name"))
1478 continue;
1479 if (!STRCMP(dict_key, "filename"))
1480 continue;
1481 if (!STRCMP(dict_key, "cmd"))
1482 continue;
1483 if (!STRCMP(dict_key, "kind"))
1484 continue;
1485
1486 *p++ = TAB;
1487 STRCPY(p, dict_key);
1488 p += STRLEN(p);
1489 STRCPY(p, ":");
1490 p += STRLEN(p);
1491 STRCPY(p, tv->vval.v_string);
1492 p += STRLEN(p);
1493 }
1494 }
1495 }
1496
1497 // Add all matches because tagfunc should do filtering.
1498 if (ga_grow(ga, 1) == OK)
1499 {
1500 ((char_u **)(ga->ga_data))[ga->ga_len++] = mfp;
1501 ++ntags;
1502 result = OK;
1503 }
1504 else
1505 {
1506 vim_free(mfp);
1507 break;
1508 }
1509 }
1510
1511 clear_tv(&rettv);
1512
1513 *match_count = ntags;
1514 return result;
1515 }
1516 #endif
1245 1517
1246 /* 1518 /*
1247 * find_tags() - search for tags in tags files 1519 * find_tags() - search for tags in tags files
1248 * 1520 *
1249 * Return FAIL if search completely failed (*num_matches will be 0, *matchesp 1521 * Return FAIL if search completely failed (*num_matches will be 0, *matchesp
1266 * TAG_NAMES only return name of tag 1538 * TAG_NAMES only return name of tag
1267 * TAG_REGEXP use "pat" as a regexp 1539 * TAG_REGEXP use "pat" as a regexp
1268 * TAG_NOIC don't always ignore case 1540 * TAG_NOIC don't always ignore case
1269 * TAG_KEEP_LANG keep language 1541 * TAG_KEEP_LANG keep language
1270 * TAG_CSCOPE use cscope results for tags 1542 * TAG_CSCOPE use cscope results for tags
1543 * TAG_NO_TAGFUNC do not call the 'tagfunc' function
1271 */ 1544 */
1272 int 1545 int
1273 find_tags( 1546 find_tags(
1274 char_u *pat, /* pattern to search for */ 1547 char_u *pat, /* pattern to search for */
1275 int *num_matches, /* return: number of matches found */ 1548 int *num_matches, /* return: number of matches found */
1383 int get_it_again = FALSE; 1656 int get_it_again = FALSE;
1384 #ifdef FEAT_CSCOPE 1657 #ifdef FEAT_CSCOPE
1385 int use_cscope = (flags & TAG_CSCOPE); 1658 int use_cscope = (flags & TAG_CSCOPE);
1386 #endif 1659 #endif
1387 int verbose = (flags & TAG_VERBOSE); 1660 int verbose = (flags & TAG_VERBOSE);
1661 #ifdef FEAT_EVAL
1662 int use_tfu = ((flags & TAG_NO_TAGFUNC) == 0);
1663 #endif
1388 int save_p_ic = p_ic; 1664 int save_p_ic = p_ic;
1389 1665
1390 /* 1666 /*
1391 * Change the value of 'ignorecase' according to 'tagcase' for the 1667 * Change the value of 'ignorecase' according to 'tagcase' for the
1392 * duration of this function. 1668 * duration of this function.
1476 1752
1477 #ifdef FEAT_TAG_BINS 1753 #ifdef FEAT_TAG_BINS
1478 /* This is only to avoid a compiler warning for using search_info 1754 /* This is only to avoid a compiler warning for using search_info
1479 * uninitialised. */ 1755 * uninitialised. */
1480 vim_memset(&search_info, 0, (size_t)1); 1756 vim_memset(&search_info, 0, (size_t)1);
1757 #endif
1758
1759 #ifdef FEAT_EVAL
1760 if (*curbuf->b_p_tfu != NUL && use_tfu && !tfu_in_use)
1761 {
1762 tfu_in_use = TRUE;
1763 retval = find_tagfunc_tags(pat, &ga_match[0], &match_count,
1764 flags, buf_ffname);
1765 tfu_in_use = FALSE;
1766 if (retval != NOTDONE)
1767 goto findtag_end;
1768 }
1481 #endif 1769 #endif
1482 1770
1483 /* 1771 /*
1484 * When finding a specified number of matches, first try with matching 1772 * When finding a specified number of matches, first try with matching
1485 * case, so binary search can be used, and try ignore-case matches in a 1773 * case, so binary search can be used, and try ignore-case matches in a
2306 get_it_again = p_sft; 2594 get_it_again = p_sft;
2307 } 2595 }
2308 } 2596 }
2309 else 2597 else
2310 { 2598 {
2311 #define TAG_SEP 0x02
2312 size_t tag_fname_len = STRLEN(tag_fname); 2599 size_t tag_fname_len = STRLEN(tag_fname);
2313 #ifdef FEAT_EMACS_TAGS 2600 #ifdef FEAT_EMACS_TAGS
2314 size_t ebuf_len = 0; 2601 size_t ebuf_len = 0;
2315 #endif 2602 #endif
2316 2603
2575 ga_clear_strings(&tag_fnames); 2862 ga_clear_strings(&tag_fnames);
2576 do_tag(NULL, DT_FREE, 0, 0, 0); 2863 do_tag(NULL, DT_FREE, 0, 0, 0);
2577 tag_freematch(); 2864 tag_freematch();
2578 2865
2579 # if defined(FEAT_QUICKFIX) 2866 # if defined(FEAT_QUICKFIX)
2580 if (ptag_entry.tagname) 2867 tagstack_clear_entry(&ptag_entry);
2581 VIM_CLEAR(ptag_entry.tagname);
2582 # endif 2868 # endif
2583 } 2869 }
2584 #endif 2870 #endif
2585 2871
2586 /* 2872 /*
2938 tagp->is_etag, 3224 tagp->is_etag,
2939 #endif 3225 #endif
2940 tagp); 3226 tagp);
2941 3227
2942 tagp->tagkind = NULL; 3228 tagp->tagkind = NULL;
3229 tagp->user_data = NULL;
2943 tagp->command_end = NULL; 3230 tagp->command_end = NULL;
2944 3231
2945 if (retval == OK) 3232 if (retval == OK)
2946 { 3233 {
2947 /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/ 3234 /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/
2955 p += 2; /* skip ";\"" */ 3242 p += 2; /* skip ";\"" */
2956 if (*p++ == TAB) 3243 if (*p++ == TAB)
2957 while (ASCII_ISALPHA(*p)) 3244 while (ASCII_ISALPHA(*p))
2958 { 3245 {
2959 if (STRNCMP(p, "kind:", 5) == 0) 3246 if (STRNCMP(p, "kind:", 5) == 0)
2960 {
2961 tagp->tagkind = p + 5; 3247 tagp->tagkind = p + 5;
3248 else if (STRNCMP(p, "user_data:", 10) == 0)
3249 tagp->user_data = p + 10;
3250 if (tagp->tagkind != NULL && tagp->user_data != NULL)
2962 break; 3251 break;
2963 }
2964 pc = vim_strchr(p, ':'); 3252 pc = vim_strchr(p, ':');
2965 pt = vim_strchr(p, '\t'); 3253 pt = vim_strchr(p, '\t');
2966 if (pc == NULL || (pt != NULL && pc > pt)) 3254 if (pc == NULL || (pt != NULL && pc > pt))
2967 {
2968 tagp->tagkind = p; 3255 tagp->tagkind = p;
2969 break;
2970 }
2971 if (pt == NULL) 3256 if (pt == NULL)
2972 break; 3257 break;
2973 p = pt + 1; 3258 p = pt + 1;
2974 } 3259 }
2975 } 3260 }
2977 { 3262 {
2978 for (p = tagp->tagkind; 3263 for (p = tagp->tagkind;
2979 *p && *p != '\t' && *p != '\r' && *p != '\n'; ++p) 3264 *p && *p != '\t' && *p != '\r' && *p != '\n'; ++p)
2980 ; 3265 ;
2981 tagp->tagkind_end = p; 3266 tagp->tagkind_end = p;
3267 }
3268 if (tagp->user_data != NULL)
3269 {
3270 for (p = tagp->user_data;
3271 *p && *p != '\t' && *p != '\r' && *p != '\n'; ++p)
3272 ;
3273 tagp->user_data_end = p;
2982 } 3274 }
2983 } 3275 }
2984 return retval; 3276 return retval;
2985 } 3277 }
2986 3278
3545 return OK; 3837 return OK;
3546 } 3838 }
3547 return FAIL; 3839 return FAIL;
3548 } 3840 }
3549 3841
3842 /*
3843 * Free a single entry in a tag stack
3844 */
3845 static void
3846 tagstack_clear_entry(taggy_T *item)
3847 {
3848 VIM_CLEAR(item->tagname);
3849 VIM_CLEAR(item->user_data);
3850 }
3851
3550 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 3852 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
3551 int 3853 int
3552 expand_tags( 3854 expand_tags(
3553 int tagnames, /* expand tag names */ 3855 int tagnames, /* expand tag names */
3554 char_u *pat, 3856 char_u *pat,
3566 tagnmflag = TAG_NAMES; 3868 tagnmflag = TAG_NAMES;
3567 else 3869 else
3568 tagnmflag = 0; 3870 tagnmflag = 0;
3569 if (pat[0] == '/') 3871 if (pat[0] == '/')
3570 ret = find_tags(pat + 1, num_file, file, 3872 ret = find_tags(pat + 1, num_file, file,
3571 TAG_REGEXP | tagnmflag | TAG_VERBOSE, 3873 TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC,
3572 TAG_MANY, curbuf->b_ffname); 3874 TAG_MANY, curbuf->b_ffname);
3573 else 3875 else
3574 ret = find_tags(pat, num_file, file, 3876 ret = find_tags(pat, num_file, file,
3575 TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NOIC, 3877 TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
3576 TAG_MANY, curbuf->b_ffname); 3878 TAG_MANY, curbuf->b_ffname);
3577 if (ret == OK && !tagnames) 3879 if (ret == OK && !tagnames)
3578 { 3880 {
3579 /* Reorganize the tags for display and matching as strings of: 3881 /* Reorganize the tags for display and matching as strings of:
3580 * "<tagname>\0<kind>\0<filename>\0" 3882 * "<tagname>\0<kind>\0<filename>\0"
3751 fmark_T *fmark; 4053 fmark_T *fmark;
3752 4054
3753 dict_add_string(retdict, "tagname", tag->tagname); 4055 dict_add_string(retdict, "tagname", tag->tagname);
3754 dict_add_number(retdict, "matchnr", tag->cur_match + 1); 4056 dict_add_number(retdict, "matchnr", tag->cur_match + 1);
3755 dict_add_number(retdict, "bufnr", tag->cur_fnum); 4057 dict_add_number(retdict, "bufnr", tag->cur_fnum);
4058 if (tag->user_data)
4059 dict_add_string(retdict, "user_data", tag->user_data);
3756 4060
3757 if ((pos = list_alloc_id(aid_tagstack_from)) == NULL) 4061 if ((pos = list_alloc_id(aid_tagstack_from)) == NULL)
3758 return; 4062 return;
3759 dict_add_list(retdict, "from", pos); 4063 dict_add_list(retdict, "from", pos);
3760 4064
3803 { 4107 {
3804 int i; 4108 int i;
3805 4109
3806 // Free the current tag stack 4110 // Free the current tag stack
3807 for (i = 0; i < wp->w_tagstacklen; ++i) 4111 for (i = 0; i < wp->w_tagstacklen; ++i)
3808 vim_free(wp->w_tagstack[i].tagname); 4112 tagstack_clear_entry(&wp->w_tagstack[i]);
3809 wp->w_tagstacklen = 0; 4113 wp->w_tagstacklen = 0;
3810 wp->w_tagstackidx = 0; 4114 wp->w_tagstackidx = 0;
3811 } 4115 }
3812 4116
3813 /* 4117 /*
3818 tagstack_shift(win_T *wp) 4122 tagstack_shift(win_T *wp)
3819 { 4123 {
3820 taggy_T *tagstack = wp->w_tagstack; 4124 taggy_T *tagstack = wp->w_tagstack;
3821 int i; 4125 int i;
3822 4126
3823 vim_free(tagstack[0].tagname); 4127 tagstack_clear_entry(&tagstack[0]);
3824 for (i = 1; i < wp->w_tagstacklen; ++i) 4128 for (i = 1; i < wp->w_tagstacklen; ++i)
3825 tagstack[i - 1] = tagstack[i]; 4129 tagstack[i - 1] = tagstack[i];
3826 wp->w_tagstacklen--; 4130 wp->w_tagstacklen--;
3827 } 4131 }
3828 4132
3834 win_T *wp, 4138 win_T *wp,
3835 char_u *tagname, 4139 char_u *tagname,
3836 int cur_fnum, 4140 int cur_fnum,
3837 int cur_match, 4141 int cur_match,
3838 pos_T mark, 4142 pos_T mark,
3839 int fnum) 4143 int fnum,
4144 char_u *user_data)
3840 { 4145 {
3841 taggy_T *tagstack = wp->w_tagstack; 4146 taggy_T *tagstack = wp->w_tagstack;
3842 int idx = wp->w_tagstacklen; // top of the stack 4147 int idx = wp->w_tagstacklen; // top of the stack
3843 4148
3844 // if the tagstack is full: remove the oldest entry 4149 // if the tagstack is full: remove the oldest entry
3854 tagstack[idx].cur_match = cur_match; 4159 tagstack[idx].cur_match = cur_match;
3855 if (tagstack[idx].cur_match < 0) 4160 if (tagstack[idx].cur_match < 0)
3856 tagstack[idx].cur_match = 0; 4161 tagstack[idx].cur_match = 0;
3857 tagstack[idx].fmark.mark = mark; 4162 tagstack[idx].fmark.mark = mark;
3858 tagstack[idx].fmark.fnum = fnum; 4163 tagstack[idx].fmark.fnum = fnum;
4164 tagstack[idx].user_data = user_data;
3859 } 4165 }
3860 4166
3861 /* 4167 /*
3862 * Add a list of items to the tag stack in the specified window 4168 * Add a list of items to the tag stack in the specified window
3863 */ 4169 */
3890 if (mark.col > 0) 4196 if (mark.col > 0)
3891 mark.col--; 4197 mark.col--;
3892 tagstack_push_item(wp, tagname, 4198 tagstack_push_item(wp, tagname,
3893 (int)dict_get_number(itemdict, (char_u *)"bufnr"), 4199 (int)dict_get_number(itemdict, (char_u *)"bufnr"),
3894 (int)dict_get_number(itemdict, (char_u *)"matchnr") - 1, 4200 (int)dict_get_number(itemdict, (char_u *)"matchnr") - 1,
3895 mark, fnum); 4201 mark, fnum,
4202 dict_get_string(itemdict, (char_u *)"user_data", TRUE));
3896 } 4203 }
3897 } 4204 }
3898 4205
3899 /* 4206 /*
3900 * Set the current index in the tag stack. Valid values are between 0 4207 * Set the current index in the tag stack. Valid values are between 0
3918 set_tagstack(win_T *wp, dict_T *d, int action) 4225 set_tagstack(win_T *wp, dict_T *d, int action)
3919 { 4226 {
3920 dictitem_T *di; 4227 dictitem_T *di;
3921 list_T *l; 4228 list_T *l;
3922 4229
4230 #ifdef FEAT_EVAL
4231 // not allowed to alter the tag stack entries from inside tagfunc
4232 if (tfu_in_use)
4233 {
4234 emsg(_(recurmsg));
4235 return FAIL;
4236 }
4237 #endif
4238
3923 if ((di = dict_find(d, (char_u *)"items", -1)) != NULL) 4239 if ((di = dict_find(d, (char_u *)"items", -1)) != NULL)
3924 { 4240 {
3925 if (di->di_tv.v_type != VAR_LIST) 4241 if (di->di_tv.v_type != VAR_LIST)
3926 { 4242 {
3927 emsg(_(e_listreq)); 4243 emsg(_(e_listreq));