mirror of
https://github.com/neovim/neovim.git
synced 2025-10-07 10:26:31 +00:00
vim-patch:8.1.0252: quickfix functions are too long
Problem: Quickfix functions are too long.
Solution: Refactor. (Yegappan Lakshmanan, closes vim/vim#2950)
de3b3677f7
This commit is contained in:
@@ -163,6 +163,8 @@ enum {
|
|||||||
QF_MULTISCAN = 5,
|
QF_MULTISCAN = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// State information used to parse lines and add entries to a quickfix/location
|
||||||
|
// list.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char_u *linebuf;
|
char_u *linebuf;
|
||||||
size_t linelen;
|
size_t linelen;
|
||||||
@@ -266,92 +268,95 @@ static struct fmtpattern
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Convert an errorformat pattern to a regular expression pattern.
|
// Convert an errorformat pattern to a regular expression pattern.
|
||||||
// See fmt_pat definition above for the list of supported patterns.
|
// See fmt_pat definition above for the list of supported patterns. The
|
||||||
static char_u *fmtpat_to_regpat(
|
// pattern specifier is supplied in "efmpat". The converted pattern is stored
|
||||||
const char_u *efmp,
|
// in "regpat". Returns a pointer to the location after the pattern.
|
||||||
efm_T *fmt_ptr,
|
static char_u * efmpat_to_regpat(
|
||||||
|
const char_u *efmpat,
|
||||||
|
char_u *regpat,
|
||||||
|
efm_T *efminfo,
|
||||||
int idx,
|
int idx,
|
||||||
int round,
|
int round,
|
||||||
char_u *ptr,
|
|
||||||
char_u *errmsg,
|
char_u *errmsg,
|
||||||
size_t errmsglen)
|
size_t errmsglen)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
if (fmt_ptr->addr[idx]) {
|
if (efminfo->addr[idx]) {
|
||||||
// Each errorformat pattern can occur only once
|
// Each errorformat pattern can occur only once
|
||||||
snprintf((char *)errmsg, errmsglen,
|
snprintf((char *)errmsg, errmsglen,
|
||||||
_("E372: Too many %%%c in format string"), *efmp);
|
_("E372: Too many %%%c in format string"), *efmpat);
|
||||||
EMSG(errmsg);
|
EMSG(errmsg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((idx && idx < 6
|
if ((idx && idx < 6
|
||||||
&& vim_strchr((char_u *)"DXOPQ", fmt_ptr->prefix) != NULL)
|
&& vim_strchr((char_u *)"DXOPQ", efminfo->prefix) != NULL)
|
||||||
|| (idx == 6
|
|| (idx == 6
|
||||||
&& vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL)) {
|
&& vim_strchr((char_u *)"OPQ", efminfo->prefix) == NULL)) {
|
||||||
snprintf((char *)errmsg, errmsglen,
|
snprintf((char *)errmsg, errmsglen,
|
||||||
_("E373: Unexpected %%%c in format string"), *efmp);
|
_("E373: Unexpected %%%c in format string"), *efmpat);
|
||||||
EMSG(errmsg);
|
EMSG(errmsg);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
fmt_ptr->addr[idx] = (char_u)++round;
|
efminfo->addr[idx] = (char_u)++round;
|
||||||
*ptr++ = '\\';
|
*regpat++ = '\\';
|
||||||
*ptr++ = '(';
|
*regpat++ = '(';
|
||||||
#ifdef BACKSLASH_IN_FILENAME
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
if (*efmp == 'f') {
|
if (*efmpat == 'f') {
|
||||||
// Also match "c:" in the file name, even when
|
// Also match "c:" in the file name, even when
|
||||||
// checking for a colon next: "%f:".
|
// checking for a colon next: "%f:".
|
||||||
// "\%(\a:\)\="
|
// "\%(\a:\)\="
|
||||||
STRCPY(ptr, "\\%(\\a:\\)\\=");
|
STRCPY(regpat, "\\%(\\a:\\)\\=");
|
||||||
ptr += 10;
|
regpat += 10;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (*efmp == 'f' && efmp[1] != NUL) {
|
if (*efmpat == 'f' && efmpat[1] != NUL) {
|
||||||
if (efmp[1] != '\\' && efmp[1] != '%') {
|
if (efmpat[1] != '\\' && efmpat[1] != '%') {
|
||||||
// A file name may contain spaces, but this isn't
|
// A file name may contain spaces, but this isn't
|
||||||
// in "\f". For "%f:%l:%m" there may be a ":" in
|
// in "\f". For "%f:%l:%m" there may be a ":" in
|
||||||
// the file name. Use ".\{-1,}x" instead (x is
|
// the file name. Use ".\{-1,}x" instead (x is
|
||||||
// the next character), the requirement that :999:
|
// the next character), the requirement that :999:
|
||||||
// follows should work.
|
// follows should work.
|
||||||
STRCPY(ptr, ".\\{-1,}");
|
STRCPY(regpat, ".\\{-1,}");
|
||||||
ptr += 7;
|
regpat += 7;
|
||||||
} else {
|
} else {
|
||||||
// File name followed by '\\' or '%': include as
|
// File name followed by '\\' or '%': include as
|
||||||
// many file name chars as possible.
|
// many file name chars as possible.
|
||||||
STRCPY(ptr, "\\f\\+");
|
STRCPY(regpat, "\\f\\+");
|
||||||
ptr += 4;
|
regpat += 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char_u *srcptr = (char_u *)fmt_pat[idx].pattern;
|
char_u *srcptr = (char_u *)fmt_pat[idx].pattern;
|
||||||
while ((*ptr = *srcptr++) != NUL) {
|
while ((*regpat = *srcptr++) != NUL) {
|
||||||
ptr++;
|
regpat++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ptr++ = '\\';
|
*regpat++ = '\\';
|
||||||
*ptr++ = ')';
|
*regpat++ = ')';
|
||||||
|
|
||||||
return ptr;
|
return regpat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a scanf like format in 'errorformat' to a regular expression.
|
// Convert a scanf like format in 'errorformat' to a regular expression.
|
||||||
static char_u *scanf_fmt_to_regpat(
|
// Returns a pointer to the location after the pattern.
|
||||||
|
static char_u * scanf_fmt_to_regpat(
|
||||||
|
const char_u **pefmp,
|
||||||
const char_u *efm,
|
const char_u *efm,
|
||||||
int len,
|
int len,
|
||||||
const char_u **pefmp,
|
char_u *regpat,
|
||||||
char_u *ptr,
|
|
||||||
char_u *errmsg,
|
char_u *errmsg,
|
||||||
size_t errmsglen)
|
size_t errmsglen)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
const char_u *efmp = *pefmp;
|
const char_u *efmp = *pefmp;
|
||||||
|
|
||||||
if (*++efmp == '[' || *efmp == '\\') {
|
if (*efmp == '[' || *efmp == '\\') {
|
||||||
if ((*ptr++ = *efmp) == '[') { // %*[^a-z0-9] etc.
|
if ((*regpat++ = *efmp) == '[') { // %*[^a-z0-9] etc.
|
||||||
if (efmp[1] == '^') {
|
if (efmp[1] == '^') {
|
||||||
*ptr++ = *++efmp;
|
*regpat++ = *++efmp;
|
||||||
}
|
}
|
||||||
if (efmp < efm + len) {
|
if (efmp < efm + len) {
|
||||||
*ptr++ = *++efmp; // could be ']'
|
*regpat++ = *++efmp; // could be ']'
|
||||||
while (efmp < efm + len && (*ptr++ = *++efmp) != ']') {
|
while (efmp < efm + len && (*regpat++ = *++efmp) != ']') {
|
||||||
}
|
}
|
||||||
if (efmp == efm + len) {
|
if (efmp == efm + len) {
|
||||||
EMSG(_("E374: Missing ] in format string"));
|
EMSG(_("E374: Missing ] in format string"));
|
||||||
@@ -359,10 +364,10 @@ static char_u *scanf_fmt_to_regpat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (efmp < efm + len) { // %*\D, %*\s etc.
|
} else if (efmp < efm + len) { // %*\D, %*\s etc.
|
||||||
*ptr++ = *++efmp;
|
*regpat++ = *++efmp;
|
||||||
}
|
}
|
||||||
*ptr++ = '\\';
|
*regpat++ = '\\';
|
||||||
*ptr++ = '+';
|
*regpat++ = '+';
|
||||||
} else {
|
} else {
|
||||||
// TODO(vim): scanf()-like: %*ud, %*3c, %*f, ... ?
|
// TODO(vim): scanf()-like: %*ud, %*3c, %*f, ... ?
|
||||||
snprintf((char *)errmsg, errmsglen,
|
snprintf((char *)errmsg, errmsglen,
|
||||||
@@ -373,31 +378,27 @@ static char_u *scanf_fmt_to_regpat(
|
|||||||
|
|
||||||
*pefmp = efmp;
|
*pefmp = efmp;
|
||||||
|
|
||||||
return ptr;
|
return regpat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyze/parse an errorformat prefix.
|
// Analyze/parse an errorformat prefix.
|
||||||
static int efm_analyze_prefix(const char_u **pefmp, efm_T *fmt_ptr,
|
static char_u *efm_analyze_prefix(const char_u *efmp, efm_T *efminfo,
|
||||||
char_u *errmsg, size_t errmsglen)
|
char_u *errmsg, size_t errmsglen)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
const char_u *efmp = *pefmp;
|
|
||||||
|
|
||||||
if (vim_strchr((char_u *)"+-", *efmp) != NULL) {
|
if (vim_strchr((char_u *)"+-", *efmp) != NULL) {
|
||||||
fmt_ptr->flags = *efmp++;
|
efminfo->flags = *efmp++;
|
||||||
}
|
}
|
||||||
if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) {
|
if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) {
|
||||||
fmt_ptr->prefix = *efmp;
|
efminfo->prefix = *efmp;
|
||||||
} else {
|
} else {
|
||||||
snprintf((char *)errmsg, errmsglen,
|
snprintf((char *)errmsg, errmsglen,
|
||||||
_("E376: Invalid %%%c in format string prefix"), *efmp);
|
_("E376: Invalid %%%c in format string prefix"), *efmp);
|
||||||
EMSG(errmsg);
|
EMSG(errmsg);
|
||||||
return FAIL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pefmp = efmp;
|
return efmp;
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -420,16 +421,17 @@ static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx < FMT_PATTERNS) {
|
if (idx < FMT_PATTERNS) {
|
||||||
ptr = fmtpat_to_regpat(efmp, fmt_ptr, idx, round, ptr,
|
ptr = efmpat_to_regpat(efmp, ptr, fmt_ptr, idx, round, errmsg,
|
||||||
errmsg, errmsglen);
|
errmsglen);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return -1;
|
return FAIL;
|
||||||
}
|
}
|
||||||
round++;
|
round++;
|
||||||
} else if (*efmp == '*') {
|
} else if (*efmp == '*') {
|
||||||
ptr = scanf_fmt_to_regpat(efm, len, &efmp, ptr, errmsg, errmsglen);
|
efmp++;
|
||||||
|
ptr = scanf_fmt_to_regpat(&efmp, efm, len, ptr, errmsg, errmsglen);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
return -1;
|
return FAIL;
|
||||||
}
|
}
|
||||||
} else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) {
|
} else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) {
|
||||||
*ptr++ = *efmp; // regexp magic characters
|
*ptr++ = *efmp; // regexp magic characters
|
||||||
@@ -438,14 +440,17 @@ static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr,
|
|||||||
} else if (*efmp == '>') {
|
} else if (*efmp == '>') {
|
||||||
fmt_ptr->conthere = true;
|
fmt_ptr->conthere = true;
|
||||||
} else if (efmp == efm + 1) { // analyse prefix
|
} else if (efmp == efm + 1) { // analyse prefix
|
||||||
if (efm_analyze_prefix(&efmp, fmt_ptr, errmsg, errmsglen) == FAIL) {
|
// prefix is allowed only at the beginning of the errorformat
|
||||||
return -1;
|
// option part
|
||||||
|
efmp = efm_analyze_prefix(efmp, fmt_ptr, errmsg, errmsglen);
|
||||||
|
if (efmp == NULL) {
|
||||||
|
return FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf((char *)errmsg, CMDBUFFSIZE + 1,
|
snprintf((char *)errmsg, CMDBUFFSIZE + 1,
|
||||||
_("E377: Invalid %%%c in format string"), *efmp);
|
_("E377: Invalid %%%c in format string"), *efmp);
|
||||||
EMSG(errmsg);
|
EMSG(errmsg);
|
||||||
return -1;
|
return FAIL;
|
||||||
}
|
}
|
||||||
} else { // copy normal character
|
} else { // copy normal character
|
||||||
if (*efmp == '\\' && efmp + 1 < efm + len) {
|
if (*efmp == '\\' && efmp + 1 < efm + len) {
|
||||||
@@ -461,7 +466,7 @@ static int efm_to_regpat(const char_u *efm, int len, efm_T *fmt_ptr,
|
|||||||
*ptr++ = '$';
|
*ptr++ = '$';
|
||||||
*ptr = NUL;
|
*ptr = NUL;
|
||||||
|
|
||||||
return 0;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls
|
static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls
|
||||||
@@ -477,7 +482,42 @@ static void free_efm_list(efm_T **efm_first)
|
|||||||
fmt_start = NULL;
|
fmt_start = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse 'errorformat' option
|
// Compute the size of the buffer used to convert a 'errorformat' pattern into
|
||||||
|
// a regular expression pattern.
|
||||||
|
static size_t efm_regpat_bufsz(char_u *efm)
|
||||||
|
{
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
sz = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2);
|
||||||
|
for (int i = FMT_PATTERNS - 1; i >= 0; ) {
|
||||||
|
sz += STRLEN(fmt_pat[i--].pattern);
|
||||||
|
}
|
||||||
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
|
sz += 12; // "%f" can become twelve chars longer (see efm_to_regpat)
|
||||||
|
#else
|
||||||
|
sz += 2; // "%f" can become two chars longer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the length of a 'errorformat' option part (separated by ",").
|
||||||
|
static int efm_option_part_len(char_u *efm)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
for (len = 0; efm[len] != NUL && efm[len] != ','; len++) {
|
||||||
|
if (efm[len] == '\\' && efm[len + 1] != NUL) {
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the 'errorformat' option. Multiple parts in the 'errorformat' option
|
||||||
|
// are parsed and converted to regular expressions. Returns information about
|
||||||
|
// the parsed 'errorformat' option.
|
||||||
static efm_T * parse_efm_option(char_u *efm)
|
static efm_T * parse_efm_option(char_u *efm)
|
||||||
{
|
{
|
||||||
efm_T *fmt_ptr = NULL;
|
efm_T *fmt_ptr = NULL;
|
||||||
@@ -489,16 +529,8 @@ static efm_T * parse_efm_option(char_u *efm)
|
|||||||
char_u *errmsg = xmalloc(errmsglen);
|
char_u *errmsg = xmalloc(errmsglen);
|
||||||
|
|
||||||
// Get some space to modify the format string into.
|
// Get some space to modify the format string into.
|
||||||
size_t i = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2);
|
size_t sz = efm_regpat_bufsz(efm);
|
||||||
for (int round = FMT_PATTERNS - 1; round >= 0; ) {
|
char_u *fmtstr = xmalloc(sz);
|
||||||
i += STRLEN(fmt_pat[round--].pattern);
|
|
||||||
}
|
|
||||||
#ifdef BACKSLASH_IN_FILENAME
|
|
||||||
i += 12; // "%f" can become twelve chars longer (see efm_to_regpat)
|
|
||||||
#else
|
|
||||||
i += 2; // "%f" can become two chars longer
|
|
||||||
#endif
|
|
||||||
char_u *fmtstr = xmalloc(i);
|
|
||||||
|
|
||||||
while (efm[0] != NUL) {
|
while (efm[0] != NUL) {
|
||||||
// Allocate a new eformat structure and put it at the end of the list
|
// Allocate a new eformat structure and put it at the end of the list
|
||||||
@@ -511,13 +543,9 @@ static efm_T * parse_efm_option(char_u *efm)
|
|||||||
fmt_last = fmt_ptr;
|
fmt_last = fmt_ptr;
|
||||||
|
|
||||||
// Isolate one part in the 'errorformat' option
|
// Isolate one part in the 'errorformat' option
|
||||||
for (len = 0; efm[len] != NUL && efm[len] != ','; len++) {
|
len = efm_option_part_len(efm);
|
||||||
if (efm[len] == '\\' && efm[len + 1] != NUL) {
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg, errmsglen) == -1) {
|
if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg, errmsglen) == FAIL) {
|
||||||
goto parse_efm_error;
|
goto parse_efm_error;
|
||||||
}
|
}
|
||||||
if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) {
|
if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) {
|
||||||
@@ -543,6 +571,7 @@ parse_efm_end:
|
|||||||
return fmt_first;
|
return fmt_first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allocate more memory for the line buffer used for parsing lines.
|
||||||
static char_u *qf_grow_linebuf(qfstate_T *state, size_t newsz)
|
static char_u *qf_grow_linebuf(qfstate_T *state, size_t newsz)
|
||||||
{
|
{
|
||||||
// If the line exceeds LINE_MAXLEN exclude the last
|
// If the line exceeds LINE_MAXLEN exclude the last
|
||||||
@@ -1011,7 +1040,7 @@ qf_init_ext(
|
|||||||
} else {
|
} else {
|
||||||
// Adding to existing list, use last entry.
|
// Adding to existing list, use last entry.
|
||||||
adding = true;
|
adding = true;
|
||||||
if (qi->qf_lists[qf_idx].qf_count > 0) {
|
if (!qf_list_empty(qi, qf_idx)) {
|
||||||
old_last = qi->qf_lists[qf_idx].qf_last;
|
old_last = qi->qf_lists[qf_idx].qf_last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1183,6 +1212,219 @@ static void qf_new_list(qf_info_T *qi, const char_u *qf_title)
|
|||||||
qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id;
|
qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the match for filename ('%f') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->namebuf".
|
||||||
|
static int qf_parse_fmt_f(regmatch_T *rmp,
|
||||||
|
int midx,
|
||||||
|
qffields_T *fields,
|
||||||
|
int prefix)
|
||||||
|
{
|
||||||
|
char_u c;
|
||||||
|
|
||||||
|
if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand ~/file and $HOME/file to full path.
|
||||||
|
c = *rmp->endp[midx];
|
||||||
|
*rmp->endp[midx] = NUL;
|
||||||
|
expand_env(rmp->startp[midx], fields->namebuf, CMDBUFFSIZE);
|
||||||
|
*rmp->endp[midx] = c;
|
||||||
|
|
||||||
|
// For separate filename patterns (%O, %P and %Q), the specified file
|
||||||
|
// should exist.
|
||||||
|
if (vim_strchr((char_u *)"OPQ", prefix) != NULL
|
||||||
|
&& !os_path_exists(fields->namebuf)) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for error number ('%n') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->enr".
|
||||||
|
static int qf_parse_fmt_n(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
fields->enr = (int)atol((char *)rmp->startp[midx]);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for line number (%l') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->lnum".
|
||||||
|
static int qf_parse_fmt_l(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
fields->lnum = atol((char *)rmp->startp[midx]);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for column number ('%c') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->col".
|
||||||
|
static int qf_parse_fmt_c(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
fields->col = (int)atol((char *)rmp->startp[midx]);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for error type ('%t') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->type".
|
||||||
|
static int qf_parse_fmt_t(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
fields->type = *rmp->startp[midx];
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for '%+' format pattern. The whole matching line is included
|
||||||
|
// in the error string. Return the matched line in "fields->errmsg".
|
||||||
|
static int qf_parse_fmt_plus(char_u *linebuf,
|
||||||
|
size_t linelen,
|
||||||
|
qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (linelen >= fields->errmsglen) {
|
||||||
|
// linelen + null terminator
|
||||||
|
fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
|
||||||
|
fields->errmsglen = linelen + 1;
|
||||||
|
}
|
||||||
|
STRLCPY(fields->errmsg, linebuf, linelen + 1);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for error message ('%m') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->errmsg".
|
||||||
|
static int qf_parse_fmt_m(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
len = (size_t)(rmp->endp[midx] - rmp->startp[midx]);
|
||||||
|
if (len >= fields->errmsglen) {
|
||||||
|
// len + null terminator
|
||||||
|
fields->errmsg = xrealloc(fields->errmsg, len + 1);
|
||||||
|
fields->errmsglen = len + 1;
|
||||||
|
}
|
||||||
|
STRLCPY(fields->errmsg, rmp->startp[midx], len + 1);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for rest of a single-line file message ('%r') pattern.
|
||||||
|
// Return the matched value in "tail".
|
||||||
|
static int qf_parse_fmt_r(regmatch_T *rmp, int midx, char_u **tail)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
*tail = rmp->startp[midx];
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse the match for the pointer line ('%p') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->col".
|
||||||
|
static int qf_parse_fmt_p(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
char_u *match_ptr;
|
||||||
|
|
||||||
|
if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
fields->col = 0;
|
||||||
|
for (match_ptr = rmp->startp[midx]; match_ptr != rmp->endp[midx];
|
||||||
|
match_ptr++) {
|
||||||
|
fields->col++;
|
||||||
|
if (*match_ptr == TAB) {
|
||||||
|
fields->col += 7;
|
||||||
|
fields->col -= fields->col % 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fields->col++;
|
||||||
|
fields->use_viscol = true;
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse the match for the virtual column number ('%v') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->col".
|
||||||
|
static int qf_parse_fmt_v(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
if (rmp->startp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
fields->col = (int)atol((char *)rmp->startp[midx]);
|
||||||
|
fields->use_viscol = true;
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Parse the match for the search text ('%s') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->pattern".
|
||||||
|
static int qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
len = (size_t)(rmp->endp[midx] - rmp->startp[midx]);
|
||||||
|
if (len > CMDBUFFSIZE - 5) {
|
||||||
|
len = CMDBUFFSIZE - 5;
|
||||||
|
}
|
||||||
|
STRCPY(fields->pattern, "^\\V");
|
||||||
|
xstrlcat((char *)fields->pattern, (char *)rmp->startp[midx], len + 4);
|
||||||
|
fields->pattern[len + 3] = '\\';
|
||||||
|
fields->pattern[len + 4] = '$';
|
||||||
|
fields->pattern[len + 5] = NUL;
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the match for the module ('%o') pattern in regmatch.
|
||||||
|
// Return the matched value in "fields->module".
|
||||||
|
static int qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
size_t dsize;
|
||||||
|
|
||||||
|
if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) {
|
||||||
|
return QF_FAIL;
|
||||||
|
}
|
||||||
|
len = (size_t)(rmp->endp[midx] - rmp->startp[midx]);
|
||||||
|
dsize = STRLEN(fields->module) + len + 1;
|
||||||
|
if (dsize > CMDBUFFSIZE) {
|
||||||
|
dsize = CMDBUFFSIZE;
|
||||||
|
}
|
||||||
|
xstrlcat((char *)fields->module, (char *)rmp->startp[midx], dsize);
|
||||||
|
return QF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'errorformat' format pattern parser functions.
|
||||||
|
// The '%f' and '%r' formats are parsed differently from other formats.
|
||||||
|
// See qf_parse_match() for details.
|
||||||
|
static int (*qf_parse_fmt[FMT_PATTERNS])(regmatch_T *, int, qffields_T *) = {
|
||||||
|
NULL,
|
||||||
|
qf_parse_fmt_n,
|
||||||
|
qf_parse_fmt_l,
|
||||||
|
qf_parse_fmt_c,
|
||||||
|
qf_parse_fmt_t,
|
||||||
|
qf_parse_fmt_m,
|
||||||
|
NULL,
|
||||||
|
qf_parse_fmt_p,
|
||||||
|
qf_parse_fmt_v,
|
||||||
|
qf_parse_fmt_s,
|
||||||
|
qf_parse_fmt_o
|
||||||
|
};
|
||||||
|
|
||||||
/// Parse the error format matches in 'regmatch' and set the values in 'fields'.
|
/// Parse the error format matches in 'regmatch' and set the values in 'fields'.
|
||||||
/// fmt_ptr contains the 'efm' format specifiers/prefixes that have a match.
|
/// fmt_ptr contains the 'efm' format specifiers/prefixes that have a match.
|
||||||
/// Returns QF_OK if all the matches are successfully parsed. On failure,
|
/// Returns QF_OK if all the matches are successfully parsed. On failure,
|
||||||
@@ -1193,7 +1435,8 @@ static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr,
|
|||||||
{
|
{
|
||||||
char_u idx = fmt_ptr->prefix;
|
char_u idx = fmt_ptr->prefix;
|
||||||
int i;
|
int i;
|
||||||
size_t len;
|
int midx;
|
||||||
|
int status;
|
||||||
|
|
||||||
if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
|
if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
|
||||||
return QF_FAIL;
|
return QF_FAIL;
|
||||||
@@ -1207,118 +1450,26 @@ static int qf_parse_match(char_u *linebuf, size_t linelen, efm_T *fmt_ptr,
|
|||||||
// Extract error message data from matched line.
|
// Extract error message data from matched line.
|
||||||
// We check for an actual submatch, because "\[" and "\]" in
|
// We check for an actual submatch, because "\[" and "\]" in
|
||||||
// the 'errorformat' may cause the wrong submatch to be used.
|
// the 'errorformat' may cause the wrong submatch to be used.
|
||||||
if ((i = (int)fmt_ptr->addr[0]) > 0) { // %f
|
for (i = 0; i < FMT_PATTERNS; i++) {
|
||||||
if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL) {
|
status = QF_OK;
|
||||||
return QF_FAIL;
|
midx = (int)fmt_ptr->addr[i];
|
||||||
}
|
if (i == 0 && midx > 0) { // %f
|
||||||
|
status = qf_parse_fmt_f(regmatch, midx, fields, idx);
|
||||||
// Expand ~/file and $HOME/file to full path.
|
} else if (i == 5) {
|
||||||
char_u c = *regmatch->endp[i];
|
if (fmt_ptr->flags == '+' && !qf_multiscan) { // %+
|
||||||
*regmatch->endp[i] = NUL;
|
status = qf_parse_fmt_plus(linebuf, linelen, fields);
|
||||||
expand_env(regmatch->startp[i], fields->namebuf, CMDBUFFSIZE);
|
} else if (midx > 0) { // %m
|
||||||
*regmatch->endp[i] = c;
|
status = qf_parse_fmt_m(regmatch, midx, fields);
|
||||||
|
|
||||||
if (vim_strchr((char_u *)"OPQ", idx) != NULL
|
|
||||||
&& !os_path_exists(fields->namebuf)) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[1]) > 0) { // %n
|
|
||||||
if (regmatch->startp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
fields->enr = (int)atol((char *)regmatch->startp[i]);
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[2]) > 0) { // %l
|
|
||||||
if (regmatch->startp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
fields->lnum = atol((char *)regmatch->startp[i]);
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[3]) > 0) { // %c
|
|
||||||
if (regmatch->startp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
fields->col = (int)atol((char *)regmatch->startp[i]);
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[4]) > 0) { // %t
|
|
||||||
if (regmatch->startp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
fields->type = *regmatch->startp[i];
|
|
||||||
}
|
|
||||||
if (fmt_ptr->flags == '+' && !qf_multiscan) { // %+
|
|
||||||
if (linelen >= fields->errmsglen) {
|
|
||||||
// linelen + null terminator
|
|
||||||
fields->errmsg = xrealloc(fields->errmsg, linelen + 1);
|
|
||||||
fields->errmsglen = linelen + 1;
|
|
||||||
}
|
|
||||||
STRLCPY(fields->errmsg, linebuf, linelen + 1);
|
|
||||||
} else if ((i = (int)fmt_ptr->addr[5]) > 0) { // %m
|
|
||||||
if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
len = (size_t)(regmatch->endp[i] - regmatch->startp[i]);
|
|
||||||
if (len >= fields->errmsglen) {
|
|
||||||
// len + null terminator
|
|
||||||
fields->errmsg = xrealloc(fields->errmsg, len + 1);
|
|
||||||
fields->errmsglen = len + 1;
|
|
||||||
}
|
|
||||||
STRLCPY(fields->errmsg, regmatch->startp[i], len + 1);
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[6]) > 0) { // %r
|
|
||||||
if (regmatch->startp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
*tail = regmatch->startp[i];
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[7]) > 0) { // %p
|
|
||||||
if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
fields->col = 0;
|
|
||||||
char_u *match_ptr;
|
|
||||||
for (match_ptr = regmatch->startp[i]; match_ptr != regmatch->endp[i];
|
|
||||||
match_ptr++) {
|
|
||||||
fields->col++;
|
|
||||||
if (*match_ptr == TAB) {
|
|
||||||
fields->col += 7;
|
|
||||||
fields->col -= fields->col % 8;
|
|
||||||
}
|
}
|
||||||
|
} else if (i == 6 && midx > 0) { // %r
|
||||||
|
status = qf_parse_fmt_r(regmatch, midx, tail);
|
||||||
|
} else if (midx > 0) { // others
|
||||||
|
status = (qf_parse_fmt[i])(regmatch, midx, fields);
|
||||||
}
|
}
|
||||||
fields->col++;
|
|
||||||
fields->use_viscol = true;
|
if (status != QF_OK) {
|
||||||
}
|
return status;
|
||||||
if ((i = (int)fmt_ptr->addr[8]) > 0) { // %v
|
|
||||||
if (regmatch->startp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
}
|
||||||
fields->col = (int)atol((char *)regmatch->startp[i]);
|
|
||||||
fields->use_viscol = true;
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[9]) > 0) { // %s
|
|
||||||
if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
len = (size_t)(regmatch->endp[i] - regmatch->startp[i]);
|
|
||||||
if (len > CMDBUFFSIZE - 5) {
|
|
||||||
len = CMDBUFFSIZE - 5;
|
|
||||||
}
|
|
||||||
STRCPY(fields->pattern, "^\\V");
|
|
||||||
STRNCAT(fields->pattern, regmatch->startp[i], len);
|
|
||||||
fields->pattern[len + 3] = '\\';
|
|
||||||
fields->pattern[len + 4] = '$';
|
|
||||||
fields->pattern[len + 5] = NUL;
|
|
||||||
}
|
|
||||||
if ((i = (int)fmt_ptr->addr[10]) > 0) { // %o
|
|
||||||
if (regmatch->startp[i] == NULL || regmatch->endp[i] == NULL) {
|
|
||||||
return QF_FAIL;
|
|
||||||
}
|
|
||||||
len = (size_t)(regmatch->endp[i] - regmatch->startp[i]);
|
|
||||||
if (len > CMDBUFFSIZE) {
|
|
||||||
len = CMDBUFFSIZE;
|
|
||||||
}
|
|
||||||
STRNCAT(fields->module, regmatch->startp[i], len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return QF_OK;
|
return QF_OK;
|
||||||
@@ -1572,7 +1723,7 @@ static int qf_add_entry(qf_info_T *qi, int qf_idx, char_u *dir, char_u *fname,
|
|||||||
qfp->qf_valid = valid;
|
qfp->qf_valid = valid;
|
||||||
|
|
||||||
lastp = &qi->qf_lists[qf_idx].qf_last;
|
lastp = &qi->qf_lists[qf_idx].qf_last;
|
||||||
if (qi->qf_lists[qf_idx].qf_count == 0) {
|
if (qf_list_empty(qi, qf_idx)) {
|
||||||
// first element in the list
|
// first element in the list
|
||||||
qi->qf_lists[qf_idx].qf_start = qfp;
|
qi->qf_lists[qf_idx].qf_start = qfp;
|
||||||
qi->qf_lists[qf_idx].qf_ptr = qfp;
|
qi->qf_lists[qf_idx].qf_ptr = qfp;
|
||||||
@@ -2633,22 +2784,106 @@ theend:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Highlight attributes used for displaying entries from the quickfix list.
|
||||||
|
static int qfFileAttr;
|
||||||
|
static int qfSepAttr;
|
||||||
|
static int qfLineAttr;
|
||||||
|
|
||||||
|
// Display information about a single entry from the quickfix/location list.
|
||||||
|
// Used by ":clist/:llist" commands.
|
||||||
|
static void qf_list_entry(qf_info_T *qi, qfline_T *qfp, int qf_idx)
|
||||||
|
{
|
||||||
|
char_u *fname;
|
||||||
|
buf_T *buf;
|
||||||
|
|
||||||
|
fname = NULL;
|
||||||
|
if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
|
||||||
|
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", qf_idx,
|
||||||
|
(char *)qfp->qf_module);
|
||||||
|
} else {
|
||||||
|
if (qfp->qf_fnum != 0
|
||||||
|
&& (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
|
||||||
|
fname = buf->b_fname;
|
||||||
|
if (qfp->qf_type == 1) { // :helpgrep
|
||||||
|
fname = path_tail(fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fname == NULL) {
|
||||||
|
snprintf((char *)IObuff, IOSIZE, "%2d", qf_idx);
|
||||||
|
} else {
|
||||||
|
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s",
|
||||||
|
qf_idx, (char *)fname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for filtering entries using :filter /pat/ clist
|
||||||
|
// Match against the module name, file name, search pattern and
|
||||||
|
// text of the entry.
|
||||||
|
bool filter_entry = true;
|
||||||
|
if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
|
||||||
|
filter_entry &= message_filtered(qfp->qf_module);
|
||||||
|
}
|
||||||
|
if (filter_entry && fname != NULL) {
|
||||||
|
filter_entry &= message_filtered(fname);
|
||||||
|
}
|
||||||
|
if (filter_entry && qfp->qf_pattern != NULL) {
|
||||||
|
filter_entry &= message_filtered(qfp->qf_pattern);
|
||||||
|
}
|
||||||
|
if (filter_entry) {
|
||||||
|
filter_entry &= message_filtered(qfp->qf_text);
|
||||||
|
}
|
||||||
|
if (filter_entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_putchar('\n');
|
||||||
|
msg_outtrans_attr(IObuff, qf_idx == qi->qf_lists[qi->qf_curlist].qf_index
|
||||||
|
? HL_ATTR(HLF_QFL) : qfFileAttr);
|
||||||
|
|
||||||
|
if (qfp->qf_lnum != 0) {
|
||||||
|
msg_puts_attr(":", qfSepAttr);
|
||||||
|
}
|
||||||
|
if (qfp->qf_lnum == 0) {
|
||||||
|
IObuff[0] = NUL;
|
||||||
|
} else if (qfp->qf_col == 0) {
|
||||||
|
vim_snprintf((char *)IObuff, IOSIZE, "%" PRIdLINENR, qfp->qf_lnum);
|
||||||
|
} else {
|
||||||
|
vim_snprintf((char *)IObuff, IOSIZE, "%" PRIdLINENR " col %d",
|
||||||
|
qfp->qf_lnum, qfp->qf_col);
|
||||||
|
}
|
||||||
|
vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s",
|
||||||
|
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
|
||||||
|
msg_puts_attr((const char *)IObuff, qfLineAttr);
|
||||||
|
msg_puts_attr(":", qfSepAttr);
|
||||||
|
if (qfp->qf_pattern != NULL) {
|
||||||
|
qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
|
||||||
|
msg_puts((const char *)IObuff);
|
||||||
|
msg_puts_attr(":", qfSepAttr);
|
||||||
|
}
|
||||||
|
msg_puts(" ");
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
ui_flush(); // show one line at a time
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":clist": list all errors
|
* ":clist": list all errors
|
||||||
* ":llist": list all locations
|
* ":llist": list all locations
|
||||||
*/
|
*/
|
||||||
void qf_list(exarg_T *eap)
|
void qf_list(exarg_T *eap)
|
||||||
{
|
{
|
||||||
buf_T *buf;
|
|
||||||
char_u *fname;
|
|
||||||
qfline_T *qfp;
|
qfline_T *qfp;
|
||||||
int i;
|
int i;
|
||||||
int idx1 = 1;
|
int idx1 = 1;
|
||||||
int idx2 = -1;
|
int idx2 = -1;
|
||||||
char_u *arg = eap->arg;
|
char_u *arg = eap->arg;
|
||||||
int qfFileAttr;
|
|
||||||
int qfSepAttr;
|
|
||||||
int qfLineAttr;
|
|
||||||
int all = eap->forceit; // if not :cl!, only show
|
int all = eap->forceit; // if not :cl!, only show
|
||||||
// recognised errors
|
// recognised errors
|
||||||
qf_info_T *qi = &ql_info;
|
qf_info_T *qi = &ql_info;
|
||||||
@@ -2717,80 +2952,9 @@ void qf_list(exarg_T *eap)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
fname = NULL;
|
qf_list_entry(qi, qfp, i);
|
||||||
if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
|
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i,
|
|
||||||
(char *)qfp->qf_module);
|
|
||||||
} else {
|
|
||||||
if (qfp->qf_fnum != 0 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) {
|
|
||||||
fname = buf->b_fname;
|
|
||||||
if (qfp->qf_type == 1) { // :helpgrep
|
|
||||||
fname = path_tail(fname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (fname == NULL) {
|
|
||||||
snprintf((char *)IObuff, IOSIZE, "%2d", i);
|
|
||||||
} else {
|
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", i, (char *)fname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Support for filtering entries using :filter /pat/ clist
|
|
||||||
// Match against the module name, file name, search pattern and
|
|
||||||
// text of the entry.
|
|
||||||
bool filter_entry = true;
|
|
||||||
if (qfp->qf_module != NULL && *qfp->qf_module != NUL) {
|
|
||||||
filter_entry &= message_filtered(qfp->qf_module);
|
|
||||||
}
|
|
||||||
if (filter_entry && fname != NULL) {
|
|
||||||
filter_entry &= message_filtered(fname);
|
|
||||||
}
|
|
||||||
if (filter_entry && qfp->qf_pattern != NULL) {
|
|
||||||
filter_entry &= message_filtered(qfp->qf_pattern);
|
|
||||||
}
|
|
||||||
if (filter_entry) {
|
|
||||||
filter_entry &= message_filtered(qfp->qf_text);
|
|
||||||
}
|
|
||||||
if (filter_entry) {
|
|
||||||
goto next_entry;
|
|
||||||
}
|
|
||||||
msg_putchar('\n');
|
|
||||||
msg_outtrans_attr(IObuff, i == qi->qf_lists[qi->qf_curlist].qf_index
|
|
||||||
? HL_ATTR(HLF_QFL) : qfFileAttr);
|
|
||||||
|
|
||||||
if (qfp->qf_lnum != 0) {
|
|
||||||
msg_puts_attr(":", qfSepAttr);
|
|
||||||
}
|
|
||||||
if (qfp->qf_lnum == 0) {
|
|
||||||
IObuff[0] = NUL;
|
|
||||||
} else if (qfp->qf_col == 0) {
|
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, "%" PRIdLINENR, qfp->qf_lnum);
|
|
||||||
} else {
|
|
||||||
vim_snprintf((char *)IObuff, IOSIZE, "%" PRIdLINENR " col %d",
|
|
||||||
qfp->qf_lnum, qfp->qf_col);
|
|
||||||
}
|
|
||||||
vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE, "%s",
|
|
||||||
(char *)qf_types(qfp->qf_type, qfp->qf_nr));
|
|
||||||
msg_puts_attr((const char *)IObuff, qfLineAttr);
|
|
||||||
msg_puts_attr(":", qfSepAttr);
|
|
||||||
if (qfp->qf_pattern != NULL) {
|
|
||||||
qf_fmt_text(qfp->qf_pattern, IObuff, IOSIZE);
|
|
||||||
msg_puts((const char *)IObuff);
|
|
||||||
msg_puts_attr(":", qfSepAttr);
|
|
||||||
}
|
|
||||||
msg_puts(" ");
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
ui_flush(); /* show one line at a time */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next_entry:
|
|
||||||
qfp = qfp->qf_next;
|
qfp = qfp->qf_next;
|
||||||
if (qfp == NULL) {
|
if (qfp == NULL) {
|
||||||
break;
|
break;
|
||||||
@@ -2995,8 +3159,8 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount,
|
|||||||
qi = wp->w_llist;
|
qi = wp->w_llist;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (idx = 0; idx < qi->qf_listcount; ++idx)
|
for (idx = 0; idx < qi->qf_listcount; idx++) {
|
||||||
if (qi->qf_lists[idx].qf_count)
|
if (!qf_list_empty(qi, idx)) {
|
||||||
for (i = 0, qfp = qi->qf_lists[idx].qf_start;
|
for (i = 0, qfp = qi->qf_lists[idx].qf_start;
|
||||||
i < qi->qf_lists[idx].qf_count && qfp != NULL;
|
i < qi->qf_lists[idx].qf_count && qfp != NULL;
|
||||||
i++, qfp = qfp->qf_next) {
|
i++, qfp = qfp->qf_next) {
|
||||||
@@ -3011,6 +3175,8 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount,
|
|||||||
qfp->qf_lnum += amount_after;
|
qfp->qf_lnum += amount_after;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return found_one;
|
return found_one;
|
||||||
}
|
}
|
||||||
@@ -4596,7 +4762,7 @@ void ex_vimgrep(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Jump to first match.
|
// Jump to first match.
|
||||||
if (qi->qf_lists[qi->qf_curlist].qf_count > 0) {
|
if (!qf_list_empty(qi, qi->qf_curlist)) {
|
||||||
if ((flags & VGR_NOJUMP) == 0) {
|
if ((flags & VGR_NOJUMP) == 0) {
|
||||||
vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy, first_match_buf,
|
vgr_jump_to_match(qi, eap->forceit, &redraw_for_dummy, first_match_buf,
|
||||||
target_dir);
|
target_dir);
|
||||||
@@ -4805,7 +4971,7 @@ int get_errorlist(const qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (qf_idx >= qi->qf_listcount
|
if (qf_idx >= qi->qf_listcount
|
||||||
|| qi->qf_lists[qf_idx].qf_count == 0) {
|
|| qf_list_empty(qi, qf_idx)) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5119,7 +5285,7 @@ static int qf_getprop_ctx(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
|||||||
static int qf_getprop_idx(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
static int qf_getprop_idx(qf_info_T *qi, int qf_idx, dict_T *retdict)
|
||||||
{
|
{
|
||||||
int idx = qi->qf_lists[qf_idx].qf_index;
|
int idx = qi->qf_lists[qf_idx].qf_index;
|
||||||
if (qi->qf_lists[qf_idx].qf_count == 0) {
|
if (qf_list_empty(qi, qf_idx)) {
|
||||||
// For empty lists, qf_index is set to 1
|
// For empty lists, qf_index is set to 1
|
||||||
idx = 0;
|
idx = 0;
|
||||||
}
|
}
|
||||||
@@ -5276,7 +5442,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list,
|
|||||||
// make place for a new list
|
// make place for a new list
|
||||||
qf_new_list(qi, title);
|
qf_new_list(qi, title);
|
||||||
qf_idx = qi->qf_curlist;
|
qf_idx = qi->qf_curlist;
|
||||||
} else if (action == 'a' && qi->qf_lists[qf_idx].qf_count > 0) {
|
} else if (action == 'a' && !qf_list_empty(qi, qf_idx)) {
|
||||||
// Adding to existing list, use last entry.
|
// Adding to existing list, use last entry.
|
||||||
old_last = qi->qf_lists[qf_idx].qf_last;
|
old_last = qi->qf_lists[qf_idx].qf_last;
|
||||||
} else if (action == 'r') {
|
} else if (action == 'r') {
|
||||||
@@ -5308,7 +5474,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list,
|
|||||||
}
|
}
|
||||||
if (action != 'a') {
|
if (action != 'a') {
|
||||||
qi->qf_lists[qf_idx].qf_ptr = qi->qf_lists[qf_idx].qf_start;
|
qi->qf_lists[qf_idx].qf_ptr = qi->qf_lists[qf_idx].qf_start;
|
||||||
if (qi->qf_lists[qf_idx].qf_count > 0) {
|
if (!qf_list_empty(qi, qf_idx)) {
|
||||||
qi->qf_lists[qf_idx].qf_index = 1;
|
qi->qf_lists[qf_idx].qf_index = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6023,11 +6189,12 @@ void ex_helpgrep(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Jump to first match. */
|
// Jump to first match.
|
||||||
if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
|
if (!qf_list_empty(qi, qi->qf_curlist)) {
|
||||||
qf_jump(qi, 0, 0, FALSE);
|
qf_jump(qi, 0, 0, false);
|
||||||
else
|
} else {
|
||||||
EMSG2(_(e_nomatch2), eap->arg);
|
EMSG2(_(e_nomatch2), eap->arg);
|
||||||
|
}
|
||||||
|
|
||||||
if (eap->cmdidx == CMD_lhelpgrep) {
|
if (eap->cmdidx == CMD_lhelpgrep) {
|
||||||
// If the help window is not opened or if it already points to the
|
// If the help window is not opened or if it already points to the
|
||||||
|
@@ -1045,8 +1045,8 @@ func Test_efm2()
|
|||||||
set efm=%f:%s
|
set efm=%f:%s
|
||||||
cexpr 'Xtestfile:Line search text'
|
cexpr 'Xtestfile:Line search text'
|
||||||
let l = getqflist()
|
let l = getqflist()
|
||||||
call assert_equal(l[0].pattern, '^\VLine search text\$')
|
call assert_equal('^\VLine search text\$', l[0].pattern)
|
||||||
call assert_equal(l[0].lnum, 0)
|
call assert_equal(0, l[0].lnum)
|
||||||
|
|
||||||
let l = split(execute('clist', ''), "\n")
|
let l = split(execute('clist', ''), "\n")
|
||||||
call assert_equal([' 1 Xtestfile:^\VLine search text\$: '], l)
|
call assert_equal([' 1 Xtestfile:^\VLine search text\$: '], l)
|
||||||
|
Reference in New Issue
Block a user