Patch 8.0.1406
Problem:    Difficult to track changes to a quickfix list.
Solution:   Add a "changedtick" value. (Yegappan Lakshmanan, closes #2460)
Files:      runtime/doc/eval.txt, runtime/doc/quickfix.txt, src/quickfix.c,
            src/testdir/test_quickfix.vim


*** ../vim-8.0.1405/runtime/doc/eval.txt        2017-12-16 18:26:56.618992550 
+0100
--- runtime/doc/eval.txt        2017-12-18 19:45:00.179246715 +0100
***************
*** 4662,4667 ****
--- 4674,4681 ----
                If the optional {what} dictionary argument is supplied, then
                returns only the items listed in {what} as a dictionary. The
                following string items are supported in {what}:
+                       changedtick     get the total number of changes made
+                                       to the list
                        context get the context stored with |setqflist()|
                        efm     errorformat to use when parsing "lines". If
                                not present, then the 'errorformat' option
***************
*** 4695,4700 ****
--- 4709,4716 ----
                "items" with the list of entries.
  
                The returned dictionary contains the following entries:
+                       changedtick     total number of changes made to the
+                                       list |quickfix-changedtick|
                        context context information stored with |setqflist()|.
                                If not present, set to "".
                        id      quickfix list ID |quickfix-ID|. If not
*** ../vim-8.0.1405/runtime/doc/quickfix.txt    2017-12-10 15:25:12.506523247 
+0100
--- runtime/doc/quickfix.txt    2017-12-18 19:45:00.179246715 +0100
***************
*** 1,4 ****
! *quickfix.txt*  For Vim version 8.0.  Last change: 2017 Sep 13
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
--- 1,4 ----
! *quickfix.txt*  For Vim version 8.0.  Last change: 2017 Dec 13
  
  
                  VIM REFERENCE MANUAL    by Bram Moolenaar
***************
*** 64,69 ****
--- 64,77 ----
  location list.  When there are no longer any references to a location list,
  the location list is destroyed.
  
+                                               *quickfix-changedtick*
+ 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.
+ 
  The following quickfix commands can be used.  The location list commands are
  similar to the quickfix commands, replacing the 'c' prefix in the quickfix
  command with 'l'.
***************
*** 363,369 ****
  The |setqflist()| and the |setloclist()| functions can be used to associate a
  context with a quickfix and a location list respectively. The |getqflist()|
  and the |getloclist()| functions can be used to retrieve the context of a
! quickifx and a location list respectively. This is useful for a Vim plugin
  dealing with multiple quickfix/location lists.
  Examples: >
  
--- 371,377 ----
  The |setqflist()| and the |setloclist()| functions can be used to associate a
  context with a quickfix and a location list respectively. The |getqflist()|
  and the |getloclist()| functions can be used to retrieve the context of a
! quickfix and a location list respectively. This is useful for a Vim plugin
  dealing with multiple quickfix/location lists.
  Examples: >
  
***************
*** 376,388 ****
        echo getloclist(2, {'id' : qfid, 'context' : 1})
  <
                                                        *quickfix-parse*
! You can parse a list of lines using 'erroformat' without creating or modifying
! a quickfix list using the |getqflist()| function. Examples: >
        echo getqflist({'lines' : ["F1:10:Line10", "F2:20:Line20"]})
        echo getqflist({'lines' : systemlist('grep -Hn quickfix *')})
  This returns a dictionary where the 'items' key contains the list of quickfix
  entries parsed from lines. The following shows how to use a custom
! 'errorformat' to parse the lines without modifying the 'erroformat' option: >
        echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']})
  <
  
--- 384,396 ----
        echo getloclist(2, {'id' : qfid, 'context' : 1})
  <
                                                        *quickfix-parse*
! You can parse a list of lines using 'errorformat' without creating or
! modifying a quickfix list using the |getqflist()| function. Examples: >
        echo getqflist({'lines' : ["F1:10:Line10", "F2:20:Line20"]})
        echo getqflist({'lines' : systemlist('grep -Hn quickfix *')})
  This returns a dictionary where the 'items' key contains the list of quickfix
  entries parsed from lines. The following shows how to use a custom
! 'errorformat' to parse the lines without modifying the 'errorformat' option: >
        echo getqflist({'efm' : '%f#%l#%m', 'lines' : ['F1#10#Line']})
  <
  
*** ../vim-8.0.1405/src/quickfix.c      2017-12-18 15:32:55.274906330 +0100
--- src/quickfix.c      2017-12-18 19:45:00.179246715 +0100
***************
*** 76,81 ****
--- 76,82 ----
      int                       qf_multiline;
      int                       qf_multiignore;
      int                       qf_multiscan;
+     long              qf_changedtick;
  } qf_list_T;
  
  /*
***************
*** 1668,1673 ****
--- 1669,1675 ----
  
        /* Assign a new ID for the location list */
        to_qfl->qf_id = ++last_qf_id;
