Hi all,

When adding a new quickfix list using the setqflist() function,
currently the new list is added after the current quickfix list.
If there are lists after the current list, then they are all freed.

This will create issues for plugins which create and add
entries to a quickfix list asynchronously in the background.

For example, consider that the user has invoked a plugin
to run and process make output in the background and then
he invokes an identifier search plugin in the background.
Both of them are updating the quickfix lists in parallel.
The user goes back to the first list and browses the make
output. Now if he invokes another identifier search command,
then currently there is no way for the plugin to create the
new list at the end. The new list will be added after the first
list and the second list will be freed. This will impact the
previous invocation of the identifier search command.

The attached patch adds support for specifying the quickfix
list number to use when adding a new list. If the number is
set to '$', then the new quickfix list is added at the end of
the stack. if the 'nr' is not specified, then the current behavior
is retained.

- Yegappan

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index de142ee80..35e567093 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -7023,7 +7023,10 @@ setqflist({list} [, {action}[, {what}]])         
*setqflist()*
                        freed.
 
                If {action} is not present or is set to ' ', then a new list
-               is created.
+               is created. The new quickfix list is added after the current
+               quickfix list in the stack and all the following lists are
+               freed. To add a new quickfix list at the end of the stack,
+               set "nr" in {what} to '$'.
 
                If the optional {what} dictionary argument is supplied, then
                only the items listed in {what} are set. The first {list}
diff --git a/src/quickfix.c b/src/quickfix.c
index 75b58af3b..5415fc962 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -1368,7 +1368,9 @@ qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
 }
 
 /*
- * Prepare for adding a new quickfix list.
+ * Prepare for adding a new quickfix list. If the current list is in the
+ * middle of the stack, then all the following lists are freed and then
+ * the new list is added.
  */
     static void
 qf_new_list(qf_info_T *qi, char_u *qf_title)
@@ -4907,21 +4909,28 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int 
action, char_u *title)
 
            if ((action == ' ' || action == 'a') &&
                    qf_idx == qi->qf_listcount)
+           {
                /*
                 * When creating a new list, accept qf_idx pointing to the next
-                * non-available list
+                * non-available list and add the new list at the end of the
+                * stack.
                 */
                newlist = TRUE;
+               qf_idx = qi->qf_listcount - 1;
+           }
            else if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
                return FAIL;
-           else
+           else if (action != ' ')
                newlist = FALSE;        /* use the specified list */
        } else if (di->di_tv.v_type == VAR_STRING &&
-               STRCMP(di->di_tv.vval.v_string, "$") == 0 &&
-               qi->qf_listcount > 0)
+               STRCMP(di->di_tv.vval.v_string, "$") == 0)
        {
-           qf_idx = qi->qf_listcount - 1;
-           newlist = FALSE;
+           if (qi->qf_listcount > 0)
+               qf_idx = qi->qf_listcount - 1;
+           else if (newlist)
+               qf_idx = 0;
+           else
+               return FAIL;
        }
        else
            return FAIL;
@@ -4929,6 +4938,7 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int 
action, char_u *title)
 
     if (newlist)
     {
+       qi->qf_curlist = qf_idx;
        qf_new_list(qi, title);
        qf_idx = qi->qf_curlist;
     }
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 3acbd12df..8fa715395 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -11,7 +11,7 @@ func s:setup_commands(cchar)
     command! -nargs=* -bang Xlist <mods>clist<bang> <args>
     command! -nargs=* Xgetexpr <mods>cgetexpr <args>
     command! -nargs=* Xaddexpr <mods>caddexpr <args>
-    command! -nargs=* Xolder <mods>colder <args>
+    command! -nargs=* -count Xolder <mods><count>colder <args>
     command! -nargs=* Xnewer <mods>cnewer <args>
     command! -nargs=* Xopen <mods>copen <args>
     command! -nargs=* Xwindow <mods>cwindow <args>
@@ -43,7 +43,7 @@ func s:setup_commands(cchar)
     command! -nargs=* -bang Xlist <mods>llist<bang> <args>
     command! -nargs=* Xgetexpr <mods>lgetexpr <args>
     command! -nargs=* Xaddexpr <mods>laddexpr <args>
