To: vim_dev@googlegroups.com Subject: Patch 8.2.1255 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1255 Problem: Cannot use a lambda with quickfix functions. Solution: Add support for lambda. (Yegappan Lakshmanan, closes #6499) Files: runtime/doc/eval.txt, runtime/doc/options.txt, runtime/doc/quickfix.txt, src/channel.c, src/evalvars.c, src/optionstr.c, src/proto/evalvars.pro, src/proto/quickfix.pro, src/quickfix.c, src/testdir/test_quickfix.vim *** ../vim-8.2.1254/runtime/doc/eval.txt 2020-07-18 22:24:18.626245018 +0200 --- runtime/doc/eval.txt 2020-07-20 21:24:51.730411122 +0200 *************** *** 2502,2514 **** List list of jump list items getline({lnum}) String line {lnum} of current buffer getline({lnum}, {end}) List lines {lnum} to {end} of current buffer ! getloclist({nr} [, {what}]) List list of location list items getmarklist([{expr}]) List list of global/local marks getmatches([{win}]) List list of current matches getmousepos() Dict last known mouse position getpid() Number process ID of Vim getpos({expr}) List position of cursor, mark, etc. ! getqflist([{what}]) List list of quickfix items getreg([{regname} [, 1 [, {list}]]]) String or List contents of a register getreginfo([{regname}]) Dict information about a register --- 2512,2526 ---- List list of jump list items getline({lnum}) String line {lnum} of current buffer getline({lnum}, {end}) List lines {lnum} to {end} of current buffer ! getloclist({nr}) List list of location list items ! getloclist({nr}, {what}) Dict get specific location list properties getmarklist([{expr}]) List list of global/local marks getmatches([{win}]) List list of current matches getmousepos() Dict last known mouse position getpid() Number process ID of Vim getpos({expr}) List position of cursor, mark, etc. ! getqflist() List list of quickfix items ! getqflist({what}) Dict get specific quickfix list properties getreg([{regname} [, 1 [, {list}]]]) String or List contents of a register getreginfo([{regname}]) Dict information about a register *************** *** 2747,2758 **** setenv({name}, {val}) none set environment variable setfperm({fname}, {mode}) Number set {fname} file permissions to {mode} setline({lnum}, {line}) Number set line {lnum} to {line} ! setloclist({nr}, {list} [, {action} [, {what}]]) ! Number modify location list using {list} setmatches({list} [, {win}]) Number restore a list of matches setpos({expr}, {list}) Number set the {expr} position to {list} ! setqflist({list} [, {action} [, {what}]]) ! Number modify quickfix list using {list} setreg({n}, {v} [, {opt}]) Number set register to value and type settabvar({nr}, {varname}, {val}) none set {varname} in tab page {nr} to {val} settabwinvar({tabnr}, {winnr}, {varname}, {val}) --- 2759,2773 ---- setenv({name}, {val}) none set environment variable setfperm({fname}, {mode}) Number set {fname} file permissions to {mode} setline({lnum}, {line}) Number set line {lnum} to {line} ! setloclist({nr}, {list} [, {action}]) ! Number modify location list using {list} ! setloclist({nr}, {list}, {action}, {what}) ! Number modify specific location list props setmatches({list} [, {win}]) Number restore a list of matches setpos({expr}, {list}) Number set the {expr} position to {list} ! setqflist({list} [, {action}]) Number modify quickfix list using {list} ! setqflist({list}, {action}, {what}) ! Number modify specific quickfix list props setreg({n}, {v} [, {opt}]) Number set register to value and type settabvar({nr}, {varname}, {val}) none set {varname} in tab page {nr} to {val} settabwinvar({tabnr}, {winnr}, {varname}, {val}) *************** *** 9097,9103 **** Note that the list is not exactly the same as what |getqflist()| returns. ! {action} values: *E927* 'a' The items from {list} are added to the existing quickfix list. If there is no existing list, then a new list is created. --- 9143,9149 ---- Note that the list is not exactly the same as what |getqflist()| returns. ! {action} values: *setqflist-action* *E927* 'a' The items from {list} are added to the existing quickfix list. If there is no existing list, then a new list is created. *************** *** 9138,9144 **** 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| --- 9184,9191 ---- the last quickfix list. quickfixtextfunc function to get the text to display in the ! quickfix window. The value can be the name of ! a function or a funcref or a lambda. 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| *** ../vim-8.2.1254/runtime/doc/options.txt 2020-07-18 16:07:02.005864389 +0200 --- runtime/doc/options.txt 2020-07-20 21:24:51.730411122 +0200 *************** *** 5912,5918 **** 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. --- 5913,5920 ---- 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. The value can be the name of a function or a ! lambda. This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. *** ../vim-8.2.1254/runtime/doc/quickfix.txt 2020-06-11 19:35:48.741325222 +0200 --- runtime/doc/quickfix.txt 2020-07-20 21:24:51.730411122 +0200 *************** *** 1965,1971 **** window for each entry from start_idx to end_idx. The function can obtain information about the entries using the |getqflist()| function and specifying the quickfix list identifier "id". For a location list, getloclist() function ! can be used with the 'winid' argument. If a quickfix or location list specific customization is needed, then the 'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or --- 1964,1973 ---- window for each entry from start_idx to end_idx. The function can obtain information about the entries using the |getqflist()| function and specifying the quickfix list identifier "id". For a location list, getloclist() function ! can be used with the 'winid' argument. If an empty list is returned, then the ! default format is used to display all the entries. If an item in the returned ! list is an empty string, then the default format is used to display the ! corresponding entry. If a quickfix or location list specific customization is needed, then the 'quickfixtextfunc' attribute of the list can be set using the |setqflist()| or *** ../vim-8.2.1254/src/channel.c 2020-06-07 20:49:02.073891895 +0200 --- src/channel.c 2020-07-20 21:24:51.730411122 +0200 *************** *** 1101,1127 **** return channel; } - /* - * Copy callback from "src" to "dest", incrementing the refcounts. - */ - static void - copy_callback(callback_T *dest, callback_T *src) - { - dest->cb_partial = src->cb_partial; - if (dest->cb_partial != NULL) - { - dest->cb_name = src->cb_name; - dest->cb_free_name = FALSE; - ++dest->cb_partial->pt_refcount; - } - else - { - dest->cb_name = vim_strsave(src->cb_name); - dest->cb_free_name = TRUE; - func_ref(src->cb_name); - } - } - static void free_set_callback(callback_T *cbp, callback_T *callback) { --- 1101,1106 ---- *** ../vim-8.2.1254/src/evalvars.c 2020-07-12 17:07:01.024810908 +0200 --- src/evalvars.c 2020-07-20 21:24:51.730411122 +0200 *************** *** 3849,3854 **** --- 3849,3875 ---- } /* + * Copy callback from "src" to "dest", incrementing the refcounts. + */ + void + copy_callback(callback_T *dest, callback_T *src) + { + dest->cb_partial = src->cb_partial; + if (dest->cb_partial != NULL) + { + dest->cb_name = src->cb_name; + dest->cb_free_name = FALSE; + ++dest->cb_partial->pt_refcount; + } + else + { + dest->cb_name = vim_strsave(src->cb_name); + dest->cb_free_name = TRUE; + func_ref(src->cb_name); + } + } + + /* * Unref/free "callback" returned by get_callback() or set_callback(). */ void *** ../vim-8.2.1254/src/optionstr.c 2020-07-18 16:07:02.005864389 +0200 --- src/optionstr.c 2020-07-20 21:24:51.730411122 +0200 *************** *** 2255,2260 **** --- 2255,2268 ---- # endif #endif + #ifdef FEAT_QUICKFIX + else if (varp == &p_qftf) + { + if (qf_process_qftf_option() == FALSE) + errmsg = e_invarg; + } + #endif + // Options that are a list of flags. else { *** ../vim-8.2.1254/src/proto/evalvars.pro 2020-07-01 18:29:23.685143414 +0200 --- src/proto/evalvars.pro 2020-07-20 21:24:51.730411122 +0200 *************** *** 88,92 **** --- 88,93 ---- callback_T get_callback(typval_T *arg); void put_callback(callback_T *cb, typval_T *tv); void set_callback(callback_T *dest, callback_T *src); + void copy_callback(callback_T *dest, callback_T *src); void free_callback(callback_T *callback); /* vim: set ft=c : */ *** ../vim-8.2.1254/src/proto/quickfix.pro 2019-12-12 12:55:31.000000000 +0100 --- src/proto/quickfix.pro 2020-07-20 21:24:51.730411122 +0200 *************** *** 15,20 **** --- 15,21 ---- void ex_copen(exarg_T *eap); void ex_cbottom(exarg_T *eap); linenr_T qf_current_entry(win_T *wp); + int qf_process_qftf_option(void); int grep_internal(cmdidx_T cmdidx); void ex_make(exarg_T *eap); int qf_get_size(exarg_T *eap); *** ../vim-8.2.1254/src/quickfix.c 2020-07-01 13:03:58.190648795 +0200 --- src/quickfix.c 2020-07-20 21:24:51.734411111 +0200 *************** *** 82,88 **** 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; --- 82,88 ---- 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 ! callback_T qftf_cb; // 'quickfixtextfunc' callback function struct dir_stack_T *qf_dir_stack; char_u *qf_directory; *************** *** 161,166 **** --- 161,169 ---- static efm_T *fmt_start = NULL; // cached across qf_parse_line() calls + // callback function for 'quickfixtextfunc' + static callback_T qftf_cb; + static void qf_new_list(qf_info_T *qi, char_u *qf_title); static int qf_add_entry(qf_list_T *qfl, char_u *dir, char_u *fname, char_u *module, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid); static void qf_free(qf_list_T *qfl); *************** *** 2279,2288 **** } 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) --- 2282,2291 ---- } else to_qfl->qf_ctx = NULL; ! if (from_qfl->qftf_cb.cb_name != NULL) ! copy_callback(&to_qfl->qftf_cb, &from_qfl->qftf_cb); else ! to_qfl->qftf_cb.cb_name = NULL; if (from_qfl->qf_count) if (copy_loclist_entries(from_qfl, to_qfl) == FAIL) *************** *** 3818,3824 **** 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; } --- 3821,3827 ---- VIM_CLEAR(qfl->qf_title); free_tv(qfl->qf_ctx); qfl->qf_ctx = NULL; ! free_callback(&qfl->qftf_cb); qfl->qf_id = 0; qfl->qf_changedtick = 0L; } *************** *** 4349,4354 **** --- 4352,4400 ---- } /* + * Process the 'quickfixtextfunc' option value. + */ + int + qf_process_qftf_option(void) + { + typval_T *tv; + callback_T cb; + + if (p_qftf == NULL || *p_qftf == NUL) + { + free_callback(&qftf_cb); + return TRUE; + } + + if (*p_qftf == '{') + { + // Lambda expression + tv = eval_expr(p_qftf, NULL); + if (tv == NULL) + return FALSE; + } + else + { + // treat everything else as a function name string + tv = alloc_string_tv(vim_strsave(p_qftf)); + if (tv == NULL) + return FALSE; + } + + cb = get_callback(tv); + if (cb.cb_name == NULL) + { + free_tv(tv); + return FALSE; + } + + free_callback(&qftf_cb); + set_callback(&qftf_cb, &cb); + free_tv(tv); + return TRUE; + } + + /* * Update the w:quickfix_title variable in the quickfix/location list window */ static void *************** *** 4424,4430 **** int len; buf_T *errbuf; ! if (qftf_str != NULL) vim_strncpy(IObuff, qftf_str, IOSIZE - 1); else { --- 4470,4478 ---- int len; buf_T *errbuf; ! // If the 'quickfixtextfunc' function returned an non-empty custom string ! // for this entry, then use it. ! if (qftf_str != NULL && *qftf_str != NUL) vim_strncpy(IObuff, qftf_str, IOSIZE - 1); else { *************** *** 4501,4521 **** return OK; } static list_T * call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx) { ! char_u *qftf = p_qftf; list_T *qftf_list = NULL; // If 'quickfixtextfunc' is set, then use the user-supplied function to get // the text to display. Use the local value of 'quickfixtextfunc' if it is // set. ! if (qfl->qf_qftf != NULL) ! qftf = qfl->qf_qftf; ! if (qftf != NULL && *qftf != NUL) { typval_T args[1]; dict_T *d; // create the dict argument if ((d = dict_alloc_lock(VAR_FIXED)) == NULL) --- 4549,4574 ---- return OK; } + /* + * Call the 'quickfixtextfunc' function to get the list of lines to display in + * the quickfix window for the entries 'start_idx' to 'end_idx'. + */ static list_T * call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long end_idx) { ! callback_T *cb = &qftf_cb; list_T *qftf_list = NULL; // If 'quickfixtextfunc' is set, then use the user-supplied function to get // the text to display. Use the local value of 'quickfixtextfunc' if it is // set. ! if (qfl->qftf_cb.cb_name != NULL) ! cb = &qfl->qftf_cb; ! if (cb != NULL && cb->cb_name != NULL) { typval_T args[1]; dict_T *d; + typval_T rettv; // create the dict argument if ((d = dict_alloc_lock(VAR_FIXED)) == NULL) *************** *** 4529,4536 **** args[0].v_type = VAR_DICT; args[0].vval.v_dict = d; ! qftf_list = call_func_retlist(qftf, 1, args); ! --d->dv_refcount; } return qftf_list; --- 4582,4598 ---- args[0].v_type = VAR_DICT; args[0].vval.v_dict = d; ! qftf_list = NULL; ! if (call_callback(cb, 0, &rettv, 1, args) != FAIL) ! { ! if (rettv.v_type == VAR_LIST) ! { ! qftf_list = rettv.vval.v_list; ! qftf_list->lv_refcount++; ! } ! clear_tv(&rettv); ! } ! dict_unref(d); } return qftf_list; *************** *** 4569,4574 **** --- 4631,4637 ---- if (qfl != NULL) { char_u dirname[MAXPATHL]; + int invalid_val = FALSE; *dirname = NUL; *************** *** 4593,4601 **** { char_u *qftf_str = NULL; ! if (qftf_li != NULL) ! // Use the text supplied by the user defined function qftf_str = tv_get_string_chk(&qftf_li->li_tv); if (qf_buf_add_line(buf, lnum, qfp, dirname, qftf_str) == FAIL) break; --- 4656,4670 ---- { char_u *qftf_str = NULL; ! // Use the text supplied by the user defined function (if any). ! // If the returned value is not string, then ignore the rest ! // of the returned values and use the default. ! if (qftf_li != NULL && !invalid_val) ! { qftf_str = tv_get_string_chk(&qftf_li->li_tv); + if (qftf_str == NULL) + invalid_val = TRUE; + } if (qf_buf_add_line(buf, lnum, qfp, dirname, qftf_str) == FAIL) break; *************** *** 6515,6521 **** QF_GETLIST_TICK = 0x100, QF_GETLIST_FILEWINID = 0x200, QF_GETLIST_QFBUFNR = 0x400, ! QF_GETLIST_ALL = 0x7FF, }; /* --- 6584,6591 ---- QF_GETLIST_TICK = 0x100, QF_GETLIST_FILEWINID = 0x200, QF_GETLIST_QFBUFNR = 0x400, ! QF_GETLIST_QFTF = 0x800, ! QF_GETLIST_ALL = 0xFFF, }; /* *************** *** 6644,6649 **** --- 6714,6722 ---- if (dict_find(what, (char_u *)"qfbufnr", -1) != NULL) flags |= QF_GETLIST_QFBUFNR; + if (dict_find(what, (char_u *)"quickfixtextfunc", -1) != NULL) + flags |= QF_GETLIST_QFTF; + return flags; } *************** *** 6738,6743 **** --- 6811,6818 ---- status = dict_add_number(retdict, "filewinid", 0); if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) status = qf_getprop_qfbufnr(qi, retdict); + if ((status == OK) && (flags & QF_GETLIST_QFTF)) + status = dict_add_string(retdict, "quickfixtextfunc", (char_u *)""); return status; } *************** *** 6837,6842 **** --- 6912,6939 ---- } /* + * Return the 'quickfixtextfunc' function of a quickfix/location list + */ + static int + qf_getprop_qftf(qf_list_T *qfl, dict_T *retdict) + { + int status; + + if (qfl->qftf_cb.cb_name != NULL) + { + typval_T tv; + + put_callback(&qfl->qftf_cb, &tv); + status = dict_add_tv(retdict, "quickfixtextfunc", &tv); + clear_tv(&tv); + } + else + status = dict_add_string(retdict, "quickfixtextfunc", (char_u *)""); + + return status; + } + + /* * Return quickfix/location list details (title) as a * dictionary. 'what' contains the details to return. If 'list_idx' is -1, * then current list is used. Otherwise the specified list is used. *************** *** 6899,6904 **** --- 6996,7003 ---- status = qf_getprop_filewinid(wp, qi, retdict); if ((status == OK) && (flags & QF_GETLIST_QFBUFNR)) status = qf_getprop_qfbufnr(qi, retdict); + if ((status == OK) && (flags & QF_GETLIST_QFTF)) + status = qf_getprop_qftf(qfl, retdict); return status; } *************** *** 7260,7269 **** 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; } --- 7359,7370 ---- static int qf_setprop_qftf(qf_info_T *qi UNUSED, qf_list_T *qfl, dictitem_T *di) { ! callback_T cb; ! ! free_callback(&qfl->qftf_cb); ! cb = get_callback(&di->di_tv); ! if (cb.cb_name != NULL && *cb.cb_name != NUL) ! set_callback(&qfl->qftf_cb, &cb); return OK; } *** ../vim-8.2.1254/src/testdir/test_quickfix.vim 2020-07-11 22:14:54.318422203 +0200 --- src/testdir/test_quickfix.vim 2020-07-20 21:24:51.734411111 +0200 *************** *** 3490,3502 **** if a:cchar == 'c' call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0, ! \ 'title' : '', 'winid' : 0, 'changedtick': 0}, ! \ g:Xgetlist({'all' : 0})) else call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, \ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', \ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0, ! \ 'qfbufnr' : 0}, \ g:Xgetlist({'all' : 0})) endif --- 3490,3502 ---- if a:cchar == 'c' call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, \ 'items' : [], 'nr' : 0, 'size' : 0, 'qfbufnr' : 0, ! \ 'title' : '', 'winid' : 0, 'changedtick': 0, ! \ 'quickfixtextfunc' : ''}, g:Xgetlist({'all' : 0})) else call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, \ 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', \ 'winid' : 0, 'changedtick': 0, 'filewinid' : 0, ! \ 'qfbufnr' : 0, 'quickfixtextfunc' : ''}, \ g:Xgetlist({'all' : 0})) endif *************** *** 3535,3546 **** if a:cchar == 'c' call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'qfbufnr' : qfbufnr, \ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0})) else call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0}, \ g:Xgetlist({'id' : qfid, 'all' : 0})) endif --- 3535,3547 ---- if a:cchar == 'c' call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'qfbufnr' : qfbufnr, 'quickfixtextfunc' : '', \ 'changedtick' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0})) else call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0, ! \ 'quickfixtextfunc' : ''}, \ g:Xgetlist({'id' : qfid, 'all' : 0})) endif *************** *** 3557,3569 **** if a:cchar == 'c' call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'changedtick' : 0, 'qfbufnr' : qfbufnr}, ! \ g:Xgetlist({'nr' : 5, 'all' : 0})) else call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0}, ! \ g:Xgetlist({'nr' : 5, 'all' : 0})) endif endfunc --- 3558,3570 ---- if a:cchar == 'c' call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'changedtick' : 0, 'qfbufnr' : qfbufnr, ! \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0})) else call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], \ 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0, ! \ 'changedtick' : 0, 'filewinid' : 0, 'qfbufnr' : 0, ! \ 'quickfixtextfunc' : ''}, g:Xgetlist({'nr' : 5, 'all' : 0})) endif endfunc *************** *** 4865,4870 **** --- 4866,4874 ---- set efm=%f:%l:%c:%m set quickfixtextfunc=Tqfexpr + call assert_equal('Tqfexpr', &quickfixtextfunc) + call assert_equal('', + \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc) Xexpr ['F1:10:2:green', 'F1:20:4:blue'] Xwindow call assert_equal('F1-L10C2-green', getline(1)) *************** *** 4901,4912 **** --- 4905,4919 ---- call assert_equal('Line 10, Col 2', getline(1)) call assert_equal('Line 20, Col 4', getline(2)) Xclose + call assert_equal(function('PerQfText'), + \ g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc) " Add entries to the list when the quickfix buffer is hidden Xaddexpr ['F1:30:6:red'] Xwindow call assert_equal('Line 30, Col 6', getline(3)) Xclose call g:Xsetlist([], 'r', {'quickfixtextfunc' : ''}) + call assert_equal('', g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc) set quickfixtextfunc& delfunc PerQfText *************** *** 4941,4952 **** call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']", \ 'E730:') call assert_fails('Xwindow', 'E730:') ! call assert_equal(['one', 'F1|20 col 4| blue', 'two'], getline(1, '$')) Xclose set quickfixtextfunc& delfunc Xqftext delfunc Xqftext2 endfunc func Test_qftextfunc() --- 4948,5000 ---- call assert_fails("Xexpr ['F1:10:2:green', 'F1:20:4:blue', 'F1:30:6:red']", \ 'E730:') call assert_fails('Xwindow', 'E730:') ! call assert_equal(['one', 'F1|20 col 4| blue', 'F1|30 col 6| red'], ! \ getline(1, '$')) Xclose set quickfixtextfunc& delfunc Xqftext delfunc Xqftext2 + + " set the global option to a lambda function + set quickfixtextfunc={d\ ->\ map(g:Xgetlist({'id'\ :\ d.id,\ 'items'\ :\ 1}).items[d.start_idx-1:d.end_idx-1],\ 'v:val.text')} + Xexpr ['F1:10:2:green', 'F1:20:4:blue'] + Xwindow + call assert_equal(['green', 'blue'], getline(1, '$')) + Xclose + call assert_equal("{d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], 'v:val.text')}", &quickfixtextfunc) + set quickfixtextfunc& + + " use a lambda function that returns an empty list + set quickfixtextfunc={d\ ->\ []} + Xexpr ['F1:10:2:green', 'F1:20:4:blue'] + Xwindow + call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'], + \ getline(1, '$')) + Xclose + set quickfixtextfunc& + + " use a lambda function that returns a list with empty strings + set quickfixtextfunc={d\ ->\ ['',\ '']} + Xexpr ['F1:10:2:green', 'F1:20:4:blue'] + Xwindow + call assert_equal(['F1|10 col 2| green', 'F1|20 col 4| blue'], + \ getline(1, '$')) + Xclose + set quickfixtextfunc& + + " set the per-quickfix list text function to a lambda function + call g:Xsetlist([], ' ', + \ {'quickfixtextfunc' : + \ {d -> map(g:Xgetlist({'id' : d.id, 'items' : 1}).items[d.start_idx-1:d.end_idx-1], + \ "'Line ' .. v:val.lnum .. ', Col ' .. v:val.col")}}) + 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 assert_match("function('\\d\\+')", string(g:Xgetlist({'quickfixtextfunc' : 1}).quickfixtextfunc)) + call g:Xsetlist([], 'f') endfunc func Test_qftextfunc() *** ../vim-8.2.1254/src/version.c 2020-07-20 21:21:26.950936122 +0200 --- src/version.c 2020-07-20 21:26:11.970205304 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 1255, /**/ -- hundred-and-one symptoms of being an internet addict: 47. You are so familiar with the WWW that you find the search engines useless. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///