+       to_qfl->qf_changedtick = 0L;
  
        /* When no valid entries are present in the list, qf_ptr points to
         * the first item in the list */
***************
*** 2965,2970 ****
--- 2967,2973 ----
      free_tv(qfl->qf_ctx);
      qfl->qf_ctx = NULL;
      qfl->qf_id = 0;
+     qfl->qf_changedtick = 0L;
  }
  
  /*
***************
*** 3604,3609 ****
--- 3607,3618 ----
      KeyTyped = old_KeyTyped;
  }
  
+     static void
+ qf_list_changed(qf_info_T *qi, int qf_idx)
+ {
+     qi->qf_lists[qf_idx].qf_changedtick++;
+ }
+ 
  /*
   * Return TRUE when using ":vimgrep" for ":grep".
   */
***************
*** 3713,3718 ****
--- 3722,3729 ----
                                           *eap->cmdlinep, enc);
      if (wp != NULL)
        qi = GET_LOC_LIST(wp);
+     if (res >= 0 && qi != NULL)
+       qf_list_changed(qi, qi->qf_curlist);
  #ifdef FEAT_AUTOCMD
      if (au_name != NULL)
      {
***************
*** 4105,4118 ****
       */
      res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
                        && eap->cmdidx != CMD_laddfile), *eap->cmdlinep, enc);
  #ifdef FEAT_AUTOCMD
      if (au_name != NULL)
        apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf);
  #endif
      if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile))
      {
-       if (wp != NULL)
-           qi = GET_LOC_LIST(wp);
        qf_jump(qi, 0, 0, eap->forceit);        /* display first error */
      }
  }
--- 4116,4131 ----
       */
      res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
                        && eap->cmdidx != CMD_laddfile), *eap->cmdlinep, enc);
+     if (wp != NULL)
+       qi = GET_LOC_LIST(wp);
+     if (res >= 0 && qi != NULL)
+       qf_list_changed(qi, qi->qf_curlist);
  #ifdef FEAT_AUTOCMD
      if (au_name != NULL)
        apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf);
  #endif
      if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile))
      {
        qf_jump(qi, 0, 0, eap->forceit);        /* display first error */
      }
  }
***************
*** 4469,4474 ****
--- 4482,4488 ----
      qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE;
      qi->qf_lists[qi->qf_curlist].qf_ptr = 
qi->qf_lists[qi->qf_curlist].qf_start;
      qi->qf_lists[qi->qf_curlist].qf_index = 1;
+     qf_list_changed(qi, qi->qf_curlist);
  
      qf_update_buffer(qi, NULL);
  
***************
*** 4780,4786 ****
      QF_GETLIST_ID     = 0x20,
      QF_GETLIST_IDX    = 0x40,
      QF_GETLIST_SIZE   = 0x80,
!     QF_GETLIST_ALL    = 0xFF
  };
  
  /*
--- 4794,4801 ----
      QF_GETLIST_ID     = 0x20,
      QF_GETLIST_IDX    = 0x40,
      QF_GETLIST_SIZE   = 0x80,
!     QF_GETLIST_TICK   = 0x100,
!     QF_GETLIST_ALL    = 0x1FF
  };
  
  /*
***************
*** 4896,4901 ****
--- 4911,4919 ----
      if (dict_find(what, (char_u *)"size", -1) != NULL)
        flags |= QF_GETLIST_SIZE;
  
+     if (dict_find(what, (char_u *)"changedtick", -1) != NULL)
+       flags |= QF_GETLIST_TICK;
+ 
      if (qi != NULL && qi->qf_listcount != 0)
      {
        qf_idx = qi->qf_curlist;        /* default is the current list */
