# HG changeset patch # User Bram Moolenaar # Date 1547215208 -3600 # Node ID 90c8ff9c19ee64f8a3e457f4585410cf018f6f7e # Parent aabfc000d8a81edb501a3b3f5336cae8e7086654 patch 8.1.0720: cannot easily change the current quickfx list index commit https://github.com/vim/vim/commit/5b69c22fd2bf0c0d32aab90ee4c7ef74259d2c4c Author: Bram Moolenaar Date: Fri Jan 11 14:50:06 2019 +0100 patch 8.1.0720: cannot easily change the current quickfx list index Problem: Cannot easily change the current quickfx list index. Solution: Add the "idx" argument to setqflist(). (Yegappan Lakshmanan, closes #3701) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.1. Last change: 2019 Jan 06 +*eval.txt* For Vim version 8.1. Last change: 2019 Jan 11 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2322,7 +2322,7 @@ prop_clear({lnum} [, {lnum-end} [, {prop none remove all text properties prop_find({props} [, {direction}]) Dict search for a text property -prop_list({lnum} [, {props}) List text properties in {lnum} +prop_list({lnum} [, {props}) List text properties in {lnum} prop_remove({props} [, {lnum} [, {lnum-end}]]) Number remove a text property prop_type_add({name}, {props}) none define a new property type @@ -3979,7 +3979,7 @@ feedkeys({string} [, {mode}]) *feedke stuck, waiting for a character to be typed before the script continues. Note that if you manage to call feedkeys() while - executing commands, thus calling it recursively, the + executing commands, thus calling it recursively, then all typehead will be consumed by the last call. '!' When used with 'x' will not end Insert mode. Can be used in a test when a timer is set to exit Insert mode @@ -4794,7 +4794,7 @@ getloclist({nr} [, {what}]) *getlocli If {what} contains 'filewinid', then returns the id of the window used to display files from the location list. This field is applicable only when called from a location list - window. + window. See |location-list-file-window| for more details. getmatches() *getmatches()* Returns a |List| with all matches previously defined by @@ -4885,7 +4885,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 list + idx index of the current entry in the quickfix + list specified by 'id' or 'nr'. + See |quickfix-index| items quickfix list entries lines parse a list of lines using 'efm' and return the resulting entries. Only a |List| type is @@ -5084,7 +5086,7 @@ getwinpos([{timeout}]) *getwinpos()* When using a value less than 10 and no response is received within that time, a previously reported position is returned, if available. This can be used to poll for the position and - do some work in the mean time: > + do some work in the meantime: > while 1 let res = getwinpos(1) if res[0] >= 0 @@ -6336,7 +6338,7 @@ mode([expr]) Return a string that indica nov Operator-pending (forced characterwise |o_v|) noV Operator-pending (forced linewise |o_V|) noCTRL-V Operator-pending (forced blockwise |o_CTRL-V|); - CTRL-V is one character + CTRL-V is one character niI Normal using |i_CTRL-O| in |Insert-mode| niR Normal using |i_CTRL-O| in |Replace-mode| niV Normal using |i_CTRL-O| in |Virtual-Replace-mode| @@ -6708,12 +6710,12 @@ prop_add({lnum}, {col}, {props}) for a property that does not continue in another line; can be zero end_lnum line number for the end of text - end_col column just after the text; not used when "length" - is present; when {col} and "end_col" are - equal, and "end_lnum" is omitted or equal to - {lnum}, this is a zero-width text property + end_col column just after the text; not used when + "length" is present; when {col} and "end_col" + are equal, and "end_lnum" is omitted or equal + to {lnum}, this is a zero-width text property bufnr buffer to add the property to; when omitted - the current buffer is used + the current buffer is used id user defined ID for the property; when omitted zero is used type name of the text property type @@ -6758,7 +6760,7 @@ prop_find({props} [, {direction}]) start position with "lnum" and "col" must be given; when omitted the current buffer is used - lnum" start in this line (when omitted start + lnum start in this line (when omitted start at the cursor) col start at this column (when omitted and "lnum" is given: use column 1, @@ -6776,7 +6778,7 @@ prop_find({props} [, {direction}]) See |text-properties| for information about text properties. -prop_list({lnum} [, {props}]) *prop_list()* +prop_list({lnum} [, {props}]) *prop_list()* Return a List with all text properties in line {lnum}. When {props} contains a "bufnr" item, use this buffer instead @@ -7701,16 +7703,22 @@ setqflist({list} [, {action} [, {what}]] efm errorformat to use when parsing text from "lines". If this is not present, then the 'errorformat' option value is used. + See |quickfix-parse| id quickfix list identifier |quickfix-ID| + idx index of the current entry in the quickfix + list specified by 'id' or 'nr'. If set to '$', + then the last entry in the list is set as the + current entry. See |quickfix-index| items list of quickfix entries. Same as the {list} argument. lines use 'errorformat' to parse a list of lines and add the resulting entries to the quickfix list {nr} or {id}. Only a |List| value is supported. + See |quickfix-parse| nr list number in the quickfix stack; zero means the current quickfix list and "$" means - the last quickfix list - title quickfix list title text + the last quickfix list. + 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 is modified. When creating a new quickfix list, "nr" can be @@ -8026,7 +8034,7 @@ sign_place({id}, {group}, {name}, {expr} the sign group name. To use the global sign group, use an empty string. {group} functions as a namespace for {id}, thus two groups can use the same IDs. Refer to |sign-identifier| - for more information. + and |sign-group| for more information. {name} refers to a defined sign. {expr} refers to a buffer name or number. For the accepted @@ -10091,9 +10099,9 @@ vim_starting True while initial source' *vim_starting* viminfo Compiled with viminfo support. virtualedit Compiled with 'virtualedit' option. -visual Compiled with Visual mode. -visualextra Compiled with extra Visual mode commands. - |blockwise-operators|. +visual Compiled with Visual mode. (always true) +visualextra Compiled with extra Visual mode commands. (always + true) |blockwise-operators|. vms VMS version of Vim. vreplace Compiled with |gR| and |gr| commands. vtp Compiled for vcon support |+vtp| (check vcon to find diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt --- a/runtime/doc/quickfix.txt +++ b/runtime/doc/quickfix.txt @@ -1,4 +1,4 @@ -*quickfix.txt* For Vim version 8.1. Last change: 2018 Dec 27 +*quickfix.txt* For Vim version 8.1. Last change: 2019 Jan 09 VIM REFERENCE MANUAL by Bram Moolenaar @@ -56,6 +56,7 @@ A location list is a window-local quickf like `:lvimgrep`, `:lgrep`, `:lhelpgrep`, `:lmake`, etc., which create a location list instead of a quickfix list as the corresponding `:vimgrep`, `:grep`, `:helpgrep`, `:make` do. + *location-list-file-window* A location list is associated with a window and each window can have a separate location list. A location list can be associated with only one window. The location list is independent of the quickfix list. @@ -364,6 +365,23 @@ modify the title of a quickfix and locat call setloclist(3, [], 'a', {'title' : 'Cmd output'}) echo getloclist(3, {'title' : 1}) < + *quickfix-index* +When you jump to a quickfix/location list entry using any of the quickfix +commands (e.g. |cc|, |cnext|, |cprev|, etc.), that entry becomes the currently +selected entry. The index of the currently selected entry in a +quickfix/location list can be obtained using the getqflist()/getloclist() +functions. Examples: > + echo getqflist({'idx' : 0}).idx + echo getqflist({'id' : qfid, 'idx' : 0}).idx + echo getloclist(2, {'idx' : 0}).idx +< +For a new quickfix list, the first entry is selected and the index is 1. Any +entry in any quickfix/location list can be set as the currently selected entry +using the setqflist() function. Examples: > + call setqflist([], 'a', {'idx' : 12}) + call setqflist([], 'a', {'id' : qfid, 'idx' : 7}) + call setloclist(1, [], 'a', {'idx' : 7}) +< *quickfix-size* You can get the number of entries (size) in a quickfix and a location list using the |getqflist()| and |getloclist()| functions respectively. Examples: > @@ -657,6 +675,9 @@ using these functions are below: " get the location list window id of the third window :echo getloclist(3, {'winid' : 0}).winid + + " get the file window id of a location list window (winnr: 4) + :echo getloclist(4, {'filewinid' : 0}).filewinid < *setqflist-examples* The |setqflist()| and |setloclist()| functions can be used to set the various @@ -671,6 +692,9 @@ using these functions are below: " set the title of the current quickfix list :call setqflist([], 'a', {'title' : 'Mytitle'}) + " change the current entry in the list specified by an identifier + :call setqflist([], 'a', {'id' : qfid, 'idx' : 10}) + " set the context of a quickfix list specified by an identifier :call setqflist([], 'a', {'id' : qfid, 'context' : {'val' : 100}}) @@ -1551,7 +1575,7 @@ The backslashes before the pipe characte recognized as a command separator. The backslash before each space is required for the set command. - *cfilter-plugin* *:Cfilter* *:Lfilter* + *cfilter-plugin* *:Cfilter* *:Lfilter* If you have too many matching messages, you can use the cfilter plugin to reduce the number of entries. Load the plugin with: > packadd cfilter diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -3266,13 +3266,7 @@ qf_jump_to_buffer( } /* - * Jump to a quickfix line. - * If dir == FORWARD go "errornr" valid entries forward. - * If dir == BACKWARD go "errornr" valid entries backward. - * If dir == FORWARD_FILE go "errornr" valid entries files backward. - * If dir == BACKWARD_FILE go "errornr" valid entries files backward - * else if "errornr" is zero, redisplay the same line - * else go to entry "errornr". + * Jump to a quickfix line and try to use an existing window. */ void qf_jump(qf_info_T *qi, @@ -3284,7 +3278,14 @@ qf_jump(qf_info_T *qi, } /* - * As qf_info(). + * Jump to a quickfix line. + * If dir == 0 go to entry "errornr". + * If dir == FORWARD go "errornr" valid entries forward. + * If dir == BACKWARD go "errornr" valid entries backward. + * If dir == FORWARD_FILE go "errornr" valid entries files backward. + * If dir == BACKWARD_FILE go "errornr" valid entries files backward + * else if "errornr" is zero, redisplay the same line + * If 'forceit' is TRUE, then can discard changes to the current buffer. * If 'newwin' is TRUE, then open the file in a new window. */ void @@ -3687,7 +3688,7 @@ qf_history(exarg_T *eap) if (is_loclist_cmd(eap->cmdidx)) qi = GET_LOC_LIST(curwin); - if (qf_stack_empty(qi) || qf_list_empty(qi, qi->qf_curlist)) + if (qf_stack_empty(qi)) MSG(_("No entries")); else for (i = 0; i < qi->qf_listcount; ++i) @@ -6549,6 +6550,50 @@ qf_setprop_context(qf_list_T *qfl, dicti } /* + * Set the current index in the specified quickfix list + */ + static int +qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, dictitem_T *di) +{ + int denote = FALSE; + int newidx; + int old_qfidx; + qfline_T *qf_ptr; + + // If the specified index is '$', then use the last entry + if (di->di_tv.v_type == VAR_STRING + && di->di_tv.vval.v_string != NULL + && STRCMP(di->di_tv.vval.v_string, "$") == 0) + newidx = qfl->qf_count; + else + { + // Otherwise use the specified index + newidx = tv_get_number_chk(&di->di_tv, &denote); + if (denote) + return FAIL; + } + + if (newidx < 1) // sanity check + return FAIL; + if (newidx > qfl->qf_count) + newidx = qfl->qf_count; + + old_qfidx = qfl->qf_index; + qf_ptr = get_nth_entry(qfl, newidx, &newidx); + if (qf_ptr == NULL) + return FAIL; + qfl->qf_ptr = qf_ptr; + qfl->qf_index = newidx; + + // If the current list is modified and it is displayed in the quickfix + // window, then Update it. + if (qi->qf_lists[qi->qf_curlist].qf_id == qfl->qf_id) + qf_win_pos_update(qi, old_qfidx); + + return OK; +} + +/* * Set quickfix/location list properties (title, items, context). * Also used to add items from parsing a list of lines. * Used by the setqflist() and setloclist() Vim script functions. @@ -6585,6 +6630,8 @@ qf_set_properties(qf_info_T *qi, dict_T retval = qf_setprop_items_from_lines(qi, qf_idx, what, di, action); if ((di = dict_find(what, (char_u *)"context", -1)) != NULL) retval = qf_setprop_context(qfl, di); + if ((di = dict_find(what, (char_u *)"idx", -1)) != NULL) + retval = qf_setprop_curidx(qi, qfl, di); if (retval == OK) qf_list_changed(qfl); diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -1811,6 +1811,13 @@ func HistoryTest(cchar) call g:Xsetlist([], 'f') let l = split(execute(a:cchar . 'hist'), "\n") call assert_equal('No entries', l[0]) + + " An empty list should still show the stack history + call g:Xsetlist([]) + let res = split(execute(a:cchar . 'hist'), "\n") + call assert_equal('> error list 1 of 1; 0 ' . common, res[0]) + + call g:Xsetlist([], 'f') endfunc func Test_history() @@ -2068,6 +2075,56 @@ func Test_qf_property() call Xproperty_tests('l') endfunc +" Test for setting the current index in the location/quickfix list +func Xtest_setqfidx(cchar) + call s:setup_commands(a:cchar) + + Xgetexpr "F1:10:1:Line1\nF2:20:2:Line2\nF3:30:3:Line3" + Xgetexpr "F4:10:1:Line1\nF5:20:2:Line2\nF6:30:3:Line3" + Xgetexpr "F7:10:1:Line1\nF8:20:2:Line2\nF9:30:3:Line3" + + call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 2}) + call g:Xsetlist([], 'a', {'nr' : 2, 'idx' : 2}) + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 3}) + Xolder 2 + Xopen + call assert_equal(3, line('.')) + Xnewer + call assert_equal(2, line('.')) + Xnewer + call assert_equal(2, line('.')) + " Update the current index with the quickfix window open + wincmd w + call g:Xsetlist([], 'a', {'nr' : 3, 'idx' : 3}) + Xopen + call assert_equal(3, line('.')) + Xclose + + " Set the current index to the last entry + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : '$'}) + call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) + " A large value should set the index to the last index + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 1}) + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 999}) + call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) + " Invalid index values + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : -1}) + call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 0}) + call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) + call g:Xsetlist([], 'a', {'nr' : 1, 'idx' : 'xx'}) + call assert_equal(3, g:Xgetlist({'nr' : 1, 'idx' : 0}).idx) + call assert_fails("call g:Xsetlist([], 'a', {'nr':1, 'idx':[]})", 'E745:') + + call g:Xsetlist([], 'f') + new | only +endfunc + +func Test_setqfidx() + call Xtest_setqfidx('c') + call Xtest_setqfidx('l') +endfunc + " Tests for the QuickFixCmdPre/QuickFixCmdPost autocommands func QfAutoCmdHandler(loc, cmd) call add(g:acmds, a:loc . a:cmd) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -796,6 +796,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 720, +/**/ 719, /**/ 718,