]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 8.2.0869: it is not possible to customize the quickfix window contents v8.2.0869
authorBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 21:11:59 +0000 (23:11 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 31 May 2020 21:11:59 +0000 (23:11 +0200)
Problem:    It is not possible to customize the quickfix window contents.
Solution:   Add 'quickfixtextfunc'. (Yegappan Lakshmanan, closes #5465)

runtime/doc/eval.txt
runtime/doc/options.txt
runtime/doc/quickfix.txt
src/option.h
src/optiondefs.h
src/quickfix.c
src/testdir/test_quickfix.vim
src/version.c

index b753aae62975c43e3624cd974ae445d34fa06322..fb0b2a7896743c0eaf6ca6ad5cf740cdb7d3bcf7 100644 (file)
@@ -5508,8 +5508,9 @@ getqflist([{what}])                                       *getqflist()*
                        id      get information for the quickfix list with
                                |quickfix-ID|; zero means the id for the
                                current list or the list specified by "nr"
-                       idx     index of the current entry in the quickfix
-                               list specified by 'id' or 'nr'.
+                       idx     get information for the quickfix entry at this
+                               index in the list specified by 'id' or 'nr'.
+                               If set to zero, then uses the current entry.
                                See |quickfix-index|
                        items   quickfix list entries
                        lines   parse a list of lines using 'efm' and return
@@ -5545,7 +5546,7 @@ getqflist([{what}])                                       *getqflist()*
                                If not present, set to "".
                        id      quickfix list ID |quickfix-ID|. If not
                                present, set to 0.
-                       idx     index of the current entry in the list. If not
+                       idx     index of the quickfix entry in the list. If not
                                present, set to 0.
                        items   quickfix list entries. If not present, set to
                                an empty list.
@@ -8841,6 +8842,11 @@ setqflist({list} [, {action} [, {what}]])                *setqflist()*
                    nr          list number in the quickfix stack; zero
                                means the current quickfix list and "$" means
                                the last quickfix list.
+                   quickfixtextfunc
+                               function to get the text to display in the
+                               quickfix window.  Refer to
+                               |quickfix-window-function| for an explanation
+                               of how to write the function and an example.
                    title       quickfix list title text. See |quickfix-title|
                Unsupported keys in {what} are ignored.
                If the "nr" item is not present, then the current quickfix list
index d4d87872c869d1041665d11e33207e95a39bf93d..82b91a610a958aa2b2e18dadd676ea33cdef72d8 100644 (file)
@@ -5898,6 +5898,21 @@ A jump table for the options with a short description can be found at |Q_op|.
        'pyxversion' has no effect.  The pyx* functions and commands are
        always the same as the compiled version.
 
+       This option cannot be set from a |modeline| or in the |sandbox|, for
+       security reasons.
+
+                                               *'quickfixtextfunc'* *'qftf'*
+'quickfixtextfunc' 'qftf'      string (default "")
+                       global
+                       {only available when compiled with the |+quickfix|
+                       feature}
+       This option specifies a function to be used to get the text to display
+       in the quickfix and location list windows.  This can be used to
+       customize the information displayed in the quickfix or location window
+       for each entry in the corresponding quickfix or location list.  See
+       |quickfix-window-function| for an explanation of how to write the
+       function and an example.
+
        This option cannot be set from a |modeline| or in the |sandbox|, for
        security reasons.
 
index 7f7f10faca520300300a2d0409c41011ff8ecd0a..d4ebf5c489f8ffe7ccc3f8367ca87340817aa53b 100644 (file)
@@ -15,6 +15,7 @@ This subject is introduced in section |30.1| of the user manual.
 7. The error format                    |error-file-format|
 8. The directory stack                 |quickfix-directory-stack|
 9. Specific error file formats         |errorformats|
+10. Customizing the quickfix window    |quickfix-window-function|
 
 The quickfix commands are not available when the |+quickfix| feature was
 disabled at compile time.
@@ -1921,6 +1922,59 @@ error messages into a format that quickfix mode will understand.  See the
 start of the file about how to use it.  (This script is deprecated, see
 |compiler-perl|.)
 
-
+=============================================================================
+10. Customizing the quickfix window            *quickfix-window-function*
+
+The default format for the lines displayed in the quickfix window and location
+list window is:
+
+    <filename>|<lnum> col <col>|<text>
+
+The values displayed in each line correspond to the "bufnr", "lnum", "col" and
+"text" fields returned by the |getqflist()| function.
+
+For some quickfix/location lists, the displayed text need to be customized.
+For example, if only the filename is present for a quickfix entry, then the
+two "|" field separator characters after the filename are not needed.  Another
+use case is to customize the path displayed for a filename. By default, the
+complete path (which may be too long) is displayed for files which are not
+under the current directory tree. The file path may need to be simplified to a
+common parent directory.
+
+The displayed text can be customized by setting the 'quickfixtextfunc' option
+to a Vim function.  This function will be called with a dict argument for
+every entry in a quickfix or a location list. The dict argument will have the
+following fields:
+
+    quickfix   set to 1 when called for a quickfix list and 0 when called for
+               a location list.
+    id         quickfix or location list identifier
+    idx                index of the entry in the quickfix or location list
+
+The function should return a single line of text to display in the quickfix
+window for the entry identified by idx. The function can obtain information
+about the current entry using the |getqflist()| function and specifying the
+quickfix list identifier "id" and the entry index "idx".
+
+If a quickfix or location list specific customization is needed, then the
+'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or
+|setloclist()| function. This overrides the global 'quickfixtextfunc' option.
+
+The example below displays the list of old files (|v:oldfiles|) in a quickfix
+window. As there is no line, column number and error text information
+associated with each entry, the 'quickfixtextfunc' function returns only the
+filename.
+Example: >
+    " create a quickfix list from v:oldfiles
+    call setqflist([], ' ', {'lines' : v:oldfiles, 'efm' : '%f',
+                                       \ 'quickfixtextfunc' : 'QfOldFiles'})
+    func QfOldFiles(info)
+       " get information about the specific quickfix entry
+       let e = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
+                                               \ 'items' : 1}).items[0]
+       " return the simplified file name
+       return fnamemodify(bufname(e.bufnr), ':p:.')
+    endfunc
+<
 
  vim:tw=78:ts=8:noet:ft=help:norl:
