diff options
Diffstat (limited to 'src/nvim/quickfix.c')
| -rw-r--r-- | src/nvim/quickfix.c | 84 | 
1 files changed, 80 insertions, 4 deletions
| diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index d77cec4fd8..c5d03e73f1 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -85,6 +85,7 @@ typedef struct qf_list_S {    int qf_nonevalid;             // TRUE if not a single valid entry found    char_u      *qf_title;        // title derived from the command that created                                  // the error list +  typval_T    *qf_ctx;          // context set by setqflist/setloclist  } qf_list_T;  struct qf_info_S { @@ -800,7 +801,7 @@ restofline:          fields->type = *regmatch.startp[i];        }        if (fmt_ptr->flags == '+' && !qi->qf_multiscan) {       // %+ -        if (linelen > fields->errmsglen) { +        if (linelen >= fields->errmsglen) {            // linelen + null terminator            fields->errmsg = xrealloc(fields->errmsg, linelen + 1);            fields->errmsglen = linelen + 1; @@ -811,7 +812,7 @@ restofline:            continue;          }          len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); -        if (len > fields->errmsglen) { +        if (len >= fields->errmsglen) {            // len + null terminator            fields->errmsg = xrealloc(fields->errmsg, len + 1);            fields->errmsglen = len + 1; @@ -888,7 +889,7 @@ restofline:      fields->namebuf[0] = NUL;                // no match found, remove file name      fields->lnum = 0;                        // don't jump to this line      fields->valid = false; -    if (linelen > fields->errmsglen) { +    if (linelen >= fields->errmsglen) {        // linelen + null terminator        fields->errmsg = xrealloc(fields->errmsg, linelen + 1);        fields->errmsglen = linelen + 1; @@ -1409,6 +1410,13 @@ void copy_loclist(win_T *from, win_T *to)      else        to_qfl->qf_title = NULL; +    if (from_qfl->qf_ctx != NULL) { +      to_qfl->qf_ctx = xcalloc(1, sizeof(typval_T)); +      tv_copy(from_qfl->qf_ctx, to_qfl->qf_ctx); +    } else { +      to_qfl->qf_ctx = NULL; +    } +      if (from_qfl->qf_count) {        qfline_T    *from_qfp;        qfline_T    *prevp; @@ -2410,6 +2418,8 @@ static void qf_free(qf_info_T *qi, int idx)    qi->qf_lists[idx].qf_start = NULL;    qi->qf_lists[idx].qf_ptr = NULL;    qi->qf_lists[idx].qf_title = NULL; +  tv_free(qi->qf_lists[idx].qf_ctx); +  qi->qf_lists[idx].qf_ctx = NULL;    qi->qf_lists[idx].qf_index = 0;    qi->qf_lists[idx].qf_start = NULL;    qi->qf_lists[idx].qf_last = NULL; @@ -4060,6 +4070,7 @@ enum {    QF_GETLIST_ITEMS = 0x2,    QF_GETLIST_NR = 0x4,    QF_GETLIST_WINID = 0x8, +  QF_GETLIST_CONTEXT = 0x10,    QF_GETLIST_ALL = 0xFF  }; @@ -4110,6 +4121,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)      flags |= QF_GETLIST_WINID;    } +  if (tv_dict_find(what, S_LEN("context")) != NULL) { +    flags |= QF_GETLIST_CONTEXT; +  } +    if (flags & QF_GETLIST_TITLE) {      char_u *t = qi->qf_lists[qf_idx].qf_title;      if (t == NULL) { @@ -4127,6 +4142,20 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)      }    } +  if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) { +    if (qi->qf_lists[qf_idx].qf_ctx != NULL) { +      di = tv_dict_item_alloc_len(S_LEN("context")); +      if (di != NULL) { +        tv_copy(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv); +        if (tv_dict_add(retdict, di) == FAIL) { +          tv_dict_item_free(di); +        } +      } +    } else { +      status = tv_dict_add_str(retdict, S_LEN("context"), ""); +    } +  } +    return status;  } @@ -4249,7 +4278,10 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)    if ((di = tv_dict_find(what, S_LEN("nr"))) != NULL) {      // Use the specified quickfix/location list      if (di->di_tv.v_type == VAR_NUMBER) { -      qf_idx = (int)di->di_tv.vval.v_number - 1; +      // for zero use the current list +      if (di->di_tv.vval.v_number != 0) { +        qf_idx = (int)di->di_tv.vval.v_number - 1; +      }        if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {          return FAIL;        } @@ -4276,6 +4308,14 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)      }    } +  if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) { +    tv_free(qi->qf_lists[qf_idx].qf_ctx); + +    typval_T *ctx = xcalloc(1, sizeof(typval_T)); +    tv_copy(&di->di_tv, ctx); +    qi->qf_lists[qf_idx].qf_ctx = ctx; +  } +    return retval;  } @@ -4362,6 +4402,42 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title,    return retval;  } +static bool mark_quickfix_ctx(qf_info_T *qi, int copyID) +{ +  bool abort = false; + +  for (int i = 0; i < LISTCOUNT && !abort; i++) { +    typval_T *ctx = qi->qf_lists[i].qf_ctx; +    if (ctx != NULL && ctx->v_type != VAR_NUMBER +        && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) { +      abort = set_ref_in_item(ctx, copyID, NULL, NULL); +    } +  } + +  return abort; +} + +/// Mark the context of the quickfix list and the location lists (if present) as +/// "in use". So that garabage collection doesn't free the context. +bool set_ref_in_quickfix(int copyID) +{ +  bool abort = mark_quickfix_ctx(&ql_info, copyID); +  if (abort) { +    return abort; +  } + +  FOR_ALL_TAB_WINDOWS(tp, win) { +    if (win->w_llist != NULL) { +      abort = mark_quickfix_ctx(win->w_llist, copyID); +      if (abort) { +        return abort; +      } +    } +  } + +  return abort; +} +  /*   * ":[range]cbuffer [bufnr]" command.   * ":[range]caddbuffer [bufnr]" command. | 
