forked from aniani/vim
patch 8.0.0657: cannot get and set quickfix list items
Problem: Cannot get and set quickfix list items. Solution: Add the "items" argument to getqflist() and setqflist(). (Yegappan Lakshmanan)
This commit is contained in:
@@ -4586,6 +4586,7 @@ 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()|
|
||||||
|
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
|
||||||
the last quickfix list
|
the last quickfix list
|
||||||
@@ -4602,6 +4603,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()|
|
||||||
|
items quickfix list entries
|
||||||
nr quickfix list number
|
nr quickfix list number
|
||||||
title quickfix list title text
|
title quickfix list title text
|
||||||
winid quickfix |window-ID| (if opened)
|
winid quickfix |window-ID| (if opened)
|
||||||
@@ -6998,6 +7000,8 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
|||||||
argument is ignored. The following items can be specified in
|
argument is ignored. The following items can be specified in
|
||||||
{what}:
|
{what}:
|
||||||
context any Vim type can be stored as a context
|
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
|
nr list number in the quickfix stack; zero
|
||||||
means the current quickfix list and '$' means
|
means the current quickfix list and '$' means
|
||||||
the last quickfix list
|
the last quickfix list
|
||||||
|
@@ -47,19 +47,32 @@ struct qfline_S
|
|||||||
*/
|
*/
|
||||||
#define LISTCOUNT 10
|
#define LISTCOUNT 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quickfix/Location list definition
|
||||||
|
* Contains a list of entries (qfline_T). qf_start points to the first entry
|
||||||
|
* and qf_last points to the last entry. qf_count contains the list size.
|
||||||
|
*
|
||||||
|
* Usually the list contains one or more entries. But an empty list can be
|
||||||
|
* created using setqflist()/setloclist() with a title and/or user context
|
||||||
|
* information and entries can be added later using setqflist()/setloclist().
|
||||||
|
*/
|
||||||
typedef struct qf_list_S
|
typedef struct qf_list_S
|
||||||
{
|
{
|
||||||
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 */
|
||||||
int qf_count; /* number of errors (0 means no error list) */
|
int qf_count; /* number of errors (0 means empty list) */
|
||||||
int qf_index; /* current index in the error list */
|
int qf_index; /* current index in the error list */
|
||||||
int qf_nonevalid; /* TRUE if not a single valid entry found */
|
int qf_nonevalid; /* TRUE if not a single valid entry found */
|
||||||
char_u *qf_title; /* title derived from the command that created
|
char_u *qf_title; /* title derived from the command that created
|
||||||
* the error list */
|
* the error list or set by setqflist */
|
||||||
typval_T *qf_ctx; /* context set by setqflist/setloclist */
|
typval_T *qf_ctx; /* context set by setqflist/setloclist */
|
||||||
} qf_list_T;
|
} qf_list_T;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quickfix/Location list stack definition
|
||||||
|
* Contains a list of quickfix/location lists (qf_list_T)
|
||||||
|
*/
|
||||||
struct qf_info_S
|
struct qf_info_S
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -1347,6 +1360,9 @@ qf_init_end:
|
|||||||
static void
|
static void
|
||||||
qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
|
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)
|
if (title != NULL)
|
||||||
{
|
{
|
||||||
char_u *p = alloc((int)STRLEN(title) + 2);
|
char_u *p = alloc((int)STRLEN(title) + 2);
|
||||||
@@ -2735,10 +2751,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
|
static void
|
||||||
qf_free(qf_info_T *qi, int idx)
|
qf_free_items(qf_info_T *qi, int idx)
|
||||||
{
|
{
|
||||||
qfline_T *qfp;
|
qfline_T *qfp;
|
||||||
qfline_T *qfpnext;
|
qfline_T *qfpnext;
|
||||||
@@ -2763,10 +2780,7 @@ qf_free(qf_info_T *qi, int idx)
|
|||||||
qi->qf_lists[idx].qf_start = qfpnext;
|
qi->qf_lists[idx].qf_start = qfpnext;
|
||||||
--qi->qf_lists[idx].qf_count;
|
--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_index = 0;
|
||||||
qi->qf_lists[idx].qf_start = NULL;
|
qi->qf_lists[idx].qf_start = NULL;
|
||||||
qi->qf_lists[idx].qf_last = NULL;
|
qi->qf_lists[idx].qf_last = NULL;
|
||||||
@@ -2782,6 +2796,21 @@ qf_free(qf_info_T *qi, int idx)
|
|||||||
qi->qf_multiscan = FALSE;
|
qi->qf_multiscan = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* qf_mark_adjust: adjust marks
|
||||||
*/
|
*/
|
||||||
@@ -4697,14 +4726,12 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
flags |= QF_GETLIST_NR;
|
flags |= QF_GETLIST_NR;
|
||||||
} else if ((di->di_tv.v_type == VAR_STRING) &&
|
} else if ((di->di_tv.v_type == VAR_STRING) &&
|
||||||
(STRCMP(di->di_tv.vval.v_string, "$") == 0))
|
(STRCMP(di->di_tv.vval.v_string, "$") == 0))
|
||||||
{
|
|
||||||
{
|
{
|
||||||
/* Get the last quickfix list number */
|
/* Get the last quickfix list number */
|
||||||
if (qi->qf_listcount > 0)
|
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 */
|
qf_idx = -1; /* Quickfix stack is empty */
|
||||||
}
|
|
||||||
flags |= QF_GETLIST_NR;
|
flags |= QF_GETLIST_NR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -4724,6 +4751,9 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
|
|
||||||
if (dict_find(what, (char_u *)"context", -1) != NULL)
|
if (dict_find(what, (char_u *)"context", -1) != NULL)
|
||||||
flags |= QF_GETLIST_CONTEXT;
|
flags |= QF_GETLIST_CONTEXT;
|
||||||
|
|
||||||
|
if (dict_find(what, (char_u *)"items", -1) != NULL)
|
||||||
|
flags |= QF_GETLIST_ITEMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & QF_GETLIST_TITLE)
|
if (flags & QF_GETLIST_TITLE)
|
||||||
@@ -4743,6 +4773,15 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
|||||||
if (win != NULL)
|
if (win != NULL)
|
||||||
status = dict_add_nr_str(retdict, "winid", win->w_id, 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))
|
if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
|
||||||
{
|
{
|
||||||
@@ -4802,7 +4841,7 @@ qf_add_entries(
|
|||||||
#endif
|
#endif
|
||||||
else if (action == 'r')
|
else if (action == 'r')
|
||||||
{
|
{
|
||||||
qf_free(qi, qf_idx);
|
qf_free_items(qi, qf_idx);
|
||||||
qf_store_title(qi, qf_idx, title);
|
qf_store_title(qi, qf_idx, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4915,15 +4954,27 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
|||||||
/* for zero use the current list */
|
/* for zero use the current list */
|
||||||
if (di->di_tv.vval.v_number != 0)
|
if (di->di_tv.vval.v_number != 0)
|
||||||
qf_idx = di->di_tv.vval.v_number - 1;
|
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;
|
return FAIL;
|
||||||
|
else
|
||||||
|
newlist = FALSE; /* use the specified list */
|
||||||
} else if (di->di_tv.v_type == VAR_STRING &&
|
} else if (di->di_tv.v_type == VAR_STRING &&
|
||||||
STRCMP(di->di_tv.vval.v_string, "$") == 0 &&
|
STRCMP(di->di_tv.vval.v_string, "$") == 0 &&
|
||||||
qi->qf_listcount > 0)
|
qi->qf_listcount > 0)
|
||||||
|
{
|
||||||
qf_idx = qi->qf_listcount - 1;
|
qf_idx = qi->qf_listcount - 1;
|
||||||
|
newlist = FALSE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return FAIL;
|
return FAIL;
|
||||||
newlist = FALSE; /* use the specified list */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newlist)
|
if (newlist)
|
||||||
@@ -4944,6 +4995,17 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
|||||||
retval = OK;
|
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)
|
if ((di = dict_find(what, (char_u *)"context", -1)) != NULL)
|
||||||
{
|
{
|
||||||
|
@@ -1835,6 +1835,73 @@ func Xproperty_tests(cchar)
|
|||||||
call test_garbagecollect_now()
|
call test_garbagecollect_now()
|
||||||
let m = g:Xgetlist({'context' : 1})
|
let m = g:Xgetlist({'context' : 1})
|
||||||
call assert_equal(["red", "blue", "green"], m.context)
|
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
|
endfunc
|
||||||
|
|
||||||
func Test_qf_property()
|
func Test_qf_property()
|
||||||
|
@@ -764,6 +764,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
657,
|
||||||
/**/
|
/**/
|
||||||
656,
|
656,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user