diff options
author | James McCoy <jamessan@jamessan.com> | 2017-02-27 14:35:57 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-27 14:35:57 -0500 |
commit | d290c1342117867d4fb1e8ffbe685037553971a5 (patch) | |
tree | b72fbf5e641bc2558ac5f34f9bbc7f4cc57e4b27 /src | |
parent | be65fd88f40cc0a955b25f7ef78bd954f3986046 (diff) | |
parent | a989851e3b66cd1c14c6c674b83f302648df0b82 (diff) | |
download | rneovim-d290c1342117867d4fb1e8ffbe685037553971a5.tar.gz rneovim-d290c1342117867d4fb1e8ffbe685037553971a5.tar.bz2 rneovim-d290c1342117867d4fb1e8ffbe685037553971a5.zip |
Merge pull request #6188 from jamessan/vim-7.4.2200
vim-patch:7.4.2200
Closes #5314
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 64 | ||||
-rw-r--r-- | src/nvim/eval.lua | 4 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 184 | ||||
-rw-r--r-- | src/nvim/tag.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 39 | ||||
-rw-r--r-- | src/nvim/version.c | 2 |
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, |