summaryrefslogtreecommitdiff
path: root/src/quickfix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickfix.c')
-rw-r--r--src/quickfix.c217
1 files changed, 143 insertions, 74 deletions
diff --git a/src/quickfix.c b/src/quickfix.c
index d46578701..5847ae19d 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -88,7 +88,7 @@ struct eformat
/* '-' do not include this line */
};
-static int qf_init_ext __ARGS((char_u *efile, buf_T *buf, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast));
+static int qf_init_ext __ARGS((char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast));
static void qf_new_list __ARGS((void));
static int qf_add_entry __ARGS((qfline_T **prevp, char_u *dir, char_u *fname, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid));
static void qf_msg __ARGS((void));
@@ -124,7 +124,7 @@ qf_init(efile, errorformat, newlist)
{
if (efile == NULL)
return FAIL;
- return qf_init_ext(efile, curbuf, errorformat, newlist,
+ return qf_init_ext(efile, curbuf, NULL, errorformat, newlist,
(linenr_T)0, (linenr_T)0);
}
@@ -137,9 +137,10 @@ qf_init(efile, errorformat, newlist)
* Return -1 for error, number of errors for success.
*/
static int
-qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast)
+qf_init_ext(efile, buf, tv, errorformat, newlist, lnumfirst, lnumlast)
char_u *efile;
buf_T *buf;
+ typval_T *tv;
char_u *errorformat;
int newlist; /* TRUE: start a new error list */
linenr_T lnumfirst; /* first line number to use */
@@ -176,6 +177,8 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast)
char_u *directory = NULL;
char_u *currfile = NULL;
char_u *tail = NULL;
+ char_u *p_str = NULL;
+ listitem_T *p_li = NULL;
struct dir_stack_T *file_stack = NULL;
regmatch_T regmatch;
static struct fmtpattern
@@ -222,7 +225,7 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast)
* regex prog. Only a few % characters are allowed.
*/
/* Use the local value of 'errorformat' if it's set. */
- if (errorformat == p_efm && *buf->b_p_efm != NUL)
+ if (errorformat == p_efm && tv == NULL && *buf->b_p_efm != NUL)
efm = buf->b_p_efm;
else
efm = errorformat;
@@ -432,6 +435,14 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast)
/* Always ignore case when looking for a matching error. */
regmatch.rm_ic = TRUE;
+ if (tv != NULL)
+ {
+ if (tv->v_type == VAR_STRING)
+ p_str = tv->vval.v_string;
+ else if (tv->v_type == VAR_LIST)
+ p_li = tv->vval.v_list->lv_first;
+ }
+
/*
* Read the lines in the error file one by one.
* Try to recognize one of the error formats in each line.
@@ -441,10 +452,57 @@ qf_init_ext(efile, buf, errorformat, newlist, lnumfirst, lnumlast)
/* Get the next line. */
if (fd == NULL)
{
- if (buflnum > lnumlast)
- break;
- vim_strncpy(IObuff, ml_get_buf(buf, buflnum++, FALSE),
- CMDBUFFSIZE - 2);
+ if (tv != NULL)
+ {
+ int len;
+
+ if (tv->v_type == VAR_STRING)
+ {
+ /* Get the next line from the supplied string */
+ char_u *p;
+
+ if (!*p_str) /* Reached the end of the string */
+ break;
+
+ p = vim_strchr(p_str, '\n');
+ if (p)
+ len = p - p_str + 1;
+ else
+ len = STRLEN(p_str);
+
+ if (len > CMDBUFFSIZE - 2)
+ vim_strncpy(IObuff, p_str, CMDBUFFSIZE - 2);
+ else
+ vim_strncpy(IObuff, p_str, len);
+
+ p_str += len;
+ }
+ else if (tv->v_type == VAR_LIST)
+ {
+ /* Get the next line from the supplied list */
+ while (p_li && p_li->li_tv.v_type != VAR_STRING)
+ p_li = p_li->li_next; /* Skip non-string items */
+
+ if (!p_li) /* End of the list */
+ break;
+
+ len = STRLEN(p_li->li_tv.vval.v_string);
+ if (len > CMDBUFFSIZE - 2)
+ len = CMDBUFFSIZE - 2;
+
+ vim_strncpy(IObuff, p_li->li_tv.vval.v_string, len);
+
+ p_li = p_li->li_next; /* next item */
+ }
+ }
+ else
+ {
+ /* Get the next line from the supplied buffer */
+ if (buflnum > lnumlast)
+ break;
+ vim_strncpy(IObuff, ml_get_buf(buf, buflnum++, FALSE),
+ CMDBUFFSIZE - 2);
+ }
}
else if (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) == NULL)
break;
@@ -1446,7 +1504,6 @@ qf_list(eap)
int idx1 = 1;
int idx2 = -1;
int need_return = TRUE;
- int last_printed = 1;
char_u *arg = eap->arg;
int all = eap->forceit; /* if not :cl!, only show
recognised errors */
@@ -1467,7 +1524,6 @@ qf_list(eap)
if (idx2 < 0)
idx2 = (-idx2 > i) ? 0 : idx2 + i + 1;
- more_back_used = TRUE;
if (qf_lists[qf_curlist].qf_nonevalid)
all = TRUE;
qfp = qf_lists[qf_curlist].qf_start;
@@ -1478,79 +1534,59 @@ qf_list(eap)
if (need_return)
{
msg_putchar('\n');
+ if (got_int)
+ break;
need_return = FALSE;
}
- if (more_back == 0)
- {
- fname = NULL;
- if (qfp->qf_fnum != 0
+
+ fname = NULL;
+ if (qfp->qf_fnum != 0
&& (buf = buflist_findnr(qfp->qf_fnum)) != NULL)
- {
- fname = buf->b_fname;
- if (qfp->qf_type == 1) /* :helpgrep */
- fname = gettail(fname);
- }
- if (fname == NULL)
- sprintf((char *)IObuff, "%2d", i);
- else
- vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
+ {
+ fname = buf->b_fname;
+ if (qfp->qf_type == 1) /* :helpgrep */
+ fname = gettail(fname);
+ }
+ if (fname == NULL)
+ sprintf((char *)IObuff, "%2d", i);
+ else
+ vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
i, (char *)fname);
- msg_outtrans_attr(IObuff, i == qf_lists[qf_curlist].qf_index
- ? hl_attr(HLF_L) : hl_attr(HLF_D));
- if (qfp->qf_lnum == 0)
- IObuff[0] = NUL;
- else if (qfp->qf_col == 0)
- sprintf((char *)IObuff, ":%ld", qfp->qf_lnum);
- else
- sprintf((char *)IObuff, ":%ld col %d",
+ msg_outtrans_attr(IObuff, i == qf_lists[qf_curlist].qf_index
+ ? hl_attr(HLF_L) : hl_attr(HLF_D));
+ if (qfp->qf_lnum == 0)
+ IObuff[0] = NUL;
+ else if (qfp->qf_col == 0)
+ sprintf((char *)IObuff, ":%ld", qfp->qf_lnum);
+ else
+ sprintf((char *)IObuff, ":%ld col %d",
qfp->qf_lnum, qfp->qf_col);
- sprintf((char *)IObuff + STRLEN(IObuff), "%s:",
+ sprintf((char *)IObuff + STRLEN(IObuff), "%s:",
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
- msg_puts_attr(IObuff, hl_attr(HLF_N));
- if (qfp->qf_pattern != NULL)
- {
- qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
- STRCAT(IObuff, ":");
- msg_puts(IObuff);
- }
- msg_puts((char_u *)" ");
+ msg_puts_attr(IObuff, hl_attr(HLF_N));
+ if (qfp->qf_pattern != NULL)
+ {
+ qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
+ STRCAT(IObuff, ":");
+ msg_puts(IObuff);
+ }
+ msg_puts((char_u *)" ");
- /* Remove newlines and leading whitespace from the text.
- * For an unrecognized line keep the indent, the compiler may
- * mark a word with ^^^^. */
- qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
+ /* Remove newlines and leading whitespace from the text. For an
+ * unrecognized line keep the indent, the compiler may mark a word
+ * with ^^^^. */
+ qf_fmt_text((fname != NULL || qfp->qf_lnum != 0)
? skipwhite(qfp->qf_text) : qfp->qf_text,
IObuff, IOSIZE);
- msg_prt_line(IObuff, FALSE);
- out_flush(); /* show one line at a time */
- need_return = TRUE;
- last_printed = i;
- }
- }
- if (more_back)
- {
- /* scrolling backwards from the more-prompt */
- /* TODO: compute the number of items from the screen lines */
- more_back = more_back * 2 - 1;
- while (i > last_printed - more_back && i > idx1)
- {
- do
- {
- qfp = qfp->qf_prev;
- --i;
- }
- while (i > idx1 && !qfp->qf_valid && !all);
- }
- more_back = 0;
- }
- else
- {
- qfp = qfp->qf_next;
- ++i;
+ msg_prt_line(IObuff, FALSE);
+ out_flush(); /* show one line at a time */
+ need_return = TRUE;
}
+
+ qfp = qfp->qf_next;
+ ++i;
ui_breakcheck();
}
- more_back_used = FALSE;
}
/*
@@ -2330,7 +2366,7 @@ ex_cnext(eap)
}
/*
- * ":cfile" command.
+ * ":cfile"/":cgetfile"/":caddfile" commands.
*/
void
ex_cfile(eap)
@@ -2338,7 +2374,19 @@ ex_cfile(eap)
{
if (*eap->arg != NUL)
set_string_option_direct((char_u *)"ef", -1, eap->arg, OPT_FREE);
- if (qf_init(p_ef, p_efm, TRUE) > 0 && eap->cmdidx == CMD_cfile)
+
+ /*
+ * This function is used by the :cfile, :cgetfile and :caddfile
+ * commands.
+ * :cfile always creates a new quickfix list and jumps to the
+ * first error.
+ * :cgetfile creates a new quickfix list but doesn't jump to the
+ * first error.
+ * :caddfile adds to an existing quickfix list. If there is no
+ * quickfix list then a new list is created.
+ */
+ if (qf_init(p_ef, p_efm, eap->cmdidx != CMD_caddfile) > 0
+ && eap->cmdidx == CMD_cfile)
qf_jump(0, 0, eap->forceit); /* display first error */
}
@@ -2917,11 +2965,32 @@ ex_cbuffer(eap)
|| eap->line2 < 1 || eap->line2 > buf->b_ml.ml_line_count)
EMSG(_(e_invrange));
else
- qf_init_ext(NULL, buf, p_efm, TRUE, eap->line1, eap->line2);
+ qf_init_ext(NULL, buf, NULL, p_efm, TRUE, eap->line1, eap->line2);
}
}
/*
+ * ":cexpr {expr}" command.
+ */
+ void
+ex_cexpr(eap)
+ exarg_T *eap;
+{
+ typval_T *tv;
+
+ tv = eval_expr(eap->arg, NULL);
+ if (!tv || (tv->v_type != VAR_STRING && tv->v_type != VAR_LIST) ||
+ (tv->v_type == VAR_STRING && !tv->vval.v_string) ||
+ (tv->v_type == VAR_LIST && !tv->vval.v_list))
+ return;
+
+ if (qf_init_ext(NULL, NULL, tv, p_efm, TRUE, (linenr_T)0, (linenr_T)0) > 0)
+ qf_jump(0, 0, eap->forceit); /* display first error */
+
+ clear_tv(tv);
+}
+
+/*
* ":helpgrep {pattern}"
*/
void