***************
*** 4963,4968 ****
--- 4981,4988 ----
            status = dict_add_nr_str(retdict, "idx", 0L, NULL);
        if ((status == OK) && (flags & QF_GETLIST_SIZE))
            status = dict_add_nr_str(retdict, "size", 0L, NULL);
+       if ((status == OK) && (flags & QF_GETLIST_TICK))
+           status = dict_add_nr_str(retdict, "changedtick", 0L, NULL);
  
        return status;
      }
***************
*** 5035,5040 ****
--- 5055,5064 ----
        status = dict_add_nr_str(retdict, "size",
                                        qi->qf_lists[qf_idx].qf_count, NULL);
  
+     if ((status == OK) && (flags & QF_GETLIST_TICK))
+       status = dict_add_nr_str(retdict, "changedtick",
+                               qi->qf_lists[qf_idx].qf_changedtick, NULL);
+ 
      return status;
  }
  
***************
*** 5304,5309 ****
--- 5328,5336 ----
        retval = OK;
      }
  
+     if (retval == OK)
+       qf_list_changed(qi, qf_idx);
+ 
      return retval;
  }
  
***************
*** 5407,5413 ****
--- 5434,5444 ----
      else if (what != NULL)
        retval = qf_set_properties(qi, what, action, title);
      else
+     {
        retval = qf_add_entries(qi, qi->qf_curlist, list, title, action);
+       if (retval == OK)
+           qf_list_changed(qi, qi->qf_curlist);
+     }
  
      return retval;
  }
***************
*** 5540,5545 ****
--- 5571,5578 ----
                             && eap->cmdidx != CMD_laddbuffer),
                                                   eap->line1, eap->line2,
                                                   qf_title, NULL);
+           if (res >= 0)
+               qf_list_changed(qi, qi->qf_curlist);
  #ifdef FEAT_AUTOCMD
            if (au_name != NULL)
                apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
***************
*** 5609,5614 ****
--- 5642,5649 ----
                             && eap->cmdidx != CMD_laddexpr),
                                 (linenr_T)0, (linenr_T)0, *eap->cmdlinep,
                                 NULL);
+           if (res >= 0)
+               qf_list_changed(qi, qi->qf_curlist);
  #ifdef FEAT_AUTOCMD
            if (au_name != NULL)
                apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
***************
*** 5829,5834 ****
--- 5864,5870 ----
        /* Darn, some plugin changed the value. */
        free_string_option(save_cpo);
  
+     qf_list_changed(qi, qi->qf_curlist);
      qf_update_buffer(qi, NULL);
  
  #ifdef FEAT_AUTOCMD
*** ../vim-8.0.1405/src/testdir/test_quickfix.vim       2017-12-12 
22:45:07.141808185 +0100
--- src/testdir/test_quickfix.vim       2017-12-18 19:45:00.179246715 +0100
***************
*** 2132,2137 ****
--- 2132,2139 ----
  
    call delete('Xtest')
    call delete('Xempty')
+   au! QuickFixCmdPre
+   au! QuickFixCmdPost
  endfunc
  
  func Test_Autocmd_Exception()
***************
*** 2896,2902 ****
    call assert_equal(0, g:Xgetlist({'size' : 0}).size)
    call assert_equal('', g:Xgetlist({'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
!   call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' 
: 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'all' : 0}))
  
    " Empty quickfix list
    Xexpr ""
--- 2898,2905 ----
    call assert_equal(0, g:Xgetlist({'size' : 0}).size)
    call assert_equal('', g:Xgetlist({'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
!   call assert_equal(0, g:Xgetlist({'changedtick' : 0}).changedtick)
!   call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' 
: 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick': 0}, 
g:Xgetlist({'all' : 0}))
  
    " Empty quickfix list
    Xexpr ""
***************
*** 2908,2913 ****
--- 2911,2917 ----
    call assert_equal(0, g:Xgetlist({'size' : 0}).size)
    call assert_notequal('', g:Xgetlist({'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'winid' : 0}).winid)
+   call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
  
    let qfid = g:Xgetlist({'id' : 0}).id
    call g:Xsetlist([], 'f')
***************
*** 2921,2927 ****
    call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
    call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
!   call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' 
: 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'id' : qfid, 'all' : 
0}))
  
    " Non-existing quickfix list number
    call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
--- 2925,2932 ----
    call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size)
    call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid)