index bead4c5bb630cf0cc7f8ae99a47ac6dc32e55ac9..718553a9082533497c38384e4be1917e07e7fc4d 100644 (file)
@@ -820,6 +820,7 @@ EXTERN int  p_ru;           // 'ruler'
 EXTERN char_u  *p_ruf;         // 'rulerformat'
 #endif
 EXTERN char_u  *p_pp;          // 'packpath'
+EXTERN char_u  *p_qftf;        // 'quickfixtextfunc'
 EXTERN char_u  *p_rtp;         // 'runtimepath'
 EXTERN long    p_sj;           // 'scrolljump'
 #if defined(MSWIN) && defined(FEAT_GUI)
index 5ed9be9bc6635c73cab273f19e32fe1839e5e02a..571a3af5e207fe6b1c1212f45142d9d4d3e782fd 100644 (file)
@@ -2045,6 +2045,15 @@ static struct vimoption options[] =
 #endif
                            {(char_u *)DEFAULT_PYTHON_VER, (char_u *)0L}
                            SCTX_INIT},
+    {"quickfixtextfunc", "qftf", P_STRING|P_ALLOCED|P_VI_DEF|P_VIM|P_SECURE,
+#if defined(FEAT_QUICKFIX) && defined(FEAT_EVAL)
+                           (char_u *)&p_qftf, PV_NONE,
+                           {(char_u *)"", (char_u *)0L}
+#else
+                           (char_u *)NULL, PV_NONE,
+                           {(char_u *)NULL, (char_u *)NULL}
+#endif
+                           SCTX_INIT},
     {"quoteescape", "qe",   P_STRING|P_ALLOCED|P_VI_DEF,
 #ifdef FEAT_TEXTOBJ
                            (char_u *)&p_qe, PV_QE,
index f3ad4cde205b455b4c8a083098e008bf472ad9eb..acd28a14351d5f44b31cf192c68245b10811c82b 100644 (file)
@@ -82,6 +82,7 @@ typedef struct qf_list_S
     char_u     *qf_title;      // title derived from the command that created
                                // the error list or set by setqflist
     typval_T   *qf_ctx;        // context set by setqflist/setloclist
+    char_u     *qf_qftf;       // 'quickfixtextfunc' setting for this list
 
     struct dir_stack_T *qf_dir_stack;
     char_u             *qf_directory;
@@ -2277,6 +2278,10 @@ copy_loclist(qf_list_T *from_qfl, qf_list_T *to_qfl)
     }
     else
        to_qfl->qf_ctx = NULL;
