mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00
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)
6a8958db25
This commit is contained in:
@@ -4328,6 +4328,7 @@ 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()|
|
||||
items quickfix list entries
|
||||
nr get information for this quickfix list; zero
|
||||
means the current quickfix list and '$' means
|
||||
the last quickfix list
|
||||
@@ -4344,6 +4345,7 @@ getqflist([{what}]) *getqflist()*
|
||||
|
||||
The returned dictionary contains the following entries:
|
||||
context context information stored with |setqflist()|
|
||||
items quickfix list entries
|
||||
nr quickfix list number
|
||||
title quickfix list title text
|
||||
winid quickfix |window-ID| (if opened)
|
||||
@@ -6892,6 +6894,8 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
||||
argument is ignored. The following items can be specified in
|
||||
{what}:
|
||||
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
|
||||
means the current quickfix list and '$' means
|
||||
the last quickfix list
|
||||
|
@@ -76,18 +76,25 @@ struct qfline_S {
|
||||
*/
|
||||
#define LISTCOUNT 10
|
||||
|
||||
/// Quickfix/Location list definition
|
||||
///
|
||||
/// 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 {
|
||||
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
|
||||
int qf_count; // number of errors (0 means no error list)
|
||||
int qf_index; // current index in the error list
|
||||
int qf_nonevalid; // TRUE if not a single valid entry found
|
||||
char_u *qf_title; // title derived from the command that created
|
||||
// the error list
|
||||
typval_T *qf_ctx; // context set by setqflist/setloclist
|
||||
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
|
||||
int qf_count; ///< number of errors (0 means empty list)
|
||||
int qf_index; ///< current index in the error list
|
||||
int qf_nonevalid; ///< TRUE if not a single valid entry found
|
||||
char_u *qf_title; ///< title derived from the command that created
|
||||
///< the error list or set by setqflist
|
||||
typval_T *qf_ctx; ///< context set by setqflist/setloclist
|
||||
} qf_list_T;
|
||||
|
||||
/// Quickfix/Location list stack definition
|
||||
/// Contains a list of quickfix/location lists (qf_list_T)
|
||||
struct qf_info_S {
|
||||
/*
|
||||
* Count of references to this list. Used only for location lists.
|
||||
@@ -1185,6 +1192,9 @@ qf_init_end:
|
||||
|
||||
static void qf_store_title(qf_info_T *qi, int qf_idx, char_u *title)
|
||||
{
|
||||
xfree(qi->qf_lists[qf_idx].qf_title);
|
||||
qi->qf_lists[qf_idx].qf_title = NULL;
|
||||
|
||||
if (title != NULL) {
|
||||
size_t len = STRLEN(title) + 1;
|
||||
char_u *p = xmallocz(len);
|
||||
@@ -2396,8 +2406,9 @@ void qf_history(exarg_T *eap)
|
||||
}
|
||||
}
|
||||
|
||||
/// Free all the entries in the error list "idx".
|
||||
static void qf_free(qf_info_T *qi, int 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 qf_free_items(qf_info_T *qi, int idx)
|
||||
{
|
||||
qfline_T *qfp;
|
||||
qfline_T *qfpnext;
|
||||
@@ -2421,12 +2432,9 @@ static void qf_free(qf_info_T *qi, int idx)
|
||||
qi->qf_lists[idx].qf_start = qfpnext;
|
||||
qi->qf_lists[idx].qf_count--;
|
||||
}
|
||||
xfree(qi->qf_lists[idx].qf_title);
|
||||
|
||||
qi->qf_lists[idx].qf_start = NULL;
|
||||
qi->qf_lists[idx].qf_ptr = NULL;
|
||||
qi->qf_lists[idx].qf_title = NULL;
|
||||
tv_free(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_start = NULL;
|
||||
qi->qf_lists[idx].qf_last = NULL;
|
||||
@@ -2442,6 +2450,18 @@ static void qf_free(qf_info_T *qi, int idx)
|
||||
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);
|
||||
|
||||
xfree(qi->qf_lists[idx].qf_title);
|
||||
qi->qf_lists[idx].qf_title = NULL;
|
||||
tv_free(qi->qf_lists[idx].qf_ctx);
|
||||
qi->qf_lists[idx].qf_ctx = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* qf_mark_adjust: adjust marks
|
||||
*/
|
||||
@@ -4150,6 +4170,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
if (tv_dict_find(what, S_LEN("context")) != NULL) {
|
||||
flags |= QF_GETLIST_CONTEXT;
|
||||
}
|
||||
|
||||
if (tv_dict_find(what, S_LEN("items")) != NULL) {
|
||||
flags |= QF_GETLIST_ITEMS;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & QF_GETLIST_TITLE) {
|
||||
@@ -4168,6 +4192,11 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
|
||||
status = tv_dict_add_nr(retdict, S_LEN("winid"), win->handle);
|
||||
}
|
||||
}
|
||||
if ((status == OK) && (flags & QF_GETLIST_ITEMS)) {
|
||||
list_T *l = tv_list_alloc();
|
||||
(void)get_errorlist(wp, qf_idx, l);
|
||||
tv_dict_add_list(retdict, S_LEN("items"), l);
|
||||
}
|
||||
|
||||
if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) {
|
||||
if (qi->qf_lists[qf_idx].qf_ctx != NULL) {
|
||||
@@ -4204,7 +4233,7 @@ static int qf_add_entries(qf_info_T *qi, int qf_idx, list_T *list,
|
||||
// Adding to existing list, use last entry.
|
||||
old_last = qi->qf_lists[qf_idx].qf_last;
|
||||
} else if (action == 'r') {
|
||||
qf_free(qi, qf_idx);
|
||||
qf_free_items(qi, qf_idx);
|
||||
qf_store_title(qi, qf_idx, title);
|
||||
}
|
||||
|
||||
@@ -4312,17 +4341,24 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
||||
if (di->di_tv.vval.v_number != 0) {
|
||||
qf_idx = (int)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;
|
||||
} else {
|
||||
newlist = false; // use the specified list
|
||||
}
|
||||
} else if (di->di_tv.v_type == VAR_STRING
|
||||
&& strequal((const char *)di->di_tv.vval.v_string, "$")
|
||||
&& qi->qf_listcount > 0) {
|
||||
qf_idx = qi->qf_listcount - 1;
|
||||
newlist = false;
|
||||
} else {
|
||||
return FAIL;
|
||||
}
|
||||
newlist = false; // use the specified list
|
||||
}
|
||||
|
||||
if (newlist) {
|
||||
@@ -4341,6 +4377,15 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action)
|
||||
retval = OK;
|
||||
}
|
||||
}
|
||||
if ((di = tv_dict_find(what, S_LEN("items"))) != 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);
|
||||
xfree(title_save);
|
||||
}
|
||||
}
|
||||
|
||||
if ((di = tv_dict_find(what, S_LEN("context"))) != NULL) {
|
||||
tv_free(qi->qf_lists[qf_idx].qf_ctx);
|
||||
|
@@ -1817,6 +1817,73 @@ func Xproperty_tests(cchar)
|
||||
call test_garbagecollect_now()
|
||||
let m = g:Xgetlist({'context' : 1})
|
||||
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
|
||||
|
||||
func Test_qf_property()
|
||||
|
Reference in New Issue
Block a user