!   call assert_equal(0, g:Xgetlist({'id' : qfid, 'changedtick' : 
0}).changedtick)
!   call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' 
: 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick' : 0}, 
g:Xgetlist({'id' : qfid, 'all' : 0}))
  
    " Non-existing quickfix list number
    call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context)
***************
*** 2932,2941 ****
    call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
    call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
!   call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' 
: 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0}))
  endfunc
  
  func Test_getqflist()
    call Xgetlist_empty_tests('c')
    call Xgetlist_empty_tests('l')
  endfunc
--- 2937,3005 ----
    call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size)
    call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title)
    call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid)
!   call assert_equal(0, g:Xgetlist({'nr' : 5, 'changedtick' : 0}).changedtick)
!   call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' 
: 0, 'size' : 0, 'title' : '', 'winid' : 0, 'changedtick' : 0}, 
g:Xgetlist({'nr' : 5, 'all' : 0}))
  endfunc
  
  func Test_getqflist()
    call Xgetlist_empty_tests('c')
    call Xgetlist_empty_tests('l')
  endfunc
+ 
+ " Tests for the quickfix/location list changedtick
+ func Xqftick_tests(cchar)
+   call s:setup_commands(a:cchar)
+ 
+   call g:Xsetlist([], 'f')
+ 
+   Xexpr "F1:10:Line10"
+   let qfid = g:Xgetlist({'id' : 0}).id
+   call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
+   Xaddexpr "F2:20:Line20\nF2:21:Line21"
+   call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call g:Xsetlist([], 'a', {'lines' : ["F3:30:Line30", "F3:31:Line31"]})
+   call assert_equal(3, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call g:Xsetlist([], 'r', {'lines' : ["F4:40:Line40"]})
+   call assert_equal(4, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call g:Xsetlist([], 'a', {'title' : 'New Title'})
+   call assert_equal(5, g:Xgetlist({'changedtick' : 0}).changedtick)
+ 
+   enew!
+   call append(0, ["F5:50:L50", "F6:60:L60"])
+   Xaddbuffer
+   call assert_equal(6, g:Xgetlist({'changedtick' : 0}).changedtick)
+   enew!
+ 
+   call g:Xsetlist([], 'a', {'context' : {'bus' : 'pci'}})
+   call assert_equal(7, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
+             \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'a')
+   call assert_equal(8, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
+             \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], ' ')
+   call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call g:Xsetlist([{'filename' : 'F7', 'lnum' : 10, 'text' : 'L7'},
+             \ {'filename' : 'F7', 'lnum' : 11, 'text' : 'L11'}], 'r')
+   call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
+ 
+   call writefile(["F8:80:L80", "F8:81:L81"], "Xone")
+   Xfile Xone
+   call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
+   Xaddfile Xone
+   call assert_equal(2, g:Xgetlist({'changedtick' : 0}).changedtick)
+ 
+   " Test case for updating a non-current quickfix list
+   call g:Xsetlist([], 'f')
+   Xexpr "F1:1:L1"
+   Xexpr "F2:2:L2"
+   call g:Xsetlist([], 'a', {'nr' : 1, "lines" : ["F10:10:L10"]})
+   call assert_equal(1, g:Xgetlist({'changedtick' : 0}).changedtick)
+   call assert_equal(2, g:Xgetlist({'nr' : 1, 'changedtick' : 0}).changedtick)
+ 
+   call delete("Xone")
+ endfunc
+ 
+ func Test_qf_tick()
+   call Xqftick_tests('c')
+   call Xqftick_tests('l')
+ endfunc
*** ../vim-8.0.1405/src/version.c       2017-12-18 18:14:43.455768463 +0100
--- src/version.c       2017-12-18 19:45:40.418952831 +0100
***************
*** 773,774 ****
--- 773,776 ----
  {   /* Add new patch number below this line */
+ /**/
+     1406,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
124. You begin conversations with, "Who is your internet service provider?"

 /// Bram Moolenaar -- [email protected] -- 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    ///

-- 
-- 
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.

Raspunde prin e-mail lui