+    if (from_qfl->qf_qftf != NULL)
+       to_qfl->qf_qftf = vim_strsave(from_qfl->qf_qftf);
+    else
+       to_qfl->qf_qftf = NULL;
 
     if (from_qfl->qf_count)
        if (copy_loclist_entries(from_qfl, to_qfl) == FAIL)
@@ -3812,6 +3817,7 @@ qf_free(qf_list_T *qfl)
     VIM_CLEAR(qfl->qf_title);
     free_tv(qfl->qf_ctx);
     qfl->qf_ctx = NULL;
+    VIM_CLEAR(qfl->qf_qftf);
     qfl->qf_id = 0;
     qfl->qf_changedtick = 0L;
 }
@@ -4399,75 +4405,116 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
  * Add an error line to the quickfix buffer.
  */
     static int
-qf_buf_add_line(buf_T *buf, linenr_T lnum, qfline_T *qfp, char_u *dirname)
+qf_buf_add_line(
+       qf_list_T       *qfl,           // quickfix list
+       buf_T           *buf,           // quickfix window buffer
+       linenr_T        lnum,
+       qfline_T        *qfp,
+       char_u          *dirname)
 {
     int                len;
     buf_T      *errbuf;
+    char_u     *qftf;
+
+    // If 'quickfixtextfunc' is set, then use the user-supplied function to get
+    // the text to display
+    qftf = p_qftf;
+    // Use the local value of 'quickfixtextfunc' if it is set.
+    if (qfl->qf_qftf != NULL)
+       qftf = qfl->qf_qftf;
+    if (qftf != NULL && *qftf != NUL)
+    {
+       char_u          *qfbuf_text;
+       typval_T        args[1];
+       dict_T          *d;
+
+       // create 'info' dict argument
+       if ((d = dict_alloc_lock(VAR_FIXED)) == NULL)
+           return FAIL;
+       dict_add_number(d, "quickfix", (long)IS_QF_LIST(qfl));
+       dict_add_number(d, "id", (long)qfl->qf_id);
+       dict_add_number(d, "idx", (long)(lnum + 1));
+       ++d->dv_refcount;
+       args[0].v_type = VAR_DICT;
+       args[0].vval.v_dict = d;
 
-    if (qfp->qf_module != NULL)
-    {
-       vim_strncpy(IObuff, qfp->qf_module, IOSIZE - 1);
-       len = (int)STRLEN(IObuff);
+       qfbuf_text = call_func_retstr(qftf, 1, args);
+       --d->dv_refcount;
+
+       if (qfbuf_text == NULL)
+           return FAIL;
+
+       vim_strncpy(IObuff, qfbuf_text, IOSIZE - 1);
+       vim_free(qfbuf_text);
     }
-    else if (qfp->qf_fnum != 0
-           && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
-           && errbuf->b_fname != NULL)
+    else
     {
-       if (qfp->qf_type == 1)  // :helpgrep
-           vim_strncpy(IObuff, gettail(errbuf->b_fname), IOSIZE - 1);
-       else
+       if (qfp->qf_module != NULL)
+       {
+           vim_strncpy(IObuff, qfp->qf_module, IOSIZE - 1);
+           len = (int)STRLEN(IObuff);
+       }
+       else if (qfp->qf_fnum != 0
+               && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL
+               && errbuf->b_fname != NULL)
        {
-           // shorten the file name if not done already
-           if (errbuf->b_sfname == NULL
-                   || mch_isFullName(errbuf->b_sfname))
+           if (qfp->qf_type == 1)      // :helpgrep
+               vim_strncpy(IObuff, gettail(errbuf->b_fname), IOSIZE - 1);
+           else
            {
-               if (*dirname == NUL)
-                   mch_dirname(dirname, MAXPATHL);
-               shorten_buf_fname(errbuf, dirname, FALSE);
+               // shorten the file name if not done already
+               if (errbuf->b_sfname == NULL
+                       || mch_isFullName(errbuf->b_sfname))
+               {
+                   if (*dirname == NUL)
+                       mch_dirname(dirname, MAXPATHL);
+                   shorten_buf_fname(errbuf, dirname, FALSE);
+               }
+               vim_strncpy(IObuff, errbuf->b_fname, IOSIZE - 1);
            }
-           vim_strncpy(IObuff, errbuf->b_fname, IOSIZE - 1);
+           len = (int)STRLEN(IObuff);
        }
-       len = (int)STRLEN(IObuff);
-    }
-    else
-       len = 0;
+       else
+           len = 0;
 
-    if (len < IOSIZE - 1)
-       IObuff[len++] = '|';
+       if (len < IOSIZE - 1)
+           IObuff[len++] = '|';
 
-    if (qfp->qf_lnum > 0)
-    {
-       vim_snprintf((char *)IObuff + len, IOSIZE - len, "%ld", qfp->qf_lnum);
-       len += (int)STRLEN(IObuff + len);
+       if (qfp->qf_lnum > 0)
+       {
+           vim_snprintf((char *)IObuff + len, IOSIZE - len, "%ld",
+                   qfp->qf_lnum);
+           len += (int)STRLEN(IObuff + len);
+
+           if (qfp->qf_col > 0)
+           {
+               vim_snprintf((char *)IObuff + len, IOSIZE - len,
+                       " col %d", qfp->qf_col);
+               len += (int)STRLEN(IObuff + len);
+           }
 
-       if (qfp->qf_col > 0)
+           vim_snprintf((char *)IObuff + len, IOSIZE - len, "%s",
+                   (char *)qf_types(qfp->qf_type, qfp->qf_nr));
+           len += (int)STRLEN(IObuff + len);
+       }
+       else if (qfp->qf_pattern != NULL)
        {
-           vim_snprintf((char *)IObuff + len, IOSIZE - len,
-                                                      " col %d", qfp->qf_col);
+           qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
            len += (int)STRLEN(IObuff + len);
        }
+       if (len < IOSIZE - 2)
+       {
+           IObuff[len++] = '|';
+           IObuff[len++] = ' ';
+       }
 
-       vim_snprintf((char *)IObuff + len, IOSIZE - len, "%s",
-               (char *)qf_types(qfp->qf_type, qfp->qf_nr));
-       len += (int)STRLEN(IObuff + len);
-    }
-    else if (qfp->qf_pattern != NULL)
-    {
-       qf_fmt_text(qfp->qf_pattern, IObuff + len, IOSIZE - len);
-       len += (int)STRLEN(IObuff + len);
-    }
-    if (len < IOSIZE - 2)
-    {
-       IObuff[len++] = '|';
-       IObuff[len++] = ' ';
+       // 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(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
+               IObuff + len, IOSIZE - len);
     }
 
-    // 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(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text,
-           IObuff + len, IOSIZE - len);
-
     if (ml_append_buf(buf, lnum, IObuff,
                (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL)
        return FAIL;
@@ -4522,7 +4569,7 @@ qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last)
        }
        while (lnum < qfl->qf_count)
        {
-           if (qf_buf_add_line(buf, lnum, qfp, dirname) == FAIL)
+           if (qf_buf_add_line(qfl, buf, lnum, qfp, dirname) == FAIL)
                break;
 
            ++lnum;
@@ -6369,9 +6416,16 @@ get_qfline_items(qfline_T *qfp, list_T *list)
 /*
  * Add each quickfix error to list "list" as a dictionary.
  * If qf_idx is -1, use the current list. Otherwise, use the specified list.
+ * If eidx is not 0, then return only the specified entry. Otherwise return
+ * all the entries.
  */
     static int
-get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
+get_errorlist(
+       qf_info_T       *qi_arg,
+       win_T           *wp,
+       int             qf_idx,
+       int             eidx,
+       list_T          *list)
 {
     qf_info_T  *qi = qi_arg;
     qf_list_T  *qfl;
@@ -6389,6 +6443,9 @@ get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
        }
     }
 
