vim-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)
a539f4f1ae
This commit is contained in:
Jan Edmund Lazo
2018-09-08 06:13:23 -04:00
parent b4acf609ac
commit 9bf2741ba4
3 changed files with 120 additions and 38 deletions

View File

@@ -4335,6 +4335,9 @@ getqflist([{what}]) *getqflist()*
returns only the items listed in {what} as a dictionary. The returns only the items listed in {what} as a dictionary. The
following string items are supported in {what}: following string items are supported in {what}:
context get the context stored with |setqflist()| 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 items quickfix list entries
nr get information for this quickfix list; zero nr get information for this quickfix list; zero
means the current quickfix list and '$' means means the current quickfix list and '$' means
@@ -4349,6 +4352,8 @@ getqflist([{what}]) *getqflist()*
all all of the above quickfix properties all all of the above quickfix properties
Non-string items in {what} are ignored. Non-string items in {what} are ignored.
If "nr" is not present then the current quickfix list is used. 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 To get the number of lists in the quickfix stack, set 'nr' to
'$' in {what}. The 'nr' value in the returned dictionary '$' in {what}. The 'nr' value in the returned dictionary
contains the quickfix stack size. contains the quickfix stack size.
@@ -4360,6 +4365,7 @@ getqflist([{what}]) *getqflist()*
The returned dictionary contains the following entries: The returned dictionary contains the following entries:
context context information stored with |setqflist()| context context information stored with |setqflist()|
id quickfix list ID |quickfix-ID|
items quickfix list entries items quickfix list entries
nr quickfix list number nr quickfix list number
title quickfix list title text title quickfix list title text
@@ -6926,6 +6932,7 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
text and add the resulting entries to the text and add the resulting entries to the
quickfix list {nr}. The value can be a string quickfix list {nr}. The value can be a string
with one line or a list with multiple lines. with one line or a list with multiple lines.
id quickfix list identifier |quickfix-ID|
items list of quickfix entries. Same as the {list} items list of quickfix entries. Same as the {list}
argument. argument.
nr list number in the quickfix stack; zero nr list number in the quickfix stack; zero
@@ -6936,6 +6943,9 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
If the "nr" item is not present, then the current quickfix list If the "nr" item is not present, then the current quickfix list
is modified. When creating a new quickfix list, "nr" can be is modified. When creating a new quickfix list, "nr" can be
set to a value one greater than the quickfix stack size. 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: > Examples: >
:call setqflist([], 'r', {'title': 'My search'}) :call setqflist([], 'r', {'title': 'My search'})

View File

