0
0
mirror of https://github.com/vim/vim.git synced 2025-09-25 03:54:15 -04:00

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)
This commit is contained in:
Bram Moolenaar
2017-08-13 13:42:01 +02:00
parent 3d9bdfebf1
commit 55b6926450
4 changed files with 137 additions and 35 deletions

View File

@@ -7023,7 +7023,10 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
freed. freed.
If {action} is not present or is set to ' ', then a new list 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 If the optional {what} dictionary argument is supplied, then
only the items listed in {what} are set. The first {list} only the items listed in {what} are set. The first {list}

View File

@@ -1189,8 +1189,7 @@ qf_init_ext(
fields.errmsglen = CMDBUFFSIZE + 1; fields.errmsglen = CMDBUFFSIZE + 1;
fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg); fields.errmsg = alloc_id(fields.errmsglen, aid_qf_errmsg);
fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern); fields.pattern = alloc_id(CMDBUFFSIZE + 1, aid_qf_pattern);
if (fields.namebuf == NULL || fields.errmsg == NULL || if (fields.namebuf == NULL || fields.errmsg == NULL || fields.pattern == NULL)
fields.pattern == NULL)
goto qf_init_end; goto qf_init_end;
if (efile != NULL && (state.fd = mch_fopen((char *)efile, "r")) == NULL) 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, char_u *title)
} }
/* /*
* 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 static void
qf_new_list(qf_info_T *qi, char_u *qf_title) 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 cdo and ldo commands, jump to the nth valid error.
* For cfdo and lfdo commands, jump to the nth valid file entry. * For cfdo and lfdo commands, jump to the nth valid file entry.
*/ */
if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo
eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo)
errornr = qf_get_nth_valid_entry(qi, errornr = qf_get_nth_valid_entry(qi,
eap->addr_count > 0 ? (int)eap->line1 : 1, eap->addr_count > 0 ? (int)eap->line1 : 1,
eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo); eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo);
@@ -3867,9 +3868,9 @@ ex_cnext(exarg_T *eap)
} }
} }
if (eap->addr_count > 0 && if (eap->addr_count > 0
(eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo && && (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo
eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) && eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo))
errornr = (int)eap->line2; errornr = (int)eap->line2;
else else
errornr = 1; errornr = 1;
@@ -4086,8 +4087,8 @@ ex_vimgrep(exarg_T *eap)
goto theend; goto theend;
} }
if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd && if ((eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd
eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd) && eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
|| qi->qf_curlist == qi->qf_listcount) || qi->qf_curlist == qi->qf_listcount)
/* make place for a new list */ /* make place for a new list */
qf_new_list(qi, title != NULL ? title : *eap->cmdlinep); qf_new_list(qi, title != NULL ? title : *eap->cmdlinep);
@@ -4646,10 +4647,10 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (qi == NULL) if (qi == NULL)
{ {
/* If querying for the size of the location list, return 0 */ /* If querying for the size of the location list, return 0 */
if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) && if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL)
(di->di_tv.v_type == VAR_STRING) && && (di->di_tv.v_type == VAR_STRING)
(STRCMP(di->di_tv.vval.v_string, "$") == 0)) && (STRCMP(di->di_tv.vval.v_string, "$") == 0))
return dict_add_nr_str(retdict, "nr", 0, NULL); return dict_add_nr_str(retdict, "nr", 0, NULL);
return FAIL; return FAIL;
} }
} }
@@ -4666,11 +4667,13 @@ get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
qf_idx = di->di_tv.vval.v_number - 1; qf_idx = di->di_tv.vval.v_number - 1;
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
return FAIL; return FAIL;
} else if (qi->qf_listcount == 0) /* stack is empty */ }
else if (qi->qf_listcount == 0) /* stack is empty */
return FAIL; return FAIL;
flags |= QF_GETLIST_NR; 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 */ /* Get the last quickfix list number */
if (qi->qf_listcount > 0) if (qi->qf_listcount > 0)
@@ -4905,23 +4908,30 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title)
if (di->di_tv.vval.v_number != 0) if (di->di_tv.vval.v_number != 0)
qf_idx = di->di_tv.vval.v_number - 1; qf_idx = di->di_tv.vval.v_number - 1;
if ((action == ' ' || action == 'a') && if ((action == ' ' || action == 'a') && qf_idx == qi->qf_listcount)
qf_idx == qi->qf_listcount) {
/* /*
* When creating a new list, accept qf_idx pointing to the next * 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; newlist = TRUE;
qf_idx = qi->qf_listcount - 1;
}
else if (qf_idx < 0 || qf_idx >= qi->qf_listcount) else if (qf_idx < 0 || qf_idx >= qi->qf_listcount)
return FAIL; return FAIL;
else else if (action != ' ')
newlist = FALSE; /* use the specified list */ newlist = FALSE; /* use the specified list */
} 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
qi->qf_listcount > 0) && STRCMP(di->di_tv.vval.v_string, "$") == 0)
{ {
qf_idx = qi->qf_listcount - 1; if (qi->qf_listcount > 0)
newlist = FALSE; qf_idx = qi->qf_listcount - 1;
else if (newlist)
qf_idx = 0;
else
return FAIL;
} }
else else
return FAIL; return FAIL;
@@ -4929,6 +4939,7 @@ qf_set_properties(qf_info_T *qi, dict_T *what, int action, char_u *title)
if (newlist) if (newlist)
{ {
qi->qf_curlist = qf_idx;
qf_new_list(qi, title); qf_new_list(qi, title);
qf_idx = qi->qf_curlist; qf_idx = qi->qf_curlist;
} }
@@ -5104,8 +5115,8 @@ mark_quickfix_ctx(qf_info_T *qi, int copyID)
for (i = 0; i < LISTCOUNT && !abort; ++i) for (i = 0; i < LISTCOUNT && !abort; ++i)
{ {
ctx = qi->qf_lists[i].qf_ctx; ctx = qi->qf_lists[i].qf_ctx;
if (ctx != NULL && ctx->v_type != VAR_NUMBER && if (ctx != NULL && ctx->v_type != VAR_NUMBER
ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT) && ctx->v_type != VAR_STRING && ctx->v_type != VAR_FLOAT)
abort = set_ref_in_item(ctx, copyID, NULL, NULL); abort = set_ref_in_item(ctx, copyID, NULL, NULL);
} }