+    if (eidx < 0)
+       return OK;
+
     if (qf_idx == INVALID_QFIDX)
        qf_idx = qi->qf_curlist;
 
@@ -6401,7 +6458,12 @@ get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
 
     FOR_ALL_QFL_ITEMS(qfl, qfp, i)
     {
-       if (get_qfline_items(qfp, list) == FAIL)
+       if (eidx > 0)
+       {
+           if (eidx == i)
+               return get_qfline_items(qfp, list);
+       }
+       else if (get_qfline_items(qfp, list) == FAIL)
            return FAIL;
     }
 
@@ -6461,7 +6523,7 @@ qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
            if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
                        TRUE, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0)
            {
-               (void)get_errorlist(qi, NULL, 0, l);
+               (void)get_errorlist(qi, NULL, 0, 0, l);
                qf_free(&qi->qf_lists[0]);
            }
            free(qi);
@@ -6679,16 +6741,17 @@ qf_getprop_filewinid(win_T *wp, qf_info_T *qi, dict_T *retdict)
 }
 
 /*
- * Return the quickfix list items/entries as 'items' in retdict
+ * Return the quickfix list items/entries as 'items' in retdict.
+ * If eidx is not 0, then return the item at the specified index.
  */
     static int
-qf_getprop_items(qf_info_T *qi, int qf_idx, dict_T *retdict)
+qf_getprop_items(qf_info_T *qi, int qf_idx, int eidx, dict_T *retdict)
 {
     int                status = OK;
     list_T     *l = list_alloc();
     if (l != NULL)
     {
-       (void)get_errorlist(qi, NULL, qf_idx, l);
+       (void)get_errorlist(qi, NULL, qf_idx, eidx, l);
        dict_add_list(retdict, "items", l);
     }
     else
@@ -6726,16 +6789,20 @@ qf_getprop_ctx(qf_list_T *qfl, dict_T *retdict)
 }
 
 /*
- * Return the current quickfix list index as 'idx' in retdict
+ * Return the current quickfix list index as 'idx' in retdict.
+ * If a specific entry index (eidx) is supplied, then use that.
  */
     static int
