# HG changeset patch # User Christian Brabandt # Date 1502624704 -7200 # Node ID 69ce6b3f0834bbe42f10268a79b32bc0b60e427e # Parent 23073dd342fe87dbceb77fd779524b17935bc9ca patch 8.0.0922: quickfix list always added after current one commit https://github.com/vim/vim/commit/55b6926450d75788dada3ff44a35e328224df758 Author: Bram Moolenaar Date: Sun Aug 13 13:42:01 2017 +0200 patch 8.0.0922: quickfix list always added after current one Problem: Quickfix list always added after current one. Solution: Make it possible to add a quickfix list after the last one. (Yegappan Lakshmanan) diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -7023,7 +7023,10 @@ setqflist({list} [, {action}[, {what}]]) freed. If {action} is not present or is set to ' ', then a new list - is created. + is created. The new quickfix list is added after the current + quickfix list in the stack and all the following lists are + freed. To add a new quickfix list at the end of the stack, + set "nr" in {what} to '$'. If the optional {what} dictionary argument is supplied, then only the items listed in {what} are set. The first {list} diff --git a/src/quickfix.c b/src/quickfix.c --- a/src/quickfix.c +++ b/src/quickfix.c @@ -1189,8 +1189,7 @@ qf_init_ext( fields.errmsglen = CMDBUFFSIZE + 1; fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg); fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); - if (fields.namebuf == NULL || fields.errmsg == NULL || - fields.pattern == NULL) + if (fields.namebuf == NULL || fields.errmsg == NULL || fields.pattern == NULL) goto qf_init_end; if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) @@ -1368,7 +1367,9 @@ qf_store_title(qf_info_T *qi, int qf_idx } /* - * Prepare for adding a new quickfix list. + * Prepare for adding a new quickfix list. If the current list is in the + * middle of the stack, then all the following lists are freed and then + * the new list is added. */ static void qf_new_list(qf_info_T *qi, char_u *qf_title) @@ -3830,8 +3831,8 @@ ex_cc(exarg_T *eap) /* For cdo and ldo commands, jump to the nth valid error. * For cfdo and lfdo commands, jump to the nth valid file entry. */ - if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || - eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) + if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo + || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) errornr = qf_get_nth_valid_entry(qi, eap->addr_count > 0 ? (int)eap->line1 : 1, eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo); @@ -3867,9 +3868,9 @@ ex_cnext(exarg_T *eap) } } - if (eap->addr_count > 0 && - (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo && - eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) + if (eap->addr_count > 0 + && (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo + && eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) errornr = (int)eap->line2; else errornr = 1; @@ -4086,8 +4087,8 @@ ex_vimgrep(exarg_T *eap) goto theend; } - if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd && - eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd) + if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd + && eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd) || qi->qf_curlist == qi->qf_listcount) /* make place for a new list */ qf_new_list(qi, title != NULL ? title : *eap->cmdlinep); @@ -4646,10 +4647,10 @@ get_errorlist_properties(win_T *wp, dict if (qi == NULL) { /* If querying for the size of the location list, return 0 */ - if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) && - (di->di_tv.v_type == VAR_STRING) && - (STRCMP(di->di_tv.vval.v_string, "$") == 0)) - return dict_add_nr_str(retdict, "nr", 0, NULL); + if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) + && (di->di_tv.v_type == VAR_STRING) + && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) + return dict_add_nr_str(retdict, "nr", 0, NULL); return FAIL; } } @@ -4666,11 +4667,13 @@ get_errorlist_properties(win_T *wp, dict qf_idx = di->di_tv.vval.v_number - 1; if (qf_idx < 0 || qf_idx >= qi->qf_listcount) return FAIL; - } else if (qi->qf_listcount == 0) /* stack is empty */ + } + else if (qi->qf_listcount == 0) /* stack is empty */ return FAIL; flags |= QF_GETLIST_NR; - } else if ((di->di_tv.v_type == VAR_STRING) && - (STRCMP(di->di_tv.vval.v_string, "$") == 0)) + } + else if ((di->di_tv.v_type == VAR_STRING) + && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) { /* Get the last quickfix list number */ if (qi->qf_listcount > 0) @@ -4905,23 +4908,30 @@ qf_set_properties(qf_info_T *qi, dict_T if (di->di_tv.vval.v_number != 0) qf_idx = di->di_tv.vval.v_number - 1; - if ((action == ' ' || action == 'a') && - 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 + * non-available list and add the new list at the end of the + * stack. */ newlist = TRUE; + qf_idx = qi->qf_listcount - 1; + } else if (qf_idx < 0 || qf_idx >= qi->qf_listcount) return FAIL; - else + else if (action != ' ') newlist = FALSE; /* use the specified list */ - } else if (di->di_tv.v_type == VAR_STRING && - STRCMP(di->di_tv.vval.v_string, "$") == 0 && - qi->qf_listcount > 0) + } + else if (di->di_tv.v_type == VAR_STRING + && STRCMP(di->di_tv.vval.v_string, "$") == 0) { - qf_idx = qi->qf_listcount - 1; - newlist = FALSE; + if (qi->qf_listcount > 0) + qf_idx = qi->qf_listcount - 1; + else if (newlist) + qf_idx = 0; + else + return FAIL; } else return FAIL; @@ -4929,6 +4939,7 @@ qf_set_properties(qf_info_T *qi, dict_T if (newlist) { + qi->qf_curlist = qf_idx; qf_new_list(qi, title); qf_idx = qi->qf_curlist; } @@ -5104,8 +5115,8 @@ mark_quickfix_ctx(qf_info_T *qi, int cop 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) + 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); } diff --git a/src/testdir/test_quickfix.vim b/src/testdir/test_quickfix.vim --- a/src/testdir/test_quickfix.vim +++ b/src/testdir/test_quickfix.vim @@ -11,7 +11,7 @@ func s:setup_commands(cchar) command! -nargs=* -bang Xlist clist command! -nargs=* Xgetexpr cgetexpr command! -nargs=* Xaddexpr caddexpr - command! -nargs=* Xolder colder + command! -nargs=* -count Xolder colder command! -nargs=* Xnewer cnewer command! -nargs=* Xopen copen command! -nargs=* Xwindow cwindow @@ -43,7 +43,7 @@ func s:setup_commands(cchar) command! -nargs=* -bang Xlist llist command! -nargs=* Xgetexpr lgetexpr command! -nargs=* Xaddexpr laddexpr - command! -nargs=* Xolder lolder + command! -nargs=* -count Xolder lolder command! -nargs=* Xnewer lnewer command! -nargs=* Xopen lopen command! -nargs=* Xwindow lwindow @@ -1745,7 +1745,7 @@ func Xproperty_tests(cchar) call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title) " Changing the title of an earlier quickfix list - call g:Xsetlist([], ' ', {'title' : 'NewTitle', 'nr' : 2}) + call g:Xsetlist([], 'r', {'title' : 'NewTitle', 'nr' : 2}) call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title) " Changing the title of an invalid quickfix list @@ -1812,10 +1812,10 @@ func Xproperty_tests(cchar) Xexpr "One" Xexpr "Two" Xexpr "Three" - call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1}) - call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2}) + call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1}) + call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2}) " Also, check for setting the context using quickfix list number zero. - call g:Xsetlist([], ' ', {'context' : [3], 'nr' : 0}) + call g:Xsetlist([], 'r', {'context' : [3], 'nr' : 0}) call test_garbagecollect_now() let l = g:Xgetlist({'nr' : 1, 'context' : 1}) call assert_equal([1], l.context) @@ -2433,3 +2433,89 @@ func Test_Multi_LL_Help() call assert_true(len(getloclist(2)) != 0) new | only endfunc + +" Tests for adding new quickfix lists using setqflist() +func XaddQf_tests(cchar) + call s:setup_commands(a:cchar) + + " Create a new list using ' ' for action + call g:Xsetlist([], 'f') + call g:Xsetlist([], ' ', {'title' : 'Test1'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(1, l.nr) + call assert_equal('Test1', l.title) + + " Create a new list using ' ' for action and '$' for 'nr' + call g:Xsetlist([], 'f') + call g:Xsetlist([], ' ', {'title' : 'Test2', 'nr' : '$'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(1, l.nr) + call assert_equal('Test2', l.title) + + " Create a new list using 'a' for action + call g:Xsetlist([], 'f') + call g:Xsetlist([], 'a', {'title' : 'Test3'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(1, l.nr) + call assert_equal('Test3', l.title) + + " Create a new list using 'a' for action and '$' for 'nr' + call g:Xsetlist([], 'f') + call g:Xsetlist([], 'a', {'title' : 'Test3', 'nr' : '$'}) + call g:Xsetlist([], 'a', {'title' : 'Test4'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(1, l.nr) + call assert_equal('Test4', l.title) + + " Adding a quickfix list should remove all the lists following the current + " list. + Xexpr "" | Xexpr "" | Xexpr "" + silent! 10Xolder + call g:Xsetlist([], ' ', {'title' : 'Test5'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(2, l.nr) + call assert_equal('Test5', l.title) + + " Add a quickfix list using '$' as the list number. + let lastqf = g:Xgetlist({'nr':'$'}).nr + silent! 99Xolder + call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test6'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(lastqf + 1, l.nr) + call assert_equal('Test6', l.title) + + " Add a quickfix list using 'nr' set to one more than the quickfix + " list size. + let lastqf = g:Xgetlist({'nr':'$'}).nr + silent! 99Xolder + call g:Xsetlist([], ' ', {'nr' : lastqf + 1, 'title' : 'Test7'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(lastqf + 1, l.nr) + call assert_equal('Test7', l.title) + + " Add a quickfix list to a stack with 10 lists using 'nr' set to '$' + exe repeat('Xexpr "" |', 9) . 'Xexpr ""' + silent! 99Xolder + call g:Xsetlist([], ' ', {'nr' : '$', 'title' : 'Test8'}) + let l = g:Xgetlist({'nr' : '$', 'all' : 1}) + call assert_equal(10, l.nr) + call assert_equal('Test8', l.title) + + " Add a quickfix list using 'nr' set to a value greater than 10 + call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 12, 'title' : 'Test9'})) + + " Try adding a quickfix list with 'nr' set to a value greater than the + " quickfix list size but less than 10. + call g:Xsetlist([], 'f') + Xexpr "" | Xexpr "" | Xexpr "" + silent! 99Xolder + call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : 8, 'title' : 'Test10'})) + + " Add a quickfix list using 'nr' set to a some string or list + call assert_equal(-1, g:Xsetlist([], ' ', {'nr' : [1,2], 'title' : 'Test11'})) +endfunc + +func Test_add_qf() + call XaddQf_tests('c') + call XaddQf_tests('l') +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -770,6 +770,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 922, +/**/ 921, /**/ 920,