diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-08-12 16:29:27 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-08-12 16:29:27 +0200 |
commit | d823fa910cca43fec3c31c030ee908a14c272640 (patch) | |
tree | 3584f177ff749708f006f8f8c3467dff95cc9f97 /src | |
parent | 107abd2ca53c31fd3bb40d77ff296e98eaae2975 (diff) |
patch 7.4.2200v7.4.2200
Problem: Cannot get all information about a quickfix list.
Solution: Add an optional argument to get/set loc/qf list(). (Yegappan
Lakshmanan)
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 98 | ||||
-rw-r--r-- | src/proto/quickfix.pro | 5 | ||||
-rw-r--r-- | src/quickfix.c | 210 | ||||
-rw-r--r-- | src/tag.c | 2 | ||||
-rw-r--r-- | src/testdir/test_quickfix.vim | 39 | ||||
-rw-r--r-- | src/version.c | 2 |
6 files changed, 298 insertions, 58 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 8b5ad22fed..8bb002adbf 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -171,6 +171,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv); static void f_getftime(typval_T *argvars, typval_T *rettv); static void f_getftype(typval_T *argvars, typval_T *rettv); static void f_getline(typval_T *argvars, typval_T *rettv); +static void f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED); static void f_getmatches(typval_T *argvars, typval_T *rettv); static void f_getpid(typval_T *argvars, typval_T *rettv); static void f_getcurpos(typval_T *argvars, typval_T *rettv); @@ -591,11 +592,11 @@ static struct fst {"getftime", 1, 1, f_getftime}, {"getftype", 1, 1, f_getftype}, {"getline", 1, 2, f_getline}, - {"getloclist", 1, 1, f_getqflist}, + {"getloclist", 1, 2, f_getloclist}, {"getmatches", 0, 0, f_getmatches}, {"getpid", 0, 0, f_getpid}, {"getpos", 1, 1, f_getpos}, - {"getqflist", 0, 0, f_getqflist}, + {"getqflist", 0, 1, f_getqflist}, {"getreg", 0, 3, f_getreg}, {"getregtype", 0, 1, f_getregtype}, {"gettabvar", 2, 3, f_gettabvar}, @@ -741,10 +742,10 @@ static struct fst {"setcmdpos", 1, 1, f_setcmdpos}, {"setfperm", 2, 2, f_setfperm}, {"setline", 2, 2, f_setline}, - {"setloclist", 2, 3, f_setloclist}, + {"setloclist", 2, 4, f_setloclist}, {"setmatches", 1, 1, f_setmatches}, {"setpos", 2, 2, f_setpos}, - {"setqflist", 1, 2, f_setqflist}, + {"setqflist", 1, 3, f_setqflist}, {"setreg", 2, 3, f_setreg}, {"settabvar", 3, 3, f_settabvar}, {"settabwinvar", 4, 4, f_settabwinvar}, @@ -4529,6 +4530,51 @@ f_getline(typval_T *argvars, typval_T *rettv) 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); + + static void +get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv) +{ +#ifdef FEAT_QUICKFIX + if (what_arg->v_type == VAR_UNKNOWN) + { + if (rettv_list_alloc(rettv) == OK) + if (is_qf || wp != NULL) + (void)get_errorlist(wp, -1, rettv->vval.v_list); + } + else + { + if (rettv_dict_alloc(rettv) == OK) + 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)); + } + } +#endif +} + +/* + * "getloclist()" function + */ + static void +f_getloclist(typval_T *argvars UNUSED, typval_T *rettv UNUSED) +{ +#ifdef FEAT_QUICKFIX + win_T *wp; + + wp = find_win_by_nr(&argvars[0], NULL); + get_qf_loc_list(FALSE, wp, &argvars[1], rettv); +#endif +} + /* * "getmatches()" function */ @@ -4666,28 +4712,13 @@ f_getpos(typval_T *argvars, typval_T *rettv) } /* - * "getqflist()" and "getloclist()" functions + * "getqflist()" function */ static void f_getqflist(typval_T *argvars UNUSED, typval_T *rettv UNUSED) { #ifdef FEAT_QUICKFIX - win_T *wp; -#endif - -#ifdef FEAT_QUICKFIX - if (rettv_list_alloc(rettv) == OK) - { - 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); #endif } @@ -9525,7 +9556,7 @@ f_setline(typval_T *argvars, typval_T *rettv) appended_lines_mark(lcount, added); } -static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *rettv); +static void set_qf_ll_list(win_T *wp, typval_T *list_arg, typval_T *action_arg, typval_T *what_arg, typval_T *rettv); /* * Used by "setqflist()" and "setloclist()" functions @@ -9535,6 +9566,7 @@ set_qf_ll_list( win_T *wp UNUSED, typval_T *list_arg UNUSED, typval_T *action_arg UNUSED, + typval_T *what_arg UNUSED, typval_T *rettv) { #ifdef FEAT_QUICKFIX @@ -9551,6 +9583,8 @@ set_qf_ll_list( else { list_T *l = list_arg->vval.v_list; + dict_T *d = NULL; + int valid_dict = TRUE; if (action_arg->v_type == VAR_STRING) { @@ -9567,8 +9601,20 @@ set_qf_ll_list( else EMSG(_(e_stringreq)); - if (l != NULL && action && set_errorlist(wp, l, action, - (char_u *)(wp == NULL ? "setqflist()" : "setloclist()")) == OK) + if (action_arg->v_type != VAR_UNKNOWN + && what_arg->v_type != VAR_UNKNOWN) + { + if (what_arg->v_type == VAR_DICT) + d = what_arg->vval.v_dict; + else + { + EMSG(_(e_dictreq)); + valid_dict = FALSE; + } + } + + if (l != NULL && action && valid_dict && set_errorlist(wp, l, action, + (char_u *)(wp == NULL ? "setqflist()" : "setloclist()"), d) == OK) rettv->vval.v_number = 0; } #endif @@ -9586,7 +9632,7 @@ f_setloclist(typval_T *argvars, typval_T *rettv) win = find_win_by_nr(&argvars[0], NULL); if (win != NULL) - set_qf_ll_list(win, &argvars[1], &argvars[2], rettv); + set_qf_ll_list(win, &argvars[1], &argvars[2], &argvars[3], rettv); } /* @@ -9754,7 +9800,7 @@ f_setpos(typval_T *argvars, typval_T *rettv) static void f_setqflist(typval_T *argvars, typval_T *rettv) { - set_qf_ll_list(NULL, &argvars[0], &argvars[1], rettv); + set_qf_ll_list(NULL, &argvars[0], &argvars[1], &argvars[2], rettv); } /* diff --git a/src/proto/quickfix.pro b/src/proto/quickfix.pro index 02c2d9831b..99f5edeefd 100644 --- a/src/proto/quickfix.pro +++ b/src/proto/quickfix.pro @@ -27,8 +27,9 @@ void ex_cnext(exarg_T *eap); void ex_cfile(exarg_T *eap); void ex_vimgrep(exarg_T *eap); char_u *skip_vimgrep_pat(char_u *p, char_u **s, int *flags); -int get_errorlist(win_T *wp, list_T *list); -int set_errorlist(win_T *wp, list_T *list, int action, char_u *title); +int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict); +int get_errorlist(win_T *wp, int qf_idx, list_T *list); +int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, dict_T *what); void ex_cbuffer(exarg_T *eap); void ex_cexpr(exarg_T *eap); void ex_helpgrep(exarg_T *eap); diff --git a/src/quickfix.c b/src/quickfix.c index aa94ae69a3..2fa6ed98a9 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -3141,6 +3141,24 @@ qf_find_buf(qf_info_T *qi) } /* + * 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; + win_T *curwin_save; + + if ((win = qf_find_win(qi)) != NULL) + { + curwin_save = curwin; + curwin = win; + qf_set_title_var(qi); + curwin = curwin_save; + } +} + +/* * Find the quickfix buffer. If it exists, update the contents. */ static void @@ -3148,7 +3166,6 @@ 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. */ @@ -3161,13 +3178,7 @@ qf_update_buffer(qf_info_T *qi, qfline_T *old_last) /* set curwin/curbuf to buf and save a few things */ 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); @@ -4532,9 +4543,10 @@ unload_dummy_buffer(buf_T *buf, char_u *dirname_start) #if defined(FEAT_EVAL) || defined(PROTO) /* * 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, list_T *list) +get_errorlist(win_T *wp, int qf_idx, list_T *list) { qf_info_T *qi = &ql_info; dict_T *dict; @@ -4550,12 +4562,15 @@ 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) + 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; @@ -4590,16 +4605,93 @@ get_errorlist(win_T *wp, list_T *list) } /* - * 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. + * 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 -set_errorlist( - win_T *wp, - list_T *list, - int action, - char_u *title) +get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) +{ + qf_info_T *qi = &ql_info; + int status = OK; + int qf_idx; + dictitem_T *di; + int flags = QF_GETLIST_NONE; + + if (wp != NULL) + { + qi = GET_LOC_LIST(wp); + if (qi == NULL) + return FAIL; + } + + 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; + 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; + win = qf_find_win(qi); + if (win != NULL) + status = dict_add_nr_str(retdict, "winid", win->w_id, 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; @@ -4613,16 +4705,8 @@ set_errorlist( #endif int valid, status; int retval = OK; - qf_info_T *qi = &ql_info; int did_bufnr_emsg = FALSE; - if (wp != NULL) - { - qi = ll_get_or_alloc_list(wp); - if (qi == NULL) - return FAIL; - } - if (action == ' ' || qi->qf_curlist == qi->qf_listcount) /* make place for a new list */ qf_new_list(qi, title); @@ -4719,6 +4803,74 @@ set_errorlist( return retval; } + + static int +qf_set_properties(qf_info_T *qi, dict_T *what) +{ + dictitem_T *di; + int retval = FAIL; + int qf_idx; + + 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) + { + vim_free(qi->qf_lists[qf_idx].qf_title); + qi->qf_lists[qf_idx].qf_title = + get_dict_string(what, (char_u *)"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 (qi == NULL) + return FAIL; + } + + if (what != NULL) + retval = qf_set_properties(qi, what); + else + retval = qf_add_entries(qi, list, title, action); + + return retval; +} #endif /* @@ -916,7 +916,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); vim_free(fname); diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim index 9f0b5106e9..b7d985d0df 100644 --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -1505,3 +1505,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/version.c b/src/version.c index b324c12aaa..66648d2708 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2200, +/**/ 2199, /**/ 2198, |