Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions runtime/doc/eval.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4584,6 +4584,7 @@ getqflist([{what}]) *getqflist()*
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}:
context get the context stored using setqflist
nr get information for this quickfix list; zero
means the current quickfix list
title get the list title
Expand All @@ -4595,6 +4596,7 @@ getqflist([{what}]) *getqflist()*
returned.

The returned dictionary contains the following entries:
context context information stored using setqflist
nr quickfix list number
title quickfix list title text
winid quickfix |window-ID| (if opened)
Expand Down Expand Up @@ -6982,6 +6984,7 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
only the items listed in {what} are set. The first {list}
argument is ignored. The following items can be specified in
{what}:
context any vim type can be stored as a context
nr list number in the quickfix stack
title quickfix list title text
Unsupported keys in {what} are ignored.
Expand Down
4 changes: 4 additions & 0 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -5327,6 +5327,10 @@ garbage_collect(int testing)
abort = abort || set_ref_in_timer(copyID);
#endif

#ifdef FEAT_QUICKFIX
abort = abort || set_ref_in_quickfix(copyID);
#endif

if (!abort)
{
/*
Expand Down
1 change: 1 addition & 0 deletions src/proto/quickfix.pro
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ void ex_vimgrep(exarg_T *eap);
int get_errorlist(win_T *wp, int qf_idx, list_T *list);
int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict);
int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *what);
int set_ref_in_quickfix(int copyID);
void ex_cbuffer(exarg_T *eap);
void ex_cexpr(exarg_T *eap);
void ex_helpgrep(exarg_T *eap);
Expand Down
87 changes: 87 additions & 0 deletions src/quickfix.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ typedef struct qf_list_S
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 */
} qf_list_T;

struct qf_info_S
Expand Down Expand Up @@ -1596,6 +1597,14 @@ copy_loclist(win_T *from, win_T *to)
to_qfl->qf_title = vim_strsave(from_qfl->qf_title);
else
to_qfl->qf_title = NULL;
if (from_qfl->qf_ctx != NULL)
{
to_qfl->qf_ctx = alloc_tv();
if (to_qfl->qf_ctx != NULL)
copy_tv(from_qfl->qf_ctx, to_qfl->qf_ctx);
}
else
to_qfl->qf_ctx = NULL;

if (from_qfl->qf_count)
{
Expand Down Expand Up @@ -2749,6 +2758,8 @@ qf_free(qf_info_T *qi, int 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;
qi->qf_lists[idx].qf_index = 0;
qi->qf_lists[idx].qf_start = NULL;
qi->qf_lists[idx].qf_last = NULL;
Expand Down Expand Up @@ -4629,6 +4640,7 @@ enum {
QF_GETLIST_ITEMS = 0x2,
QF_GETLIST_NR = 0x4,
QF_GETLIST_WINID = 0x8,
QF_GETLIST_CONTEXT = 0x10,
QF_GETLIST_ALL = 0xFF
};

Expand Down Expand Up @@ -4681,6 +4693,9 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
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 (flags & QF_GETLIST_TITLE)
{
char_u *t;
Expand All @@ -4699,6 +4714,22 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
status = dict_add_nr_str(retdict, "winid", win->w_id, NULL);
}

if ((status == OK) && (flags & QF_GETLIST_CONTEXT))
{
if (qi->qf_lists[qf_idx].qf_ctx != NULL)
{
dictitem_T *di;
di = dictitem_alloc((char_u *)"context");
if (di != NULL)
{
copy_tv(qi->qf_lists[qf_idx].qf_ctx, &di->di_tv);
dict_add(retdict, di);
}
}
else
status = dict_add_nr_str(retdict, "context", 0L, (char_u *)"");
}

return status;
}

Expand Down Expand Up @@ -4874,6 +4905,16 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action)
}
}

if ((di = dict_find(what, (char_u *)"context", -1)) != NULL)
{
typval_T *ctx;
free_tv(qi->qf_lists[qi->qf_curlist].qf_ctx);
ctx = alloc_tv();
if (ctx != NULL)
copy_tv(&di->di_tv, ctx);
qi->qf_lists[qi->qf_curlist].qf_ctx = ctx;
}

return retval;
}

Expand Down Expand Up @@ -4981,6 +5022,52 @@ set_errorlist(

return retval;
}

static int
mark_quickfix_ctx(qf_info_T *qi, int copyID)
{
int i;
int abort = FALSE;
typval_T *ctx;

for (i = 0; i < LISTCOUNT && !abort; ++i)
{
ctx = qi->qf_lists[i].qf_ctx;
if (ctx != NULL && ctx->v_type != VAR_NUMBER &&
ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT)
abort = set_ref_in_item(ctx, copyID, NULL, NULL);
}

return abort;
}

/*
* Mark the context of the quickfix list and the location lists (if present) as
* "in use". So that garabage collection doesn't free the context.
*/
int
set_ref_in_quickfix(int copyID)
{
int abort = FALSE;
tabpage_T *tp;
win_T *win;

abort = mark_quickfix_ctx(&ql_info, copyID);
if (abort)
return abort;

FOR_ALL_TAB_WINDOWS(tp, win)
{
if (win->w_llist != NULL)
{
abort = mark_quickfix_ctx(win->w_llist, copyID);
if (abort)
return abort;
}
}

return abort;
}
#endif

/*
Expand Down
32 changes: 32 additions & 0 deletions src/testdir/test_quickfix.vim
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,38 @@ func Xproperty_tests(cchar)
if a:cchar == 'l'
call assert_equal({}, getloclist(99, {'title': 1}))
endif

" Context related tests
call g:Xsetlist([], 'a', {'context':[1,2,3]})
call test_garbagecollect_now()
let d = g:Xgetlist({'context':1})
call assert_equal([1,2,3], d.context)
call g:Xsetlist([], 'a', {'context':{'color':'green'}})
let d = g:Xgetlist({'context':1})
call assert_equal({'color':'green'}, d.context)
call g:Xsetlist([], 'a', {'context':"Context info"})
let d = g:Xgetlist({'context':1})
call assert_equal("Context info", d.context)
call g:Xsetlist([], 'a', {'context':246})
let d = g:Xgetlist({'context':1})
call assert_equal(246, d.context)
if a:cchar == 'l'
" Test for copying context across two different location lists
new | only
let w1_id = win_getid()
let l = [1]
call setloclist(0, [], 'a', {'context':l})
new
let w2_id = win_getid()
call add(l, 2)
call assert_equal([1, 2], getloclist(w1_id, {'context':1}).context)
call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
unlet! l
call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context)
only
call setloclist(0, [], 'f')
call assert_equal({}, getloclist(0, {'context':1}))
endif
endfunc

func Test_qf_property()
Expand Down