# HG changeset patch # User Christian Brabandt # Date 1504118703 -7200 # Node ID 20641a7e1fc95b3096d42310820b482deb8fdf93 # Parent 27efa3b025f42548a81ffd81320cc4d52e97af04 patch 8.0.1023: it is not easy to identify a quickfix list commit https://github.com/vim/vim/commit/a539f4f1ae4a2b3a7dfce89cd3800214c9e990cf Author: Bram Moolenaar Date: Wed Aug 30 20:33:55 2017 +0200 patch 8.0.1023: it is not easy to identify a quickfix list Problem: It is not easy to identify a quickfix list. Solution: Add the "id" field. (Yegappan Lakshmanan) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -4632,6 +4632,9 @@ 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()| + id get information for the quickfix list with + |quickfix-ID|; zero means the id for the + current list or the list specifed by 'nr' items quickfix list entries nr get information for this quickfix list; zero means the current quickfix list and '$' means @@ -4646,6 +4649,8 @@ getqflist([{what}]) *getqflist()* all all of the above quickfix properties Non-string items in {what} are ignored. If "nr" is not present then the current quickfix list is used. + If both "nr" and a non-zero "id" are specified, then the list + specified by "id" is used. To get the number of lists in the quickfix stack, set 'nr' to '$' in {what}. The 'nr' value in the returned dictionary contains the quickfix stack size. @@ -4657,6 +4662,7 @@ getqflist([{what}]) *getqflist()* The returned dictionary contains the following entries: context context information stored with |setqflist()| + id quickfix list ID |quickfix-ID| items quickfix list entries nr quickfix list number title quickfix list title text @@ -7069,6 +7075,7 @@ setqflist({list} [, {action}[, {what}]]) text and add the resulting entries to the quickfix list {nr}. The value can be a string with one line or a list with multiple lines. + id quickfix list identifier |quickfix-ID| items list of quickfix entries. Same as the {list} argument. nr list number in the quickfix stack; zero @@ -7079,6 +7086,9 @@ setqflist({list} [, {action}[, {what}]]) If the "nr" item is not present, then the current quickfix list is modified. When creating a new quickfix list, "nr" can be set to a value one greater than the quickfix stack size. + When modifying a quickfix list, to guarantee that the correct + list is modified, 'id' should be used instead of 'nr' to + specify the list. Examples: > :call setqflist([], 'r', {'title': 'My search'}) diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -58,6 +58,7 @@ struct qfline_S */ typedef struct qf_list_S { + int_u qf_id; /* Unique identifier for this list */ qfline_T *qf_start; /* pointer to the first error */ qfline_T *qf_last; /* pointer to the last error */ qfline_T *qf_ptr; /* pointer to the current error */ @@ -96,6 +97,7 @@ struct qf_info_S }; static qf_info_T ql_info; /* global quickfix list */ +static int_u last_qf_id = 0; /* Last used quickfix list id */ #define FMT_PATTERNS 10 /* maximum number of % recognized */ @@ -1399,6 +1401,7 @@ qf_new_list(qf_info_T *qi, char_u *qf_ti qi->qf_curlist = qi->qf_listcount++; vim_memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T))); qf_store_title(qi, qi->qf_curlist, qf_title); + qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id; } /* @@ -1672,6 +1675,9 @@ copy_loclist(win_T *from, win_T *to) to_qfl->qf_index = from_qfl->qf_index; /* current index in the list */ + /* Assign a new ID for the location list */ + to_qfl->qf_id = ++last_qf_id; + /* When no valid entries are present in the list, qf_ptr points to * the first item in the list */ if (to_qfl->qf_nonevalid) @@ -2808,6 +2814,7 @@ qf_free(qf_info_T *qi, int idx) qfl->qf_title = NULL; free_tv(qfl->qf_ctx); qfl->qf_ctx = NULL; + qfl->qf_id = 0; } /* @@ -4628,6 +4635,7 @@ enum { QF_GETLIST_NR = 0x4, QF_GETLIST_WINID = 0x8, QF_GETLIST_CONTEXT = 0x10, + QF_GETLIST_ID = 0x20, QF_GETLIST_ALL = 0xFF }; @@ -4688,17 +4696,17 @@ get_errorlist_properties(win_T *wp, dict return qf_get_list_from_text(di, retdict); if (wp != NULL) + qi = GET_LOC_LIST(wp); + + /* List is not present or is empty */ + if (qi == NULL || qi->qf_listcount == 0) { - qi = GET_LOC_LIST(wp); - if (qi == NULL) - { - /* If querying for the size of the location list, return 0 */ - if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) - && (di->di_tv.v_type == VAR_STRING) - && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) - return dict_add_nr_str(retdict, "nr", 0, NULL); - return FAIL; - } + /* If querying for the size of the list, return 0 */ + if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) + && (di->di_tv.v_type == VAR_STRING) + && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) + return dict_add_nr_str(retdict, "nr", 0, NULL); + return FAIL; } qf_idx = qi->qf_curlist; /* default is the current list */ @@ -4714,41 +4722,52 @@ get_errorlist_properties(win_T *wp, dict if (qf_idx < 0 || qf_idx >= qi->qf_listcount) return FAIL; } - else if (qi->qf_listcount == 0) /* stack is empty */ - return FAIL; - flags |= QF_GETLIST_NR; } else if ((di->di_tv.v_type == VAR_STRING) && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) + /* Get the last quickfix list number */ + qf_idx = qi->qf_listcount - 1; + else + return FAIL; + flags |= QF_GETLIST_NR; + } + + if ((di = dict_find(what, (char_u *)"id", -1)) != NULL) + { + /* Look for a list with the specified id */ + if (di->di_tv.v_type == VAR_NUMBER) { - /* 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; + /* For zero, use the current list or the list specifed by 'nr' */ + if (di->di_tv.vval.v_number != 0) + { + for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) + { + if (qi->qf_lists[qf_idx].qf_id == di->di_tv.vval.v_number) + break; + } + if (qf_idx == qi->qf_listcount) + return FAIL; /* List not found */ + } + flags |= QF_GETLIST_ID; } else return FAIL; } - if (qf_idx != -1) - { - if (dict_find(what, (char_u *)"all", -1) != NULL) - flags |= QF_GETLIST_ALL; - - if (dict_find(what, (char_u *)"title", -1) != NULL) - flags |= QF_GETLIST_TITLE; - - if (dict_find(what, (char_u *)"winid", -1) != NULL) - flags |= QF_GETLIST_WINID; - - 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 (dict_find(what, (char_u *)"all", -1) != NULL) + flags |= QF_GETLIST_ALL; + + if (dict_find(what, (char_u *)"title", -1) != NULL) + flags |= QF_GETLIST_TITLE; + + if (dict_find(what, (char_u *)"winid", -1) != NULL) + flags |= QF_GETLIST_WINID; + + 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) { @@ -4798,6 +4817,10 @@ get_errorlist_properties(win_T *wp, dict status = dict_add_nr_str(retdict, "context", 0L, (char_u *)""); } + if ((status == OK) && (flags & QF_GETLIST_ID)) + status = dict_add_nr_str(retdict, "id", qi->qf_lists[qf_idx].qf_id, + NULL); + return status; } @@ -4983,6 +5006,21 @@ qf_set_properties(qf_info_T *qi, dict_T return FAIL; } + if (!newlist && (di = dict_find(what, (char_u *)"id", -1)) != NULL) + { + /* Use the quickfix/location list with the specified id */ + if (di->di_tv.v_type == VAR_NUMBER) + { + for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) + if (qi->qf_lists[qf_idx].qf_id == di->di_tv.vval.v_number) + break; + if (qf_idx == qi->qf_listcount) + return FAIL; /* List not found */ + } + else + return FAIL; + } + if (newlist) { qi->qf_curlist = qf_idx; diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -1897,8 +1897,9 @@ func Xproperty_tests(cchar) 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 + let save_id = l1.id + let l1.id=l2.id + let l2.id=save_id call g:Xsetlist([], 'r', l1) call g:Xsetlist([], 'r', l2) let newl1=g:Xgetlist({'nr':1,'all':1}) @@ -2545,3 +2546,38 @@ func Test_get_list_from_text() call XgetListFromText('c') call XgetListFromText('l') endfunc + +" Tests for the quickfix list id +func Xqfid_tests(cchar) + call s:setup_commands(a:cchar) + + call g:Xsetlist([], 'f') + call assert_equal({}, g:Xgetlist({'id':0})) + Xexpr '' + let start_id = g:Xgetlist({'id' : 0}).id + Xexpr '' | Xexpr '' + Xolder + call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id) + call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id) + call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id) + call assert_equal({}, g:Xgetlist({'id':0, 'nr':99})) + call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr) + call assert_equal({}, g:Xgetlist({'id':99, 'nr':0})) + call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0})) + + call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]}) + call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context) + call g:Xsetlist([], 'a', {'id':start_id+1, 'text':'F1:10:L10'}) + call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text) + call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'})) + call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'})) + + let qfid = g:Xgetlist({'id':0, 'nr':0}) + call g:Xsetlist([], 'f') + call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0})) +endfunc + +func Test_qf_id() + call Xqfid_tests('c') + call Xqfid_tests('l') +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1023, +/**/ 1022, /**/ 1021,