Hi Bram,

On Mon, Jun 12, 2017 at 11:37 AM, Bram Moolenaar <[email protected]> wrote:
>
> Yegappan Lakshmanan wrote:
>
>> I am attaching a patch to get and set the quickfix list items using the
>> getqflist() and setqflist() functions. After this patch, it will be easier
>> to save and restore any quickfix list in the quickfix stack.
>>
>> This will also make it consistent to get or set any attributes (title,
>> context, items) of the quickfix list using the getqflist() and setqflist()
>> functions.
>
> Splitting qf_free() in two functions makes me wonder what each of them
> is doing.
>

The qf_free_items() function frees only the entries in a quickfix list.
Other information like the context and title are not freed. This is needed
when replacing all the entries in a quickfix list using the setqflist()
function with the "r" action argument. In this case, we should not free the
context and title information.

The qf_free() function frees all the entries in a list, the context information
and the title. This function completely frees a list.

>
> It appears qf_free() also clears the title and context.  But
> in qf_add_entries() it was previously clearing the context, and it is
> not.  This should be documented.  I would also like to have a clearer
> comment on those qf_free functions.
>

I have updated the comments and the updated patch is attached.

Regards,
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 [email protected].
For more options, visit https://groups.google.com/d/optout.
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 701fd3985..0ddde0bd1 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -4586,6 +4586,7 @@ getqflist([{what}])                                       
*getqflist()*
                returns only the items listed in {what} as a dictionary. The
                following string items are supported in {what}:
                        context get the context stored with |setqflist()|
+                       items   quickfix list entries
                        nr      get information for this quickfix list; zero
                                means the current quickfix list and '$' means
                                the last quickfix list
@@ -4602,6 +4603,7 @@ getqflist([{what}])                                       
*getqflist()*
 
                The returned dictionary contains the following entries:
                        context context information stored with |setqflist()|
+                       items   quickfix list entries
                        nr      quickfix list number
                        title   quickfix list title text
                        winid   quickfix |window-ID| (if opened)
@@ -6995,6 +6997,8 @@ setqflist({list} [, {action}[, {what}]])          
*setqflist()*
                argument is ignored.  The following items can be specified in
                {what}:
                    context     any Vim type can be stored as a context
+                   items       list of quickfix entries. Same as the {list}
+                               argument.
                    nr          list number in the quickfix stack; zero
                                means the current quickfix list and '$' means
                                the last quickfix list
diff --git a/src/quickfix.c b/src/quickfix.c
index 8b61e10bc..60a4653b8 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -1347,6 +1347,9 @@ qf_init_end:
     static void
 qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
 {
+    vim_free(qi->qf_lists[qf_idx].qf_title);
+    qi->qf_lists[qf_idx].qf_title = NULL;
+
     if (title != NULL)
     {
        char_u *p = alloc((int)STRLEN(title) + 2);
@@ -2735,10 +2738,11 @@ qf_history(exarg_T *eap)
 }
 
 /*
- * Free all the entries in the error list "idx".
+ * Free all the entries in the error list "idx". Note that other information
+ * associated with the list like context and title are not freed.
  */
     static void
-qf_free(qf_info_T *qi, int idx)
+qf_free_items(qf_info_T *qi, int idx)
 {
     qfline_T   *qfp;
     qfline_T   *qfpnext;
@@ -2763,10 +2767,7 @@ qf_free(qf_info_T *qi, int idx)
        qi->qf_lists[idx].qf_start = qfpnext;
        --qi->qf_lists[idx].qf_count;
     }
-    vim_free(qi->qf_lists[idx].qf_title);
-    qi->qf_lists[idx].qf_title = NULL;
-    free_tv(qi->qf_lists[idx].qf_ctx);
-    qi->qf_lists[idx].qf_ctx = NULL;
+
     qi->qf_lists[idx].qf_index = 0;
     qi->qf_lists[idx].qf_start = NULL;
     qi->qf_lists[idx].qf_last = NULL;
@@ -2783,6 +2784,21 @@ qf_free(qf_info_T *qi, int idx)
 }
 
 /*
+ * Free error list "idx". Frees all the entries in the quickfix list,
+ * associated context information and the title.
+ */
+    static void
+qf_free(qf_info_T *qi, int idx)
+{
+    qf_free_items(qi, idx);
+
+    vim_free(qi->qf_lists[idx].qf_title);
+    qi->qf_lists[idx].qf_title = NULL;
+    free_tv(qi->qf_lists[idx].qf_ctx);
+    qi->qf_lists[idx].qf_ctx = NULL;
+}
+
+/*
  * qf_mark_adjust: adjust marks
  */
    void