-    command! -nargs=* Xolder <mods>lolder <args>
+    command! -nargs=* -count Xolder <mods><count>lolder <args>
     command! -nargs=* Xnewer <mods>lnewer <args>
     command! -nargs=* Xopen <mods>lopen <args>
     command! -nargs=* Xwindow <mods>lwindow <args>
@@ -1745,7 +1745,7 @@ func Xproperty_tests(cchar)
     call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
 
     " Changing the title of an earlier quickfix list
-    call g:Xsetlist([], ' ', {'title' : 'NewTitle', 'nr' : 2})
+    call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2})
     call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
 
     " Changing the title of an invalid quickfix list
@@ -1812,10 +1812,10 @@ func Xproperty_tests(cchar)
     Xexpr "One"
     Xexpr "Two"
     Xexpr "Three"
-    call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1})
-    call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2})
+    call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
+    call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
     " Also, check for setting the context using quickfix list number zero.
-    call g:Xsetlist([], ' ', {'context' : [3], 'nr' : 0})
+    call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0})
     call test_garbagecollect_now()
     let l = g:Xgetlist({'nr' : 1, 'context' : 1})
     call assert_equal([1], l.context)
@@ -2433,3 +2433,89 @@ func Test_Multi_LL_Help()
     call assert_true(len(getloclist(2)) != 0)
     new | only
 endfunc
+
+" Tests for adding new quickfix lists using setqflist()
+func XaddQf_tests(cchar)
+  call s:setup_commands(a:cchar)
+
+  " Create a new list using ' ' for action
+  call g:Xsetlist([], 'f')
+  call g:Xsetlist([], ' ', {'title' : 'Test1'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(1, l.nr)
+  call assert_equal('Test1', l.title)
+
+  " Create a new list using ' ' for action and '$' for 'nr'
+  call g:Xsetlist([], 'f')
+  call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(1, l.nr)
+  call assert_equal('Test2', l.title)
+
+  " Create a new list using 'a' for action
+  call g:Xsetlist([], 'f')
+  call g:Xsetlist([], 'a', {'title' : 'Test3'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(1, l.nr)
+  call assert_equal('Test3', l.title)
+
+  " Create a new list using 'a' for action and '$' for 'nr'
+  call g:Xsetlist([], 'f')
+  call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'})
+  call g:Xsetlist([], 'a', {'title' : 'Test4'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(1, l.nr)
+  call assert_equal('Test4', l.title)
+
+  " Adding a quickfix list should remove all the lists following the current
+  " list.
+  Xexpr "" | Xexpr "" | Xexpr ""
+  silent! 10Xolder
+  call g:Xsetlist([], ' ', {'title' : 'Test5'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(2, l.nr)
+  call assert_equal('Test5', l.title)
+
+  " Add a quickfix list using '$' as the list number.
+  let lastqf = g:Xgetlist({'nr':'$'}).nr
+  silent! 99Xolder
+  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(lastqf + 1, l.nr)
+  call assert_equal('Test6', l.title)
+
+  " Add a quickfix list using 'nr' set to one more than the quickfix
+  " list size.
+  let lastqf = g:Xgetlist({'nr':'$'}).nr
+  silent! 99Xolder
+  call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(lastqf + 1, l.nr)
+  call assert_equal('Test7', l.title)
+
+  " Add a quickfix list to a stack with 10 lists using 'nr' set to '$'
+  exe repeat('Xexpr "" |', 9) . 'Xexpr ""'
+  silent! 99Xolder
+  call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'})
+  let l = g:Xgetlist({'nr' : '$', 'all' : 1})
+  call assert_equal(10, l.nr)
+  call assert_equal('Test8', l.title)
+
+  " Add a quickfix list using 'nr' set to a value greater than 10
+  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'}))
+
+  " Try adding a quickfix list with 'nr' set to a value greater than the
+  " quickfix list size but less than 10.
+  call g:Xsetlist([], 'f')
+  Xexpr "" | Xexpr "" | Xexpr ""
+  silent! 99Xolder
+  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'}))
+
+  " Add a quickfix list using 'nr' set to a some string or list
+  call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 
'Test11'}))
+endfunc
+
+func Test_add_qf()
+  call XaddQf_tests('c')
+  call XaddQf_tests('l')
+endfunc

Raspunde prin e-mail lui