aboutsummaryrefslogtreecommitdiff
path: root/src/nvim
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2019-10-22 20:27:35 -0700
committerGitHub <noreply@github.com>2019-10-22 20:27:35 -0700
commit9e4db2ef508b02583c7f30d12c045ccc07328f16 (patch)
tree1f239179a6cf53520290949ae9ac30be537b133c /src/nvim
parent02393a0c74d3aaeece939bafa4f658763acca965 (diff)
parent3b6b528ea98ca7bf8cd5ae1cf103203e3ca67814 (diff)
downloadrneovim-9e4db2ef508b02583c7f30d12c045ccc07328f16.tar.gz
rneovim-9e4db2ef508b02583c7f30d12c045ccc07328f16.tar.bz2
rneovim-9e4db2ef508b02583c7f30d12c045ccc07328f16.zip
Merge #11199 from bobrippling/vim-8.1.1228
vim-patch:8.1.{1099,1228,1962} add 'tagfunc'
Diffstat (limited to 'src/nvim')
-rw-r--r--src/nvim/buffer.c1
-rw-r--r--src/nvim/buffer_defs.h10
-rw-r--r--src/nvim/edit.c2
-rw-r--r--src/nvim/ex_cmds.c2
-rw-r--r--src/nvim/globals.h6
-rw-r--r--src/nvim/hashtab.h2
-rw-r--r--src/nvim/normal.c2
-rw-r--r--src/nvim/option.c5
-rw-r--r--src/nvim/option_defs.h1
-rw-r--r--src/nvim/options.lua8
-rw-r--r--src/nvim/tag.c1186
-rw-r--r--src/nvim/tag.h27
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_tagfunc.vim84
-rw-r--r--src/nvim/window.c20
15 files changed, 913 insertions, 444 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index b81ffd09e1..1d5aa8ba9b 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1947,6 +1947,7 @@ void free_buf_options(buf_T *buf, int free_p_ff)
clear_string_option(&buf->b_p_path);
clear_string_option(&buf->b_p_tags);
clear_string_option(&buf->b_p_tc);
+ clear_string_option(&buf->b_p_tfu);
clear_string_option(&buf->b_p_dict);
clear_string_option(&buf->b_p_tsr);
clear_string_option(&buf->b_p_qe);
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index 16c7804be0..ca740dea21 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -119,10 +119,11 @@ typedef uint16_t disptick_T; // display tick type
* The taggy struct is used to store the information about a :tag command.
*/
typedef struct taggy {
- char_u *tagname; /* tag name */
- fmark_T fmark; /* cursor position BEFORE ":tag" */
- int cur_match; /* match number */
- int cur_fnum; /* buffer number used for cur_match */
+ char_u *tagname; // tag name
+ fmark_T fmark; // cursor position BEFORE ":tag"
+ int cur_match; // match number
+ int cur_fnum; // buffer number used for cur_match
+ char_u *user_data; // used with tagfunc
} taggy_T;
typedef struct buffblock buffblock_T;
@@ -647,6 +648,7 @@ struct file_buffer {
char_u *b_p_cpt; ///< 'complete'
char_u *b_p_cfu; ///< 'completefunc'
char_u *b_p_ofu; ///< 'omnifunc'
+ char_u *b_p_tfu; ///< 'tagfunc'
int b_p_eol; ///< 'endofline'
int b_p_fixeol; ///< 'fixendofline'
int b_p_et; ///< 'expandtab'
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 49cf090962..62e4f77e6e 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -4047,12 +4047,14 @@ static int ins_compl_get_exp(pos_T *ini)
// Find up to TAG_MANY matches. Avoids that an enormous number
// of matches is found when compl_pattern is empty
+ g_tag_at_cursor = true;
if (find_tags(compl_pattern, &num_matches, &matches,
TAG_REGEXP | TAG_NAMES | TAG_NOIC | TAG_INS_COMP
| (l_ctrl_x_mode != CTRL_X_NORMAL ? TAG_VERBOSE : 0),
TAG_MANY, curbuf->b_ffname) == OK && num_matches > 0) {
ins_compl_add_matches(num_matches, matches, p_ic);
}
+ g_tag_at_cursor = false;
p_ic = save_p_ic;
break;
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 00de7a3d66..2e8bd79c81 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -4905,7 +4905,7 @@ int find_help_tags(const char_u *arg, int *num_matches, char_u ***matches,
*matches = NULL;
*num_matches = 0;
- int flags = TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE;
+ int flags = TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE | TAG_NO_TAGFUNC;
if (keep_lang) {
flags |= TAG_KEEP_LANG;
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 5237c621f9..c3d1a4d40b 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -787,7 +787,11 @@ EXTERN int postponed_split_flags INIT(= 0); /* args for win_split() */
EXTERN int postponed_split_tab INIT(= 0); /* cmdmod.tab */
EXTERN int g_do_tagpreview INIT(= 0); /* for tag preview commands:
height of preview window */
-EXTERN int replace_offset INIT(= 0); /* offset for replace_push() */
+EXTERN int g_tag_at_cursor INIT(= false); // whether the tag command comes
+ // from the command line (0) or was
+ // invoked as a normal command (1)
+
+EXTERN int replace_offset INIT(= 0); // offset for replace_push()
EXTERN char_u *escape_chars INIT(= (char_u *)" \t\\\"|");
/* need backslash in cmd line */
diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h
index a70a8bea63..19633d455f 100644
--- a/src/nvim/hashtab.h
+++ b/src/nvim/hashtab.h
@@ -81,10 +81,10 @@ typedef struct hashtable_S {
size_t hi##todo_ = hi##ht_->ht_used; \
for (hashitem_T *hi = hi##ht_->ht_array; hi##todo_; hi++) { \
if (!HASHITEM_EMPTY(hi)) { \
+ hi##todo_--; \
{ \
code \
} \
- hi##todo_--; \
} \
} \
} while (0)
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index d051ba33b8..f6222f9d3f 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -4938,7 +4938,9 @@ static void nv_ident(cmdarg_T *cap)
add_to_history(HIST_SEARCH, (char_u *)buf, true, NUL);
(void)normal_search(cap, cmdchar == '*' ? '/' : '?', (char_u *)buf, 0);
} else {
+ g_tag_at_cursor = true;
do_cmdline_cmd(buf);
+ g_tag_at_cursor = false;
}
xfree(buf);
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 22f7b85133..20351d3908 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -133,6 +133,7 @@ static char_u *p_cms;
static char_u *p_cpt;
static char_u *p_cfu;
static char_u *p_ofu;
+static char_u *p_tfu;
static int p_eol;
static int p_fixeol;
static int p_et;
@@ -2273,6 +2274,7 @@ void check_buf_options(buf_T *buf)
check_string_option(&buf->b_p_ep);
check_string_option(&buf->b_p_path);
check_string_option(&buf->b_p_tags);
+ check_string_option(&buf->b_p_tfu);
check_string_option(&buf->b_p_tc);
check_string_option(&buf->b_p_dict);
check_string_option(&buf->b_p_tsr);
@@ -5590,6 +5592,7 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
case PV_INC: return (char_u *)&(curbuf->b_p_inc);
case PV_DICT: return (char_u *)&(curbuf->b_p_dict);
case PV_TSR: return (char_u *)&(curbuf->b_p_tsr);
+ case PV_TFU: return (char_u *)&(curbuf->b_p_tfu);
case PV_STL: return (char_u *)&(curwin->w_p_stl);
case PV_UL: return (char_u *)&(curbuf->b_p_ul);
case PV_LW: return (char_u *)&(curbuf->b_p_lw);
@@ -5742,6 +5745,7 @@ static char_u *get_varp(vimoption_T *p)
case PV_SPF: return (char_u *)&(curwin->w_s->b_p_spf);
case PV_SPL: return (char_u *)&(curwin->w_s->b_p_spl);
case PV_SW: return (char_u *)&(curbuf->b_p_sw);
+ case PV_TFU: return (char_u *)&(curbuf->b_p_tfu);
case PV_TS: return (char_u *)&(curbuf->b_p_ts);
case PV_TW: return (char_u *)&(curbuf->b_p_tw);
case PV_UDF: return (char_u *)&(curbuf->b_p_udf);
@@ -6004,6 +6008,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_cpt = vim_strsave(p_cpt);
buf->b_p_cfu = vim_strsave(p_cfu);
buf->b_p_ofu = vim_strsave(p_ofu);
+ buf->b_p_tfu = vim_strsave(p_tfu);
buf->b_p_sts = p_sts;
buf->b_p_sts_nopaste = p_sts_nopaste;
buf->b_p_com = vim_strsave(p_com);
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 67cb53ce02..e5a3c0bd95 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -780,6 +780,7 @@ enum {
, BV_SUA
, BV_SW
, BV_SWF
+ , BV_TFU
, BV_TAGS
, BV_TC
, BV_TS
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index 52e788944b..e96b3f8e02 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2389,6 +2389,14 @@ return {
defaults={if_true={vi=""}}
},
{
+ full_name='tagfunc', abbreviation='tfu',
+ type='string', scope={'buffer'},
+ vim=true,
+ vi_def=true,
+ varname='p_tfu',
+ defaults={if_true={vi=""}}
+ },
+ {
full_name='tabline', abbreviation='tal',
type='string', scope={'global'},
vi_def=true,
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index c8c9677a98..0d42deed2b 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -51,17 +51,20 @@
* Structure to hold pointers to various items in a tag line.
*/
typedef struct tag_pointers {
- /* filled in by parse_tag_line(): */
- char_u *tagname; /* start of tag name (skip "file:") */
- char_u *tagname_end; /* char after tag name */
- char_u *fname; /* first char of file name */
- char_u *fname_end; /* char after file name */
- char_u *command; /* first char of command */
- /* filled in by parse_match(): */
- char_u *command_end; /* first char after command */
- char_u *tag_fname; /* file name of the tags file */
- char_u *tagkind; /* "kind:" value */
- char_u *tagkind_end; /* end of tagkind */
+ // filled in by parse_tag_line():
+ char_u *tagname; // start of tag name (skip "file:")
+ char_u *tagname_end; // char after tag name
+ char_u *fname; // first char of file name
+ char_u *fname_end; // char after file name
+ char_u *command; // first char of command
+ // filled in by parse_match():
+ char_u *command_end; // first char after command
+ char_u *tag_fname; // file name of the tags file. This is used
+ // when 'tr' is set.
+ char_u *tagkind; // "kind:" value
+ char_u *tagkind_end; // end of tagkind
+ char_u *user_data; // user_data string
+ char_u *user_data_end; // end of user_data
} tagptrs_T;
/*
@@ -102,6 +105,10 @@ static char_u *nofile_fname = NULL; /* fname for NOTAGFILE error */
static char_u *bottommsg = (char_u *)N_("E555: at bottom of tag stack");
static char_u *topmsg = (char_u *)N_("E556: at top of tag stack");
+static char_u *recurmsg
+ = (char_u *)N_("E986: cannot modify the tag stack within tagfunc");
+static char_u *tfu_inv_ret_msg
+ = (char_u *)N_("E987: invalid return value from tagfunc");
static char_u *tagmatchname = NULL; /* name of last used tag */
@@ -109,7 +116,12 @@ static char_u *tagmatchname = NULL; /* name of last used tag */
* Tag for preview window is remembered separately, to avoid messing up the
* normal tagstack.
*/
-static taggy_T ptag_entry = { NULL, { { 0, 0, 0 }, 0, 0, NULL }, 0, 0 };
+static taggy_T ptag_entry = { NULL, { { 0, 0, 0 }, 0, 0, NULL }, 0, 0, NULL };
+
+static int tfu_in_use = false; // disallow recursive call of tagfunc
+
+// Used instead of NUL to separate tag fields in the growarrays.
+#define TAG_SEP 0x02
/*
* Jump to tag; handling of tag commands and tag stack
@@ -131,13 +143,13 @@ static taggy_T ptag_entry = { NULL, { { 0, 0, 0 }, 0, 0, NULL }, 0, 0 };
*
* for cscope, returns TRUE if we jumped to tag or aborted, FALSE otherwise
*/
-int
-do_tag (
- char_u *tag, /* tag (pattern) to jump to */
+int
+do_tag(
+ char_u *tag, // tag (pattern) to jump to
int type,
int count,
- int forceit, /* :ta with ! */
- int verbose /* print "tag not found" message */
+ int forceit, // :ta with !
+ int verbose // print "tag not found" message
)
{
taggy_T *tagstack = curwin->w_tagstack;
@@ -148,28 +160,20 @@ do_tag (
int oldtagstackidx = tagstackidx;
int prevtagstackidx = tagstackidx;
int prev_num_matches;
- int new_tag = FALSE;
- int other_name;
- int i, j, k;
- int idx;
+ int new_tag = false;
+ int i;
int ic;
- char_u *p;
- char_u *name;
- int no_regexp = FALSE;
+ int no_regexp = false;
int error_cur_match = 0;
- char_u *command_end;
- int save_pos = FALSE;
+ int save_pos = false;
fmark_T saved_fmark;
- int taglen;
- int jumped_to_tag = FALSE;
- tagptrs_T tagp, tagp2;
+ int jumped_to_tag = false;
int new_num_matches;
char_u **new_matches;
- int attr;
int use_tagstack;
- int skip_msg = FALSE;
- char_u *buf_ffname = curbuf->b_ffname; /* name to use for
- priority computation */
+ int skip_msg = false;
+ char_u *buf_ffname = curbuf->b_ffname; // name for priority computation
+ int use_tfu = 1;
/* remember the matches for the last used tag */
static int num_matches = 0;
@@ -177,19 +181,25 @@ do_tag (
static char_u **matches = NULL;
static int flags;
+ if (tfu_in_use) {
+ EMSG(_(recurmsg));
+ return false;
+ }
+
#ifdef EXITFREE
if (type == DT_FREE) {
/* remove the list of matches */
FreeWild(num_matches, matches);
cs_free_tags();
num_matches = 0;
- return FALSE;
+ return false;
}
#endif
if (type == DT_HELP) {
type = DT_TAG;
- no_regexp = TRUE;
+ no_regexp = true;
+ use_tfu = 0;
}
prev_num_matches = num_matches;
@@ -205,14 +215,15 @@ do_tag (
use_tagstack = false;
new_tag = true;
if (g_do_tagpreview != 0) {
- xfree(ptag_entry.tagname);
+ tagstack_clear_entry(&ptag_entry);
ptag_entry.tagname = vim_strsave(tag);
}
} else {
- if (g_do_tagpreview != 0)
- use_tagstack = FALSE;
- else
- use_tagstack = TRUE;
+ if (g_do_tagpreview != 0) {
+ use_tagstack = false;
+ } else {
+ use_tagstack = true;
+ }
/* new pattern, add to the tag stack */
if (*tag != NUL
@@ -228,7 +239,7 @@ do_tag (
cur_match = ptag_entry.cur_match;
cur_fnum = ptag_entry.cur_fnum;
} else {
- xfree(ptag_entry.tagname);
+ tagstack_clear_entry(&ptag_entry);
ptag_entry.tagname = vim_strsave(tag);
}
} else {
@@ -236,16 +247,18 @@ do_tag (
* If the last used entry is not at the top, delete all tag
* stack entries above it.
*/
- while (tagstackidx < tagstacklen)
- xfree(tagstack[--tagstacklen].tagname);
+ while (tagstackidx < tagstacklen) {
+ tagstack_clear_entry(&tagstack[--tagstacklen]);
+ }
/* if the tagstack is full: remove oldest entry */
if (++tagstacklen > TAGSTACKSIZE) {
tagstacklen = TAGSTACKSIZE;
- xfree(tagstack[0].tagname);
- for (i = 1; i < tagstacklen; ++i)
+ tagstack_clear_entry(&tagstack[0]);
+ for (i = 1; i < tagstacklen; i++) {
tagstack[i - 1] = tagstack[i];
- --tagstackidx;
+ }
+ tagstackidx--;
}
// put the tag name in the tag stack
@@ -253,15 +266,15 @@ do_tag (
curwin->w_tagstacklen = tagstacklen;
- save_pos = TRUE; /* save the cursor position below */
+ save_pos = true; // save the cursor position below
}
- new_tag = TRUE;
+ new_tag = true;
} else {
if (
- g_do_tagpreview != 0 ? ptag_entry.tagname == NULL :
- tagstacklen == 0) {
- /* empty stack */
+ g_do_tagpreview != 0 ? ptag_entry.tagname == NULL :
+ tagstacklen == 0) {
+ // empty stack
EMSG(_(e_tagstack));
goto end_do_tag;
}
@@ -271,7 +284,7 @@ do_tag (
if ((tagstackidx -= count) < 0) {
EMSG(_(bottommsg));
if (tagstackidx + count == 0) {
- /* We did [num]^T from the bottom of the stack */
+ // We did [num]^T from the bottom of the stack
tagstackidx = 0;
goto end_do_tag;
}
@@ -279,7 +292,7 @@ do_tag (
* way to the bottom now.
*/
tagstackidx = 0;
- } else if (tagstackidx >= tagstacklen) { /* count == 0? */
+ } else if (tagstackidx >= tagstacklen) { // count == 0?
EMSG(_(topmsg));
goto end_do_tag;
}
@@ -293,8 +306,8 @@ do_tag (
* file was changed) keep original position in tag stack.
*/
if (buflist_getfile(saved_fmark.fnum, saved_fmark.mark.lnum,
- GETF_SETMARK, forceit) == FAIL) {
- tagstackidx = oldtagstackidx; /* back to old posn */
+ GETF_SETMARK, forceit) == FAIL) {
+ tagstackidx = oldtagstackidx; // back to old posn
goto end_do_tag;
}
/* A BufReadPost autocommand may jump to the '" mark, but
@@ -305,12 +318,12 @@ do_tag (
curwin->w_cursor.lnum = saved_fmark.mark.lnum;
}
curwin->w_cursor.col = saved_fmark.mark.col;
- curwin->w_set_curswant = TRUE;
+ curwin->w_set_curswant = true;
check_cursor();
if ((fdo_flags & FDO_TAG) && old_KeyTyped)
foldOpenCursor();
- /* remove the old list of matches */
+ // remove the old list of matches
FreeWild(num_matches, matches);
cs_free_tags();
num_matches = 0;
@@ -325,8 +338,8 @@ do_tag (
cur_match = ptag_entry.cur_match;
cur_fnum = ptag_entry.cur_fnum;
} else {
- /* ":tag" (no argument): go to newer pattern */
- save_pos = TRUE; /* save the cursor position below */
+ // ":tag" (no argument): go to newer pattern
+ save_pos = true; // save the cursor position below
if ((tagstackidx += count - 1) >= tagstacklen) {
/*
* Beyond the last one, just give an error message and
@@ -335,8 +348,8 @@ do_tag (
*/
tagstackidx = tagstacklen - 1;
EMSG(_(topmsg));
- save_pos = FALSE;
- } else if (tagstackidx < 0) { /* must have been count == 0 */
+ save_pos = false;
+ } else if (tagstackidx < 0) { // must have been count == 0
EMSG(_(bottommsg));
tagstackidx = 0;
goto end_do_tag;
@@ -344,9 +357,9 @@ do_tag (
cur_match = tagstack[tagstackidx].cur_match;
cur_fnum = tagstack[tagstackidx].cur_fnum;
}
- new_tag = TRUE;
- } else { /* go to other matching tag */
- /* Save index for when selection is cancelled. */
+ new_tag = true;
+ } else { // go to other matching tag
+ // Save index for when selection is cancelled.
prevtagstackidx = tagstackidx;
if (g_do_tagpreview != 0) {
@@ -371,7 +384,7 @@ do_tag (
cur_match = MAXCOL - 1;
else if (cur_match < 0) {
EMSG(_("E425: Cannot go before first matching tag"));
- skip_msg = TRUE;
+ skip_msg = true;
cur_match = 0;
cur_fnum = curbuf->b_fnum;
}
@@ -418,15 +431,17 @@ do_tag (
* Repeat searching for tags, when a file has not been found.
*/
for (;; ) {
- /*
- * When desired match not found yet, try to find it (and others).
- */
- if (use_tagstack)
+ int other_name;
+ char_u *name;
+
+ // When desired match not found yet, try to find it (and others).
+ if (use_tagstack) {
name = tagstack[tagstackidx].tagname;
- else if (g_do_tagpreview != 0)
+ } else if (g_do_tagpreview != 0) {
name = ptag_entry.tagname;
- else
+ } else {
name = tag;
+ }
other_name = (tagmatchname == NULL || STRCMP(tagmatchname, name) != 0);
if (new_tag
|| (cur_match >= num_matches && max_num_matches != MAXCOL)
@@ -446,38 +461,49 @@ do_tag (
max_num_matches = cur_match + 1;
}
- /* when the argument starts with '/', use it as a regexp */
+ // when the argument starts with '/', use it as a regexp
if (!no_regexp && *name == '/') {
flags = TAG_REGEXP;
++name;
} else
flags = TAG_NOIC;
- if (type == DT_CSCOPE)
+ if (type == DT_CSCOPE) {
flags = TAG_CSCOPE;
- if (verbose)
+ }
+ if (verbose) {
flags |= TAG_VERBOSE;
+ }
+ if (!use_tfu) {
+ flags |= TAG_NO_TAGFUNC;
+ }
+
if (find_tags(name, &new_num_matches, &new_matches, flags,
- max_num_matches, buf_ffname) == OK
- && new_num_matches < max_num_matches)
- max_num_matches = MAXCOL; /* If less than max_num_matches
- found: all matches found. */
+ max_num_matches, buf_ffname) == OK
+ && new_num_matches < max_num_matches) {
+ max_num_matches = MAXCOL; // If less than max_num_matches
+ // found: all matches found.
+ }
/* If there already were some matches for the same name, move them
* to the start. Avoids that the order changes when using
* ":tnext" and jumping to another file. */
if (!new_tag && !other_name) {
- /* Find the position of each old match in the new list. Need
- * to use parse_match() to find the tag line. */
- idx = 0;
- for (j = 0; j < num_matches; ++j) {
+ int j, k;
+ int idx = 0;
+ tagptrs_T tagp, tagp2;
+
+ // Find the position of each old match in the new list. Need
+ // to use parse_match() to find the tag line.
+ for (j = 0; j < num_matches; j++) {
parse_match(matches[j], &tagp);
for (i = idx; i < new_num_matches; ++i) {
parse_match(new_matches[i], &tagp2);
if (STRCMP(tagp.tagname, tagp2.tagname) == 0) {
- p = new_matches[i];
- for (k = i; k > idx; --k)
+ char_u *p = new_matches[i];
+ for (k = i; k > idx; k--) {
new_matches[k] = new_matches[k - 1];
+ }
new_matches[idx++] = p;
break;
}
@@ -504,304 +530,27 @@ do_tag (
// jump to count'th matching tag.
cur_match = count > 0 ? count - 1 : 0;
} else if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1)) {
- // List all the matching tags.
- // Assume that the first match indicates how long the tags can
- // be, and align the file names to that.
- parse_match(matches[0], &tagp);
- taglen = (int)(tagp.tagname_end - tagp.tagname + 2);
- if (taglen < 18)
- taglen = 18;
- if (taglen > Columns - 25)
- taglen = MAXCOL;
- if (msg_col == 0)
- msg_didout = FALSE; /* overwrite previous message */
- msg_start();
- MSG_PUTS_ATTR(_(" # pri kind tag"), HL_ATTR(HLF_T));
- msg_clr_eos();
- taglen_advance(taglen);
- MSG_PUTS_ATTR(_("file\n"), HL_ATTR(HLF_T));
-
- for (i = 0; i < num_matches && !got_int; i++) {
- parse_match(matches[i], &tagp);
- if (!new_tag && ((g_do_tagpreview != 0 && i == ptag_entry.cur_match)
- || (use_tagstack
- && i == tagstack[tagstackidx].cur_match))) {
- *IObuff = '>';
- } else {
- *IObuff = ' ';
- }
- vim_snprintf((char *)IObuff + 1, IOSIZE - 1, "%2d %s ", i + 1,
- mt_names[matches[i][0] & MT_MASK]);
- msg_puts((const char *)IObuff);
- if (tagp.tagkind != NULL) {
- msg_outtrans_len(tagp.tagkind,
- (int)(tagp.tagkind_end - tagp.tagkind));
- }
- msg_advance(13);
- msg_outtrans_len_attr(tagp.tagname,
- (int)(tagp.tagname_end - tagp.tagname),
- HL_ATTR(HLF_T));
- msg_putchar(' ');
- taglen_advance(taglen);
-
- /* Find out the actual file name. If it is long, truncate
- * it and put "..." in the middle */
- p = tag_full_fname(&tagp);
- msg_puts_long_attr(p, HL_ATTR(HLF_D));
- xfree(p);
-
- if (msg_col > 0)
- msg_putchar('\n');
- if (got_int)
- break;
- msg_advance(15);
-
- /* print any extra fields */
- command_end = tagp.command_end;
- if (command_end != NULL) {
- p = command_end + 3;
- while (*p && *p != '\r' && *p != '\n') {
- while (*p == TAB)
- ++p;
-
- /* skip "file:" without a value (static tag) */
- if (STRNCMP(p, "file:", 5) == 0
- && ascii_isspace(p[5])) {
- p += 5;
- continue;
- }
- /* skip "kind:<kind>" and "<kind>" */
- if (p == tagp.tagkind
- || (p + 5 == tagp.tagkind
- && STRNCMP(p, "kind:", 5) == 0)) {
- p = tagp.tagkind_end;
- continue;
- }
- // print all other extra fields
- attr = HL_ATTR(HLF_CM);
- while (*p && *p != '\r' && *p != '\n') {
- if (msg_col + ptr2cells(p) >= Columns) {
- msg_putchar('\n');
- if (got_int)
- break;
- msg_advance(15);
- }
- p = msg_outtrans_one(p, attr);
- if (*p == TAB) {
- msg_puts_attr(" ", attr);
- break;
- }
- if (*p == ':')
- attr = 0;
- }
- }
- if (msg_col > 15) {
- msg_putchar('\n');
- if (got_int)
- break;
- msg_advance(15);
- }
- } else {
- for (p = tagp.command;
- *p && *p != '\r' && *p != '\n'; ++p)
- ;
- command_end = p;
- }
-
- /*
- * Put the info (in several lines) at column 15.
- * Don't display "/^" and "?^".
- */
- p = tagp.command;
- if (*p == '/' || *p == '?') {
- ++p;
- if (*p == '^')
- ++p;
- }
- /* Remove leading whitespace from pattern */
- while (p != command_end && ascii_isspace(*p))
- ++p;
-
- while (p != command_end) {
- if (msg_col + (*p == TAB ? 1 : ptr2cells(p)) > Columns)
- msg_putchar('\n');
- if (got_int)
- break;
- msg_advance(15);
-
- // Skip backslash used for escaping a command char or a backslash.
- if (*p == '\\' && (*(p + 1) == *tagp.command
- || *(p + 1) == '\\')) {
- ++p;
- }
-
- if (*p == TAB) {
- msg_putchar(' ');
- ++p;
- } else
- p = msg_outtrans_one(p, 0);
-
- /* don't display the "$/;\"" and "$?;\"" */
- if (p == command_end - 2 && *p == '$'
- && *(p + 1) == *tagp.command)
- break;
- /* don't display matching '/' or '?' */
- if (p == command_end - 1 && *p == *tagp.command
- && (*p == '/' || *p == '?'))
- break;
- }
- if (msg_col)
- msg_putchar('\n');
- os_breakcheck();
- }
- if (got_int) {
- got_int = false; // only stop the listing
- }
+ print_tag_list(new_tag, use_tagstack, num_matches, matches);
ask_for_selection = true;
} else if (type == DT_LTAG) {
- list_T *list;
- char_u tag_name[128 + 1];
- char_u *fname;
- char_u *cmd;
-
- /*
- * Add the matching tags to the location list for the current
- * window.
- */
-
- fname = xmalloc(MAXPATHL + 1);
- cmd = xmalloc(CMDBUFFSIZE + 1);
- list = tv_list_alloc(num_matches);
-
- for (i = 0; i < num_matches; ++i) {
- int len, cmd_len;
- long lnum;
- dict_T *dict;
-
- parse_match(matches[i], &tagp);
-
- /* Save the tag name */
- len = (int)(tagp.tagname_end - tagp.tagname);
- if (len > 128)
- len = 128;
- STRLCPY(tag_name, tagp.tagname, len + 1);
-
- /* Save the tag file name */
- p = tag_full_fname(&tagp);
- STRLCPY(fname, p, MAXPATHL + 1);
- xfree(p);
-
- /*
- * Get the line number or the search pattern used to locate
- * the tag.
- */
- lnum = 0;
- if (isdigit(*tagp.command))
- /* Line number is used to locate the tag */
- lnum = atol((char *)tagp.command);
- else {
- char_u *cmd_start, *cmd_end;
-
- /* Search pattern is used to locate the tag */
-
- /* Locate the end of the command */
- cmd_start = tagp.command;
- cmd_end = tagp.command_end;
- if (cmd_end == NULL) {
- for (p = tagp.command;
- *p && *p != '\r' && *p != '\n'; ++p)
- ;
- cmd_end = p;
- }
-
- /*
- * Now, cmd_end points to the character after the
- * command. Adjust it to point to the last
- * character of the command.
- */
- cmd_end--;
-
- /*
- * Skip the '/' and '?' characters at the
- * beginning and end of the search pattern.
- */
- if (*cmd_start == '/' || *cmd_start == '?')
- cmd_start++;
-
- if (*cmd_end == '/' || *cmd_end == '?')
- cmd_end--;
-
- len = 0;
- cmd[0] = NUL;
-
- /*
- * If "^" is present in the tag search pattern, then
- * copy it first.
- */
- if (*cmd_start == '^') {
- STRCPY(cmd, "^");
- cmd_start++;
- len++;
- }
-
- /*
- * Precede the tag pattern with \V to make it very
- * nomagic.
- */
- STRCAT(cmd, "\\V");
- len += 2;
-
- cmd_len = (int)(cmd_end - cmd_start + 1);
- if (cmd_len > (CMDBUFFSIZE - 5))
- cmd_len = CMDBUFFSIZE - 5;
- STRNCAT(cmd, cmd_start, cmd_len);
- len += cmd_len;
-
- if (cmd[len - 1] == '$') {
- /*
- * Replace '$' at the end of the search pattern
- * with '\$'
- */
- cmd[len - 1] = '\\';
- cmd[len] = '$';
- len++;
- }
-
- cmd[len] = NUL;
- }
-
- dict = tv_dict_alloc();
- tv_list_append_dict(list, dict);
-
- tv_dict_add_str(dict, S_LEN("text"), (const char *)tag_name);
- tv_dict_add_str(dict, S_LEN("filename"), (const char *)fname);
- tv_dict_add_nr(dict, S_LEN("lnum"), lnum);