@@ -4698,13 +4714,11 @@ get_errorlist_properties(win_T *wp, dict_T *what, 
dict_T *retdict)
        } else if ((di->di_tv.v_type == VAR_STRING) &&
                (STRCMP(di->di_tv.vval.v_string, "$") == 0))
        {
-           {
-               /* Get the last quickfix list number */
-               if (qi->qf_listcount > 0)
-                   qf_idx = qi->qf_listcount - 1;
-               else
-                   qf_idx = -1;        /* Quickfix stack is empty */
-           }
+           /* Get the last quickfix list number */
+           if (qi->qf_listcount > 0)
+               qf_idx = qi->qf_listcount - 1;
+           else
+               qf_idx = -1;    /* Quickfix stack is empty */
            flags |= QF_GETLIST_NR;
        }
        else
@@ -4724,6 +4738,9 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T 
*retdict)
 
        if (dict_find(what, (char_u *)"context", -1) != NULL)
            flags |= QF_GETLIST_CONTEXT;
+
+       if (dict_find(what, (char_u *)"items", -1) != NULL)
+           flags |= QF_GETLIST_ITEMS;
     }
 
     if (flags & QF_GETLIST_TITLE)
@@ -4743,6 +4760,15 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T 
*retdict)
        if (win != NULL)
            status = dict_add_nr_str(retdict, "winid", win->w_id, NULL);
     }
+    if ((status == OK) && (flags & QF_GETLIST_ITEMS))
+    {
+       list_T  *l = list_alloc();
+       if (l != NULL)
+       {
+           (void)get_errorlist(wp, qf_idx, l);
+           dict_add_list(retdict, "items", l);
+       }
+    }
 
     if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
     {
@@ -4802,7 +4828,7 @@ qf_add_entries(
 #endif
     else if (action == 'r')
     {
-       qf_free(qi, qf_idx);
+       qf_free_items(qi, qf_idx);
        qf_store_title(qi, qf_idx, title);
     }
 
@@ -4915,15 +4941,27 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int 
action)
            /* for zero use the current list */
            if (di->di_tv.vval.v_number != 0)
                qf_idx = di->di_tv.vval.v_number - 1;
-           if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
+
+           if ((action == ' ' || action == 'a') &&
+                   qf_idx == qi->qf_listcount)
+               /*
+                * When creating a new list, accept qf_idx pointing to the next
+                * non-available list
+                */
+               newlist = TRUE;
+           else if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
                return FAIL;
+           else
+               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)
+       {
            qf_idx = qi->qf_listcount - 1;
+           newlist = FALSE;
+       }
        else
            return FAIL;
-       newlist = FALSE;        /* use the specified list */
     }
 
     if (newlist)
@@ -4944,6 +4982,17 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int 
action)
            retval = OK;
        }
     }
