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.