changeset 15424:90c8ff9c19ee v8.1.0720

patch 8.1.0720: cannot easily change the current quickfx list index commit https://github.com/vim/vim/commit/5b69c22fd2bf0c0d32aab90ee4c7ef74259d2c4c Author: Bram Moolenaar <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Fri, 11 Jan 2019 15:00:08 +0100
parents aabfc000d8a8
children f96431b33513
files runtime/doc/eval.txt runtime/doc/quickfix.txt src/quickfix.c src/testdir/test_quickfix.vim src/version.c
diffstat 5 files changed, 169 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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);
--- 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)
--- 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,