View File

@@ -11,7 +11,7 @@ func s:setup_commands(cchar)
command! -nargs=* -bang Xlist <mods>clist<bang> <args> command! -nargs=* -bang Xlist <mods>clist<bang> <args>
command! -nargs=* Xgetexpr <mods>cgetexpr <args> command! -nargs=* Xgetexpr <mods>cgetexpr <args>
command! -nargs=* Xaddexpr <mods>caddexpr <args> command! -nargs=* Xaddexpr <mods>caddexpr <args>
command! -nargs=* Xolder <mods>colder <args> command! -nargs=* -count Xolder <mods><count>colder <args>
command! -nargs=* Xnewer <mods>cnewer <args> command! -nargs=* Xnewer <mods>cnewer <args>
command! -nargs=* Xopen <mods>copen <args> command! -nargs=* Xopen <mods>copen <args>
command! -nargs=* Xwindow <mods>cwindow <args> command! -nargs=* Xwindow <mods>cwindow <args>
@@ -43,7 +43,7 @@ func s:setup_commands(cchar)
command! -nargs=* -bang Xlist <mods>llist<bang> <args> command! -nargs=* -bang Xlist <mods>llist<bang> <args>
command! -nargs=* Xgetexpr <mods>lgetexpr <args> command! -nargs=* Xgetexpr <mods>lgetexpr <args>
command! -nargs=* Xaddexpr <mods>laddexpr <args> command! -nargs=* Xaddexpr <mods>laddexpr <args>
command! -nargs=* Xolder <mods>lolder <args> command! -nargs=* -count Xolder <mods><count>lolder <args>
command! -nargs=* Xnewer <mods>lnewer <args> command! -nargs=* Xnewer <mods>lnewer <args>
command! -nargs=* Xopen <mods>lopen <args> command! -nargs=* Xopen <mods>lopen <args>
command! -nargs=* Xwindow <mods>lwindow <args> command! -nargs=* Xwindow <mods>lwindow <args>
@@ -1745,7 +1745,7 @@ func Xproperty_tests(cchar)
call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title) call assert_equal('N2', g:Xgetlist({'nr':2, 'title':1}).title)
" Changing the title of an earlier quickfix list " 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) call assert_equal('NewTitle', g:Xgetlist({'nr':2, 'title':1}).title)
" Changing the title of an invalid quickfix list " Changing the title of an invalid quickfix list
@@ -1812,10 +1812,10 @@ func Xproperty_tests(cchar)
Xexpr "One" Xexpr "One"
Xexpr "Two" Xexpr "Two"
Xexpr "Three" Xexpr "Three"
call g:Xsetlist([], ' ', {'context' : [1], 'nr' : 1}) call g:Xsetlist([], 'r', {'context' : [1], 'nr' : 1})
call g:Xsetlist([], ' ', {'context' : [2], 'nr' : 2}) call g:Xsetlist([], 'a', {'context' : [2], 'nr' : 2})
" Also, check for setting the context using quickfix list number zero. " 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() call test_garbagecollect_now()
let l = g:Xgetlist({'nr' : 1, 'context' : 1}) let l = g:Xgetlist({'nr' : 1, 'context' : 1})
call assert_equal([1], l.context) call assert_equal([1], l.context)
@@ -2433,3 +2433,89 @@ func Test_Multi_LL_Help()
call assert_true(len(getloclist(2)) != 0) call assert_true(len(getloclist(2)) != 0)
new | only new | only
endfunc 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

View File

@@ -769,6 +769,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
922,
/**/ /**/
921, 921,
/**/ /**/