To: vim_dev@googlegroups.com Subject: Patch 8.1.0720 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0720 Problem: Cannot easily change the current quickfx list index. Solution: Add the "idx" argument to setqflist(). (Yegappan Lakshmanan, closes #3701) Files: runtime/doc/eval.txt, runtime/doc/quickfix.txt, src/quickfix.c, src/testdir/test_quickfix.vim *** ../vim-8.1.0719/runtime/doc/eval.txt 2019-01-11 13:42:31.676331183 +0100 --- runtime/doc/eval.txt 2019-01-11 14:44:08.978341403 +0100 *************** *** 4862,4868 **** 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 items quickfix list entries lines parse a list of lines using 'efm' and return the resulting entries. Only a |List| type is --- 4885,4893 ---- 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'. ! 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 *************** *** 5032,5039 **** Each List item is a Dictionary with the following entries: bufnr number of buffer in the window height window height (excluding winbar) - winbar 1 if the window has a toolbar, 0 - otherwise loclist 1 if showing a location list {only with the +quickfix feature} quickfix 1 if quickfix or location list window --- 5057,5062 ---- *************** *** 5044,5049 **** --- 5067,5074 ---- variables a reference to the dictionary with window-local variables width window width + winbar 1 if the window has a toolbar, 0 + otherwise wincol leftmost screen column of the window, col from |win_screenpos()| winid |window-ID| *************** *** 7675,7690 **** efm errorformat to use when parsing text from "lines". If this is not present, then the 'errorformat' option value is used. id quickfix list identifier |quickfix-ID| 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. nr list number in the quickfix stack; zero means the current quickfix list and "$" means ! the last quickfix list ! title quickfix list title text 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 --- 7703,7724 ---- 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. 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 *** ../vim-8.1.0719/runtime/doc/quickfix.txt 2018-08-21 19:22:00.366591999 +0200 --- runtime/doc/quickfix.txt 2019-01-11 14:44:08.978341403 +0100 *************** *** 46,52 **** *quickfix-ID* Each quickfix list has a unique identifier called the quickfix ID and this ! number will not change within a Vim session. The getqflist() function can be used to get the identifier assigned to a list. There is also a quickfix list number which may change whenever more than ten lists are added to a quickfix stack. --- 46,52 ---- *quickfix-ID* Each quickfix list has a unique identifier called the quickfix ID and this ! number will not change within a Vim session. The |getqflist()| function can be used to get the identifier assigned to a list. There is also a quickfix list number which may change whenever more than ten lists are added to a quickfix stack. *************** *** 56,61 **** --- 56,62 ---- 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. *************** *** 68,74 **** Every quickfix and location list has a read-only changedtick variable that tracks the total number of changes made to the list. Every time the quickfix list is modified, this count is incremented. This can be used to perform an ! action only when the list has changed. The getqflist() and getloclist() functions can be used to query the current value of changedtick. You cannot change the changedtick variable. --- 69,75 ---- Every quickfix and location list has a read-only changedtick variable that tracks the total number of changes made to the list. Every time the quickfix list is modified, this count is incremented. This can be used to perform an ! action only when the list has changed. The |getqflist()| and |getloclist()| functions can be used to query the current value of changedtick. You cannot change the changedtick variable. *************** *** 364,369 **** --- 365,387 ---- 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: > *************** *** 602,608 **** echo getloclist(2, {'winid' : 1}).winid < *getqflist-examples* ! The getqflist() and getloclist() functions can be used to get the various attributes of a quickfix and location list respectively. Some examples for using these functions are below: > --- 620,626 ---- echo getloclist(2, {'winid' : 1}).winid < *getqflist-examples* ! The |getqflist()| and |getloclist()| functions can be used to get the various attributes of a quickfix and location list respectively. Some examples for using these functions are below: > *************** *** 657,665 **** " get the location list window id of the third window :echo getloclist(3, {'winid' : 0}).winid < *setqflist-examples* ! The setqflist() and setloclist() functions can be used to set the various attributes of a quickfix and location list respectively. Some examples for using these functions are below: > --- 675,686 ---- " 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 attributes of a quickfix and location list respectively. Some examples for using these functions are below: > *************** *** 671,676 **** --- 692,700 ---- " 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}}) *************** *** 898,904 **** 'smartcase' is not used. If {pattern} is empty (e.g. // is specified), the last used search pattern is used. |last-pattern| ! When a number is put before the command this is used as the maximum number of matches to find. Use ":1vimgrep pattern file" to find only the first. --- 922,928 ---- 'smartcase' is not used. If {pattern} is empty (e.g. // is specified), the last used search pattern is used. |last-pattern| ! :{count}vim[grep] ... When a number is put before the command this is used as the maximum number of matches to find. Use ":1vimgrep pattern file" to find only the first. *************** *** 1551,1564 **** recognized as a command separator. The backslash before each space is required for the set command. ! *cfilter-plugin* 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 Then you can use these command: > ! :Cfilter[!] {pat} ! :Lfilter[!] {pat} :Cfilter creates a new quickfix list from entries matching {pat} in the current quickfix list. Both the file name and the text of the entries are --- 1575,1588 ---- recognized as a command separator. The backslash before each space is required for the set command. ! *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 Then you can use these command: > ! :Cfilter[!] /{pat}/ ! :Lfilter[!] /{pat}/ :Cfilter creates a new quickfix list from entries matching {pat} in the current quickfix list. Both the file name and the text of the entries are *** ../vim-8.1.0719/src/quickfix.c 2018-12-22 16:49:11.348536036 +0100 --- src/quickfix.c 2019-01-11 14:44:08.978341403 +0100 *************** *** 3266,3278 **** } /* ! * 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". */ void qf_jump(qf_info_T *qi, --- 3266,3272 ---- } /* ! * Jump to a quickfix line and try to use an existing window. */ void qf_jump(qf_info_T *qi, *************** *** 3284,3290 **** } /* ! * As qf_info(). * If 'newwin' is TRUE, then open the file in a new window. */ void --- 3278,3291 ---- } /* ! * 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,3693 **** if (is_loclist_cmd(eap->cmdidx)) qi = GET_LOC_LIST(curwin); ! if (qf_stack_empty(qi) || qf_list_empty(qi, qi->qf_curlist)) MSG(_("No entries")); else for (i = 0; i < qi->qf_listcount; ++i) --- 3688,3694 ---- if (is_loclist_cmd(eap->cmdidx)) qi = GET_LOC_LIST(curwin); ! if (qf_stack_empty(qi)) MSG(_("No entries")); else for (i = 0; i < qi->qf_listcount; ++i) *************** *** 6549,6554 **** --- 6550,6599 ---- } /* + * 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,6590 **** --- 6630,6637 ---- 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); *** ../vim-8.1.0719/src/testdir/test_quickfix.vim 2018-12-22 16:49:11.348536036 +0100 --- src/testdir/test_quickfix.vim 2019-01-11 14:44:08.978341403 +0100 *************** *** 1811,1816 **** --- 1811,1823 ---- 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,2073 **** --- 2075,2130 ---- 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) *** ../vim-8.1.0719/src/version.c 2019-01-11 14:37:16.689248837 +0100 --- src/version.c 2019-01-11 14:47:06.281089738 +0100 *************** *** 797,798 **** --- 797,800 ---- { /* Add new patch number below this line */ + /**/ + 720, /**/ -- hundred-and-one symptoms of being an internet addict: 159. You get excited whenever discussing your hard drive. /// 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 ///