+    if ((di = dict_find(what, (char_u *)"items", -1)) != NULL)
+    {
+       if (di->di_tv.v_type == VAR_LIST)
+       {
+           char_u *title_save = vim_strsave(qi->qf_lists[qf_idx].qf_title);
+
+           retval = qf_add_entries(qi, qf_idx, di->di_tv.vval.v_list,
+                   title_save, action == ' ' ? 'a' : action);
+           vim_free(title_save);
+       }
+    }
 
     if ((di = dict_find(what, (char_u *)"context", -1)) != NULL)
     {
diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim
index 16187be76..c23e597e3 100644
--- a/src/testdir/test_quickfix.vim
+++ b/src/testdir/test_quickfix.vim
@@ -1835,6 +1835,73 @@ func Xproperty_tests(cchar)
     call test_garbagecollect_now()
     let m = g:Xgetlist({'context' : 1})
     call assert_equal(["red", "blue", "green"], m.context)
+
+    " Test for setting/getting items
+    Xexpr ""
+    let qfprev = g:Xgetlist({'nr':0})
+    call g:Xsetlist([], ' ', {'title':'Green',
+               \ 'items' : [{'filename':'F1', 'lnum':10}]})
+    let qfcur = g:Xgetlist({'nr':0})
+    call assert_true(qfcur.nr == qfprev.nr + 1)
+    let l = g:Xgetlist({'items':1})
+    call assert_equal('F1', bufname(l.items[0].bufnr))
+    call assert_equal(10, l.items[0].lnum)
+    call g:Xsetlist([], 'a', {'items' : [{'filename':'F2', 'lnum':20},
+               \  {'filename':'F2', 'lnum':30}]})
+    let l = g:Xgetlist({'items':1})
+    call assert_equal('F2', bufname(l.items[2].bufnr))
+    call assert_equal(30, l.items[2].lnum)
+    call g:Xsetlist([], 'r', {'items' : [{'filename':'F3', 'lnum':40}]})
+    let l = g:Xgetlist({'items':1})
+    call assert_equal('F3', bufname(l.items[0].bufnr))
+    call assert_equal(40, l.items[0].lnum)
+    call g:Xsetlist([], 'r', {'items' : []})
+    let l = g:Xgetlist({'items':1})
+    call assert_equal(0, len(l.items))
+
+    " Save and restore the quickfix stack
+    call g:Xsetlist([], 'f')
+    call assert_equal(0, g:Xgetlist({'nr':'$'}).nr)
+    Xexpr "File1:10:Line1"
+    Xexpr "File2:20:Line2"
+    Xexpr "File3:30:Line3"
+    let last_qf = g:Xgetlist({'nr':'$'}).nr
+    call assert_equal(3, last_qf)
+    let qstack = []
+    for i in range(1, last_qf)
+       let qstack = add(qstack, g:Xgetlist({'nr':i, 'all':1}))
+    endfor
+    call g:Xsetlist([], 'f')
+    for i in range(len(qstack))
+       call g:Xsetlist([], ' ', qstack[i])
+    endfor
+    call assert_equal(3, g:Xgetlist({'nr':'$'}).nr)
+    call assert_equal(10, g:Xgetlist({'nr':1, 'items':1}).items[0].lnum)
+    call assert_equal(20, g:Xgetlist({'nr':2, 'items':1}).items[0].lnum)
+    call assert_equal(30, g:Xgetlist({'nr':3, 'items':1}).items[0].lnum)
+    call g:Xsetlist([], 'f')
+
+    " Swap two quickfix lists
+    Xexpr "File1:10:Line10"
+    Xexpr "File2:20:Line20"
+    Xexpr "File3:30:Line30"
+    call g:Xsetlist([], 'r', {'nr':1,'title':'Colors','context':['Colors']})
+    call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
+    let l1=g:Xgetlist({'nr':1,'all':1})
+    let l2=g:Xgetlist({'nr':2,'all':1})
+    let l1.nr=2
+    let l2.nr=1
+    call g:Xsetlist([], 'r', l1)
+    call g:Xsetlist([], 'r', l2)
+    let newl1=g:Xgetlist({'nr':1,'all':1})
+    let newl2=g:Xgetlist({'nr':2,'all':1})
+    call assert_equal(':Fruits', newl1.title)
+    call assert_equal(['Fruits'], newl1.context)
+    call assert_equal('Line20', newl1.items[0].text)
+    call assert_equal(':Colors', newl2.title)
+    call assert_equal(['Colors'], newl2.context)
+    call assert_equal('Line10', newl2.items[0].text)
+    call g:Xsetlist([], 'f')
 endfunc
 
 func Test_qf_property()

Raspunde prin e-mail lui