@@ -82,6 +82,7 @@ struct qfline_S {
/// created using setqflist()/setloclist() with a title and/or user context /// created using setqflist()/setloclist() with a title and/or user context
/// information and entries can be added later using setqflist()/setloclist(). /// information and entries can be added later using setqflist()/setloclist().
typedef struct qf_list_S { typedef struct qf_list_S {
unsigned qf_id; ///< Unique identifier for this list
qfline_T *qf_start; ///< pointer to the first error qfline_T *qf_start; ///< pointer to the first error
qfline_T *qf_last; ///< pointer to the last error qfline_T *qf_last; ///< pointer to the last error
qfline_T *qf_ptr; ///< pointer to the current error qfline_T *qf_ptr; ///< pointer to the current error
@@ -117,6 +118,7 @@ struct qf_info_S {
}; };
static qf_info_T ql_info; /* global quickfix list */ static qf_info_T ql_info; /* global quickfix list */
static unsigned last_qf_id = 0; // Last Used quickfix list id
#define FMT_PATTERNS 10 /* maximum number of % recognized */ #define FMT_PATTERNS 10 /* maximum number of % recognized */
@@ -1224,6 +1226,7 @@ static void qf_new_list(qf_info_T *qi, char_u *qf_title)
qi->qf_curlist = qi->qf_listcount++; qi->qf_curlist = qi->qf_listcount++;
memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T))); memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T)));
qf_store_title(qi, qi->qf_curlist, qf_title); qf_store_title(qi, qi->qf_curlist, qf_title);
qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id;
} }
/* /*
@@ -1467,6 +1470,9 @@ void copy_loclist(win_T *from, win_T *to)
to_qfl->qf_index = from_qfl->qf_index; /* current index in the list */ 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 /* When no valid entries are present in the list, qf_ptr points to
* the first item in the list */ * the first item in the list */
if (to_qfl->qf_nonevalid) { if (to_qfl->qf_nonevalid) {
@@ -2458,6 +2464,7 @@ static void qf_free(qf_info_T *qi, int idx)
qfl->qf_title = NULL; qfl->qf_title = NULL;
tv_free(qfl->qf_ctx); tv_free(qfl->qf_ctx);
qfl->qf_ctx = NULL; qfl->qf_ctx = NULL;
qfl->qf_id = 0;
} }
/* /*
@@ -4110,6 +4117,7 @@ enum {
QF_GETLIST_NR = 0x4, QF_GETLIST_NR = 0x4,
QF_GETLIST_WINID = 0x8, QF_GETLIST_WINID = 0x8,
QF_GETLIST_CONTEXT = 0x10, QF_GETLIST_CONTEXT = 0x10,
QF_GETLIST_ID = 0x20,
QF_GETLIST_ALL = 0xFF QF_GETLIST_ALL = 0xFF
}; };
@@ -4155,16 +4163,17 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (wp != NULL) { if (wp != NULL) {
qi = GET_LOC_LIST(wp); qi = GET_LOC_LIST(wp);
if (qi == NULL) { }
// If querying for the size of the location list, return 0 // List is not present or is empty
if (qi == NULL || qi->qf_listcount == 0) {
// If querying for the size of the list, return 0
if (((di = tv_dict_find(what, S_LEN("nr"))) != NULL) if (((di = tv_dict_find(what, S_LEN("nr"))) != NULL)
&& (di->di_tv.v_type == VAR_STRING) && (di->di_tv.v_type == VAR_STRING)
&& strequal((const char *)di->di_tv.vval.v_string, "$")) { && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) {
return tv_dict_add_nr(retdict, S_LEN("nr"), 0); return tv_dict_add_nr(retdict, S_LEN("nr"), 0);
} }
return FAIL; return FAIL;
} }
}
int status = OK; int status = OK;
int flags = QF_GETLIST_NONE; int flags = QF_GETLIST_NONE;
@@ -4179,45 +4188,52 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
return FAIL; 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 } else if (di->di_tv.v_type == VAR_STRING
&& strequal((const char *)di->di_tv.vval.v_string, "$")) { && strequal((const char *)di->di_tv.vval.v_string, "$")) {
// Get the last quickfix list number // Get the last quickfix list number
if (qi->qf_listcount > 0) {
qf_idx = qi->qf_listcount - 1; qf_idx = qi->qf_listcount - 1;
} else { } else {
qf_idx = -1; // Quickfix stack is empty return FAIL;
} }
flags |= QF_GETLIST_NR; flags |= QF_GETLIST_NR;
}
if ((di = tv_dict_find(what, S_LEN("id"))) != NULL) {
// Look for a list with the specified id
if (di->di_tv.v_type == VAR_NUMBER) {
// 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 { } else {
return FAIL; return FAIL;
} }
} }
if (qf_idx != -1) {
if (tv_dict_find(what, S_LEN("all")) != NULL) { if (tv_dict_find(what, S_LEN("all")) != NULL) {
flags |= QF_GETLIST_ALL; flags |= QF_GETLIST_ALL;
} }
if (tv_dict_find(what, S_LEN("title")) != NULL) { if (tv_dict_find(what, S_LEN("title")) != NULL) {
flags |= QF_GETLIST_TITLE; flags |= QF_GETLIST_TITLE;
} }
if (tv_dict_find(what, S_LEN("winid")) != NULL) { if (tv_dict_find(what, S_LEN("winid")) != NULL) {
flags |= QF_GETLIST_WINID; flags |= QF_GETLIST_WINID;
} }
if (tv_dict_find(what, S_LEN("context")) != NULL) { if (tv_dict_find(what, S_LEN("context")) != NULL) {
flags |= QF_GETLIST_CONTEXT; flags |= QF_GETLIST_CONTEXT;
} }
if (tv_dict_find(what, S_LEN("items")) != NULL) { if (tv_dict_find(what, S_LEN("items")) != NULL) {
flags |= QF_GETLIST_ITEMS; flags |= QF_GETLIST_ITEMS;
} }
}
if (flags & QF_GETLIST_TITLE) { if (flags & QF_GETLIST_TITLE) {
char_u *t = qi->qf_lists[qf_idx].qf_title; char_u *t = qi->qf_lists[qf_idx].qf_title;
@@ -4254,6 +4270,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
} }
} }
if ((status == OK) && (flags & QF_GETLIST_ID)) {
status = tv_dict_add_nr(retdict, S_LEN("id"), qi->qf_lists[qf_idx].qf_id);
}
return status; return status;
} }
@@ -4410,6 +4430,22 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action,
} }
} }
if (!newlist && (di = tv_dict_find(what, S_LEN("id"))) != 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) { if (newlist) {
qi->qf_curlist = qf_idx; qi->qf_curlist = qf_idx;
qf_new_list(qi, title); qf_new_list(qi, title);

View File

@@ -1879,8 +1879,9 @@ func Xproperty_tests(cchar)
call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']}) call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
let l1=g:Xgetlist({'nr':1,'all':1}) let l1=g:Xgetlist({'nr':1,'all':1})
let l2=g:Xgetlist({'nr':2,'all':1}) let l2=g:Xgetlist({'nr':2,'all':1})
let l1.nr=2 let save_id = l1.id
let l2.nr=1 let l1.id=l2.id
let l2.id=save_id
call g:Xsetlist([], 'r', l1) call g:Xsetlist([], 'r', l1)
call g:Xsetlist([], 'r', l2) call g:Xsetlist([], 'r', l2)
let newl1=g:Xgetlist({'nr':1,'all':1}) let newl1=g:Xgetlist({'nr':1,'all':1})
@@ -2527,3 +2528,38 @@ func Test_get_list_from_text()
call XgetListFromText('c') call XgetListFromText('c')
call XgetListFromText('l') call XgetListFromText('l')
endfunc 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