-qf_getprop_idx(qf_list_T *qfl, dict_T *retdict)
+qf_getprop_idx(qf_list_T *qfl, int eidx, dict_T *retdict)
 {
-    int curidx = qfl->qf_index;
-    if (qf_list_empty(qfl))
-       // For empty lists, current index is set to 0
-       curidx = 0;
-    return dict_add_number(retdict, "idx", curidx);
+    if (eidx == 0)
+    {
+       eidx = qfl->qf_index;
+       if (qf_list_empty(qfl))
+           // For empty lists, current index is set to 0
+           eidx = 0;
+    }
+    return dict_add_number(retdict, "idx", eidx);
 }
 
 /*
@@ -6750,6 +6817,7 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
     qf_list_T  *qfl;
     int                status = OK;
     int                qf_idx = INVALID_QFIDX;
+    int                eidx = 0;
     dictitem_T *di;
     int                flags = QF_GETLIST_NONE;
 
@@ -6770,6 +6838,14 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
 
     qfl = qf_get_list(qi, qf_idx);
 
+    // If an entry index is specified, use that
+    if ((di = dict_find(what, (char_u *)"idx", -1)) != NULL)
+    {
+       if (di->di_tv.v_type != VAR_NUMBER)
+           return FAIL;
+       eidx = di->di_tv.vval.v_number;
+    }
+
     if (flags & QF_GETLIST_TITLE)
        status = qf_getprop_title(qfl, retdict);
     if ((status == OK) && (flags & QF_GETLIST_NR))
@@ -6777,13 +6853,13 @@ qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict)
     if ((status == OK) && (flags & QF_GETLIST_WINID))
        status = dict_add_number(retdict, "winid", qf_winid(qi));
     if ((status == OK) && (flags & QF_GETLIST_ITEMS))
-       status = qf_getprop_items(qi, qf_idx, retdict);
+       status = qf_getprop_items(qi, qf_idx, eidx, retdict);
     if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
        status = qf_getprop_ctx(qfl, retdict);
     if ((status == OK) && (flags & QF_GETLIST_ID))
        status = dict_add_number(retdict, "id", qfl->qf_id);
     if ((status == OK) && (flags & QF_GETLIST_IDX))
-       status = qf_getprop_idx(qfl, retdict);
+       status = qf_getprop_idx(qfl, eidx, retdict);
     if ((status == OK) && (flags & QF_GETLIST_SIZE))
        status = dict_add_number(retdict, "size", qfl->qf_count);
     if ((status == OK) && (flags & QF_GETLIST_TICK))
@@ -7147,6 +7223,20 @@ qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, dictitem_T *di)
     return OK;
 }
 
+/*
+ * Set the current index in the specified quickfix list
+ */
+    static int
+qf_setprop_qftf(qf_info_T *qi UNUSED, qf_list_T *qfl, dictitem_T *di)
+{
+    VIM_CLEAR(qfl->qf_qftf);
+    if (di->di_tv.v_type == VAR_STRING
+           && di->di_tv.vval.v_string != NULL)
+       qfl->qf_qftf = vim_strsave(di->di_tv.vval.v_string);
+
+    return OK;
+}
+
 /*
  * Set quickfix/location list properties (title, items, context).
  * Also used to add items from parsing a list of lines.
@@ -7186,6 +7276,8 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title)
        retval = qf_setprop_context(qfl, di);
     if ((di = dict_find(what, (char_u *)"idx", -1)) != NULL)
        retval = qf_setprop_curidx(qi, qfl, di);
+    if ((di = dict_find(what, (char_u *)"quickfixtextfunc", -1)) != NULL)
+       retval = qf_setprop_qftf(qi, qfl, di);
 
     if (retval == OK)
        qf_list_changed(qfl);
@@ -7900,7 +7992,7 @@ get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
     {
        if (rettv_list_alloc(rettv) == OK)
            if (is_qf || wp != NULL)
-               (void)get_errorlist(NULL, wp, -1, rettv->vval.v_list);
+               (void)get_errorlist(NULL, wp, -1, 0, rettv->vval.v_list);
     }
     else
     {
index 11bdfbefa3f5b32bcf56d41eae4ccb0a07690bae..fb4e07c6f78591b2b30a4a824f3659b43339f90b 100644 (file)
@@ -4766,4 +4766,121 @@ func Test_cquit()
   call assert_fails('-3cquit', 'E16:')
 endfunc
 
+" Test for getting a specific item from a quickfix list
+func Xtest_getqflist_by_idx(cchar)
+  call s:setup_commands(a:cchar)
+  " Empty list
+  call assert_equal([], g:Xgetlist({'idx' : 1, 'items' : 0}).items)
+  Xexpr ['F1:10:L10', 'F1:20:L20']
+  let l = g:Xgetlist({'idx' : 2, 'items' : 0}).items
+  call assert_equal(bufnr('F1'), l[0].bufnr)
+  call assert_equal(20, l[0].lnum)
+  call assert_equal('L20', l[0].text)
+  call assert_equal([], g:Xgetlist({'idx' : -1, 'items' : 0}).items)
+  call assert_equal([], g:Xgetlist({'idx' : 3, 'items' : 0}).items)
+  %bwipe!
+endfunc
+
+func Test_getqflist_by_idx()
+  call Xtest_getqflist_by_idx('c')
+  call Xtest_getqflist_by_idx('l')
+endfunc
+
+" Test for the 'quickfixtextfunc' setting
+func Tqfexpr(info)
+  if a:info.quickfix
+    let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
+          \ 'items' : 1}).items
+  else
+    let qfl = getloclist(0, {'id' : a:info.id, 'idx' : a:info.idx,
+          \ 'items' : 1}).items
+  endif
+
+  let e = qfl[0]
+  let s = ''
+  if e.bufnr != 0
+    let bname = bufname(e.bufnr)
+    let s ..= fnamemodify(bname, ':.')
+  endif
+  let s ..= '-'
+  let s ..= 'L' .. string(e.lnum) .. 'C' .. string(e.col) .. '-'
+  let s ..= e.text
+
+  return s
+endfunc
+
+func Xtest_qftextfunc(cchar)
+  call s:setup_commands(a:cchar)
+
+  set efm=%f:%l:%c:%m
+  set quickfixtextfunc=Tqfexpr
+  Xexpr ['F1:10:2:green', 'F1:20:4:blue']
+  Xwindow
+  call assert_equal('F1-L10C2-green', getline(1))
+  call assert_equal('F1-L20C4-blue', getline(2))
+  Xclose
+  set quickfixtextfunc&vim
+  Xwindow
+  call assert_equal('F1|10 col 2| green', getline(1))
+  call assert_equal('F1|20 col 4| blue', getline(2))
+  Xclose
+  set efm&
+  set quickfixtextfunc&
+
+  " Test for per list 'quickfixtextfunc' setting
+  func PerQfText(info)
+    if a:info.quickfix
+      let qfl = getqflist({'id' : a:info.id, 'idx' : a:info.idx,
+            \ 'items' : 1}).items
+    else
+      let qfl = getloclist(0, {'id' : a:info.id, 'idx' : a:info.idx,
+            \ 'items' : 1}).items
+    endif
+    if empty(qfl)
+      return ''
+    endif
+    return 'Line ' .. qfl[0].lnum .. ', Col ' .. qfl[0].col
+  endfunc
+  set quickfixtextfunc=Tqfexpr
+  call g:Xsetlist([], ' ', {'quickfixtextfunc' : "PerQfText"})
+  Xaddexpr ['F1:10:2:green', 'F1:20:4:blue']
+  Xwindow
+  call assert_equal('Line 10, Col 2', getline(1))
+  call assert_equal('Line 20, Col 4', getline(2))
+  Xclose
+  call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''})
+  set quickfixtextfunc&
+  delfunc PerQfText
+
+  " Non-existing function
+  set quickfixtextfunc=Tabc
+  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
+  call assert_fails("Xwindow", 'E117:')
+  Xclose
+  set quickfixtextfunc&
+
+  " set option to a non-function
+  set quickfixtextfunc=[10,\ 20]
+  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E117:')
+  call assert_fails("Xwindow", 'E117:')
+  Xclose
+  set quickfixtextfunc&
+
+  " set option to a function with different set of arguments
+  func Xqftext(a, b, c)
+    return a:a .. a:b .. a:c
+  endfunc
+  set quickfixtextfunc=Xqftext
+  call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue']", 'E119:')
+  call assert_fails("Xwindow", 'E119:')
+  Xclose
+  set quickfixtextfunc&
+  delfunc Xqftext
+endfunc
+
+func Test_qftextfunc()
+  call Xtest_qftextfunc('c')
+  call Xtest_qftextfunc('l')
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
index c75283f9f19dada0db424d4b0f4b5305b5d8c35d..d211e8cd0a4840db439d7d7f8788528b6b9fdd1d 100644 (file)
@@ -746,6 +746,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    869,
 /**/
     868,
 /**/