aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c64
-rw-r--r--src/nvim/eval.lua4
-rw-r--r--src/nvim/quickfix.c184
-rw-r--r--src/nvim/tag.c2
-rw-r--r--src/nvim/testdir/test_quickfix.vim39
-rw-r--r--src/nvim/version.c2
6 files changed, 248 insertions, 47 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 942a82a040..672c9158ce 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -11065,6 +11065,37 @@ static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
get_buffer_lines(curbuf, lnum, end, retlist, rettv);
}
+static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg,
+ typval_T *rettv)
+{
+ if (what_arg->v_type == VAR_UNKNOWN) {
+ rettv_list_alloc(rettv);
+ if (is_qf || wp != NULL) {
+ (void)get_errorlist(wp, -1, rettv->vval.v_list);
+ }
+ } else {
+ rettv_dict_alloc(rettv);
+ if (is_qf || wp != NULL) {
+ if (what_arg->v_type == VAR_DICT) {
+ dict_T *d = what_arg->vval.v_dict;
+
+ if (d != NULL) {
+ get_errorlist_properties(wp, d, rettv->vval.v_dict);
+ }
+ } else {
+ EMSG(_(e_dictreq));
+ }
+ }
+ }
+}
+
+/// "getloclist()" function
+static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
+{
+ win_T *wp = find_win_by_nr(&argvars[0], NULL);
+ get_qf_loc_list(false, wp, &argvars[1], rettv);
+}
+
/*
* "getmatches()" function
*/
@@ -11166,20 +11197,10 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
getpos_both(argvars, rettv, false);
}
-/*
- * "getqflist()" and "getloclist()" functions
- */
+/// "getqflist()" functions
static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- rettv_list_alloc(rettv);
- win_T *wp = NULL;
- if (argvars[0].v_type != VAR_UNKNOWN) { /* getloclist() */
- wp = find_win_by_nr(&argvars[0], NULL);
- if (wp == NULL) {
- return;
- }
- }
- (void)get_errorlist(wp, rettv->vval.v_list);
+ get_qf_loc_list(true, NULL, &argvars[0], rettv);
}
/// "getreg()" function
@@ -15721,7 +15742,7 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// Create quickfix/location list from VimL values
///
/// Used by `setqflist()` and `setloclist()` functions. Accepts invalid
-/// list_arg, action_arg and title_arg arguments in which case errors out,
+/// list_arg, action_arg and what_arg arguments in which case errors out,
/// including VAR_UNKNOWN parameters.
///
/// @param[in,out] wp Window to create location list for. May be NULL in
@@ -15738,6 +15759,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)
char_u *title = NULL;
int action = ' ';
rettv->vval.v_number = -1;
+ dict_T *d = NULL;
typval_T *list_arg = &args[0];
if (list_arg->v_type != VAR_LIST) {
@@ -15765,10 +15787,16 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)
if (title_arg->v_type == VAR_UNKNOWN) {
// Option argument was not given.
goto skip_args;
- }
- title = get_tv_string_chk(title_arg);
- if (!title) {
- // Type error. Error already printed by get_tv_string_chk().
+ } else if (title_arg->v_type == VAR_STRING) {
+ title = get_tv_string_chk(title_arg);
+ if (!title) {
+ // Type error. Error already printed by get_tv_string_chk().
+ return;
+ }
+ } else if (title_arg->v_type == VAR_DICT) {
+ d = title_arg->vval.v_dict;
+ } else {
+ EMSG(_(e_dictreq));
return;
}
@@ -15778,7 +15806,7 @@ skip_args:
}
list_T *l = list_arg->vval.v_list;
- if (l && set_errorlist(wp, l, action, title) == OK) {
+ if (l && set_errorlist(wp, l, action, title, d) == OK) {
rettv->vval.v_number = 0;
}
}
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index b0bf417207..fa19ff209e 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -126,11 +126,11 @@ return {
getftime={args=1},
getftype={args=1},
getline={args={1, 2}},
- getloclist={args=1, func='f_getqflist'},
+ getloclist={args={1, 2}},
getmatches={},
getpid={},
getpos={args=1},
- getqflist={},
+ getqflist={args={0, 1}},
getreg={args={0, 3}},
getregtype={args={0, 1}},
gettabinfo={args={0, 1}},
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 0da98713df..a4c3ec2430 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -2637,6 +2637,19 @@ static buf_T *qf_find_buf(qf_info_T *qi)
return NULL;
}
+/// Update the w:quickfix_title variable in the quickfix/location list window
+static void qf_update_win_titlevar(qf_info_T *qi)
+{
+ win_T *win;
+
+ if ((win = qf_find_win(qi)) != NULL) {
+ win_T *curwin_save = curwin;
+ curwin = win;
+ qf_set_title_var(qi);
+ curwin = curwin_save;
+ }
+}
+
/*
* Find the quickfix buffer. If it exists, update the contents.
*/
@@ -2644,7 +2657,6 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
{
buf_T *buf;
win_T *win;
- win_T *curwin_save;
aco_save_T aco;
/* Check if a buffer for the quickfix list exists. Update it. */
@@ -2657,12 +2669,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
aucmd_prepbuf(&aco, buf);
}
- if ((win = qf_find_win(qi)) != NULL) {
- curwin_save = curwin;
- curwin = win;
- qf_set_title_var(qi);
- curwin = curwin_save;
- }
+ qf_update_win_titlevar(qi);
qf_fill_buffer(qi, buf, old_last);
@@ -3849,10 +3856,9 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
}
}
-/*
- * Add each quickfix error to list "list" as a dictionary.
- */
-int get_errorlist(win_T *wp, list_T *list)
+/// Add each quickfix error to list "list" as a dictionary.
+/// If qf_idx is -1, use the current list. Otherwise, use the specified list.
+int get_errorlist(win_T *wp, int qf_idx, list_T *list)
{
qf_info_T *qi = &ql_info;
dict_T *dict;
@@ -3867,13 +3873,18 @@ int get_errorlist(win_T *wp, list_T *list)
return FAIL;
}
- if (qi->qf_curlist >= qi->qf_listcount
- || qi->qf_lists[qi->qf_curlist].qf_count == 0)
+ if (qf_idx == -1) {
+ qf_idx = qi->qf_curlist;
+ }
+
+ if (qf_idx >= qi->qf_listcount
+ || qi->qf_lists[qf_idx].qf_count == 0) {
return FAIL;
+ }
- qfp = qi->qf_lists[qi->qf_curlist].qf_start;
- for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i) {
- /* Handle entries with a non-existing buffer number. */
+ qfp = qi->qf_lists[qf_idx].qf_start;
+ for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; i++) {
+ // Handle entries with a non-existing buffer number.
bufnum = qfp->qf_fnum;
if (bufnum != 0 && (buflist_findnr(bufnum) == NULL))
bufnum = 0;
@@ -3904,22 +3915,91 @@ int get_errorlist(win_T *wp, list_T *list)
return OK;
}
-// Populate the quickfix list with the items supplied in the list
-// of dictionaries. "title" will be copied to w:quickfix_title
-// "action" is 'a' for add, 'r' for replace. Otherwise create a new list.
-int set_errorlist(win_T *wp, list_T *list, int action, char_u *title)
+/// Flags used by getqflist()/getloclist() to determine which fields to return.
+enum {
+ QF_GETLIST_NONE = 0x0,
+ QF_GETLIST_TITLE = 0x1,
+ QF_GETLIST_ITEMS = 0x2,
+ QF_GETLIST_NR = 0x4,
+ QF_GETLIST_WINID = 0x8,
+ QF_GETLIST_ALL = 0xFF
+};
+
+/// Return quickfix/location list details (title) as a
+/// dictionary. 'what' contains the details to return. If 'list_idx' is -1,
+/// then current list is used. Otherwise the specified list is used.
+int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
+{
+ qf_info_T *qi = &ql_info;
+
+ if (wp != NULL) {
+ qi = GET_LOC_LIST(wp);
+ if (qi == NULL) {
+ return FAIL;
+ }
+ }
+
+ int status = OK;
+ dictitem_T *di;
+ int flags = QF_GETLIST_NONE;
+
+ int qf_idx = qi->qf_curlist; // default is the current list
+ if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) {
+ // Use the specified quickfix/location list
+ if (di->di_tv.v_type == VAR_NUMBER) {
+ qf_idx = di->di_tv.vval.v_number - 1;
+ if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
+ return FAIL;
+ }
+ flags |= QF_GETLIST_NR;
+ } else {
+ return FAIL;
+ }
+ }
+
+ 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 (flags & QF_GETLIST_TITLE) {
+ char_u *t = qi->qf_lists[qf_idx].qf_title;
+ if (t == NULL) {
+ t = (char_u *)"";
+ }
+ status = dict_add_nr_str(retdict, "title", 0L, t);
+ }
+ if ((status == OK) && (flags & QF_GETLIST_NR)) {
+ status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL);
+ }
+ if ((status == OK) && (flags & QF_GETLIST_WINID)) {
+ win_T *win = qf_find_win(qi);
+ if (win != NULL) {
+ status = dict_add_nr_str(retdict, "winid", win->handle, NULL);
+ }
+ }
+
+ return status;
+}
+
+/// Add list of entries to quickfix/location list. Each list entry is
+/// a dictionary with item information.
+static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title,
+ int action)
{
listitem_T *li;
dict_T *d;
qfline_T *old_last = NULL;
int retval = OK;
- qf_info_T *qi = &ql_info;
bool did_bufnr_emsg = false;
- if (wp != NULL) {
- qi = ll_get_or_alloc_list(wp);
- }
-
if (action == ' ' || qi->qf_curlist == qi->qf_listcount) {
// make place for a new list
qf_new_list(qi, title);
@@ -4010,6 +4090,60 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title)
return retval;
}
+static int qf_set_properties(qf_info_T *qi, dict_T *what)
+{
+ dictitem_T *di;
+ int retval = FAIL;
+
+ int qf_idx = qi->qf_curlist; // default is the current list
+ if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) {
+ // Use the specified quickfix/location list
+ if (di->di_tv.v_type == VAR_NUMBER) {
+ qf_idx = di->di_tv.vval.v_number - 1;
+ if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
+ return FAIL;
+ }
+ } else {
+ return FAIL;
+ }
+ }
+
+ if ((di = dict_find(what, (char_u *)"title", -1)) != NULL) {
+ if (di->di_tv.v_type == VAR_STRING) {
+ xfree(qi->qf_lists[qf_idx].qf_title);
+ qi->qf_lists[qf_idx].qf_title = get_dict_string(what, "title", true);
+ if (qf_idx == qi->qf_curlist) {
+ qf_update_win_titlevar(qi);
+ }
+ retval = OK;
+ }
+ }
+
+ return retval;
+}
+
+// Populate the quickfix list with the items supplied in the list
+// of dictionaries. "title" will be copied to w:quickfix_title
+// "action" is 'a' for add, 'r' for replace. Otherwise create a new list.
+int set_errorlist(win_T *wp, list_T *list, int action, char_u *title,
+ dict_T *what)
+{
+ qf_info_T *qi = &ql_info;
+ int retval = OK;
+
+ if (wp != NULL) {
+ qi = ll_get_or_alloc_list(wp);
+ }
+
+ if (what != NULL) {
+ retval = qf_set_properties(qi, what);
+ } else {
+ retval = qf_add_entries(qi, list, title, action);
+ }
+
+ return retval;
+}
+
/*
* ":[range]cbuffer [bufnr]" command.
* ":[range]caddbuffer [bufnr]" command.
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index cc5aac6094..59f4c1e968 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -789,7 +789,7 @@ do_tag (
}
vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag);
- set_errorlist(curwin, list, ' ', IObuff);
+ set_errorlist(curwin, list, ' ', IObuff, NULL);
list_free(list);
xfree(fname);
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index 7464a11abd..0d6e5e1830 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1462,3 +1462,42 @@ func Test_duplicate_buf()
call delete('Xgrepthis')
endfunc
+
+" Quickfix/Location list set/get properties tests
+function Xproperty_tests(cchar)
+ call s:setup_commands(a:cchar)
+
+ " Error cases
+ call assert_fails('call g:Xgetlist(99)', 'E715:')
+ call assert_fails('call g:Xsetlist(99)', 'E714:')
+ call assert_fails('call g:Xsetlist([], "a", [])', 'E715:')
+
+ " Set and get the title
+ Xopen
+ wincmd p
+ call g:Xsetlist([{'filename':'foo', 'lnum':27}])
+ call g:Xsetlist([], 'a', {'title' : 'Sample'})
+ let d = g:Xgetlist({"title":1})
+ call assert_equal('Sample', d.title)
+
+ Xopen
+ call assert_equal('Sample', w:quickfix_title)
+ Xclose
+
+ " Invalid arguments
+ call assert_fails('call g:Xgetlist([])', 'E715')
+ call assert_fails('call g:Xsetlist([], "a", [])', 'E715')
+ let s = g:Xsetlist([], 'a', {'abc':1})
+ call assert_equal(-1, s)
+
+ call assert_equal({}, g:Xgetlist({'abc':1}))
+
+ if a:cchar == 'l'
+ call assert_equal({}, getloclist(99, ['title']))
+ endif
+endfunction
+
+function Test_qf_property()
+ call Xproperty_tests('c')
+ call Xproperty_tests('l')
+endfunction
diff --git a/src/nvim/version.c b/src/nvim/version.c
index fe443ce01f..0374e02e02 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -240,7 +240,7 @@ static int included_patches[] = {
// 2203 NA
// 2202 NA
2201,
- // 2200,
+ 2200,
// 2199 NA
// 2198 NA
2197,