Mercurial > vim
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)); |