1
0
forked from aniani/vim

patch 9.0.0388: the do_arg_all() function is too long

Problem:    The do_arg_all() function is too long.
Solution:   Split the function in smaller parts. (Yegappan Lakshmanan,
            closes #11062)
This commit is contained in:
Yegappan Lakshmanan
2022-09-05 18:27:47 +01:00
committed by Bram Moolenaar
parent ddf7dba96e
commit 8894761daf
2 changed files with 181 additions and 127 deletions

View File

@@ -574,21 +574,23 @@ ex_args(exarg_T *eap)
alist_new(); alist_new();
} }
// ":args file ..": define new argument list, handle like ":next"
// Also for ":argslocal file .." and ":argsglobal file ..".
if (*eap->arg != NUL) if (*eap->arg != NUL)
{ {
if (check_arglist_locked() == FAIL) if (check_arglist_locked() == FAIL)
return; return;
// ":args file ..": define new argument list, handle like ":next"
// Also for ":argslocal file .." and ":argsglobal file ..".
ex_next(eap); ex_next(eap);
return;
} }
else if (eap->cmdidx == CMD_args)
// ":args": list arguments.
if (eap->cmdidx == CMD_args)
{ {
char_u **items; char_u **items;
// ":args": list arguments.
if (ARGCOUNT <= 0) if (ARGCOUNT <= 0)
return; return; // empty argument list
items = ALLOC_MULT(char_u *, ARGCOUNT); items = ALLOC_MULT(char_u *, ARGCOUNT);
if (items == NULL) if (items == NULL)
@@ -602,12 +604,15 @@ ex_args(exarg_T *eap)
items[i] = alist_name(&ARGLIST[i]); items[i] = alist_name(&ARGLIST[i]);
list_in_columns(items, ARGCOUNT, curwin->w_arg_idx); list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
vim_free(items); vim_free(items);
return;
} }
else if (eap->cmdidx == CMD_arglocal)
// ":argslocal": make a local copy of the global argument list.
if (eap->cmdidx == CMD_arglocal)
{ {
garray_T *gap = &curwin->w_alist->al_ga; garray_T *gap = &curwin->w_alist->al_ga;
// ":argslocal": make a local copy of the global argument list.
if (GA_GROW_FAILS(gap, GARGCOUNT)) if (GA_GROW_FAILS(gap, GARGCOUNT))
return; return;
@@ -919,77 +924,45 @@ alist_name(aentry_T *aep)
} }
/* /*
* do_arg_all(): Open up to 'count' windows, one for each argument. * State used by the :all command to open all the files in the argument list in
* separate windows.
*/ */
static void typedef struct {
do_arg_all( alist_T *alist; // argument list to be used
int count, int had_tab;
int forceit, // hide buffers in current windows int keep_tabs;
int keep_tabs) // keep current tabs, for ":tab drop file" int forceit;
{
int i; int use_firstwin; // use first window for arglist
win_T *wp, *wpnext;
char_u *opened; // Array of weight for which args are open: char_u *opened; // Array of weight for which args are open:
// 0: not opened // 0: not opened
// 1: opened in other tab // 1: opened in other tab
// 2: opened in curtab // 2: opened in curtab
// 3: opened in curtab and curwin // 3: opened in curtab and curwin
//
int opened_len; // length of opened[] int opened_len; // length of opened[]
int use_firstwin = FALSE; // use first window for arglist win_T *new_curwin;
int tab_drop_empty_window = FALSE; tabpage_T *new_curtab;
int split_ret = OK; } arg_all_state_T;
int p_ea_save;
alist_T *alist; // argument list to be used /*
buf_T *buf; * Close all the windows containing files which are not in the argument list.
* Used by the ":all" command.
*/
static void
arg_all_close_unused_windows(arg_all_state_T *aall)
{
win_T *wp;
win_T *wpnext;
tabpage_T *tpnext; tabpage_T *tpnext;
int had_tab = cmdmod.cmod_tab; buf_T *buf;
win_T *old_curwin, *last_curwin; int i;
tabpage_T *old_curtab, *last_curtab; win_T *old_curwin;
win_T *new_curwin = NULL; tabpage_T *old_curtab;
tabpage_T *new_curtab = NULL;
int prev_arglist_locked = arglist_locked;
#ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
{
emsg(_(e_invalid_in_cmdline_window));
return;
}
#endif
if (ARGCOUNT <= 0)
{
// Don't give an error message. We don't want it when the ":all"
// command is in the .vimrc.
return;
}
setpcmark();
opened_len = ARGCOUNT;
opened = alloc_clear(opened_len);
if (opened == NULL)
return;
// Autocommands may do anything to the argument list. Make sure it's not
// freed while we are working here by "locking" it. We still have to
// watch out for its size to be changed.
alist = curwin->w_alist;
++alist->al_refcount;
arglist_locked = TRUE;
old_curwin = curwin; old_curwin = curwin;
old_curtab = curtab; old_curtab = curtab;
#ifdef FEAT_GUI if (aall->had_tab > 0)
need_mouse_correct = TRUE;
#endif
// Try closing all windows that are not in the argument list.
// Also close windows that are not full width;
// When 'hidden' or "forceit" set the buffer becomes hidden.
// Windows that have a changed buffer and can't be hidden won't be closed.
// When the ":tab" modifier was used do this for all tab pages.
if (had_tab > 0)
goto_tabpage_tp(first_tabpage, TRUE, TRUE); goto_tabpage_tp(first_tabpage, TRUE, TRUE);
for (;;) for (;;)
{ {
@@ -999,17 +972,17 @@ do_arg_all(
wpnext = wp->w_next; wpnext = wp->w_next;
buf = wp->w_buffer; buf = wp->w_buffer;
if (buf->b_ffname == NULL if (buf->b_ffname == NULL
|| (!keep_tabs && (buf->b_nwindows > 1 || (!aall->keep_tabs && (buf->b_nwindows > 1
|| wp->w_width != Columns))) || wp->w_width != Columns)))
i = opened_len; i = aall->opened_len;
else else
{ {
// check if the buffer in this window is in the arglist // check if the buffer in this window is in the arglist
for (i = 0; i < opened_len; ++i) for (i = 0; i < aall->opened_len; ++i)
{ {
if (i < alist->al_ga.ga_len if (i < aall->alist->al_ga.ga_len
&& (AARGLIST(alist)[i].ae_fnum == buf->b_fnum && (AARGLIST(aall->alist)[i].ae_fnum == buf->b_fnum
|| fullpathcmp(alist_name(&AARGLIST(alist)[i]), || fullpathcmp(alist_name(&AARGLIST(aall->alist)[i]),
buf->b_ffname, TRUE, TRUE) & FPC_SAME)) buf->b_ffname, TRUE, TRUE) & FPC_SAME))
{ {
int weight = 1; int weight = 1;
@@ -1021,26 +994,26 @@ do_arg_all(
++weight; ++weight;
} }
if (weight > (int)opened[i]) if (weight > (int)aall->opened[i])
{ {
opened[i] = (char_u)weight; aall->opened[i] = (char_u)weight;
if (i == 0) if (i == 0)
{ {
if (new_curwin != NULL) if (aall->new_curwin != NULL)
new_curwin->w_arg_idx = opened_len; aall->new_curwin->w_arg_idx = aall->opened_len;
new_curwin = wp; aall->new_curwin = wp;
new_curtab = curtab; aall->new_curtab = curtab;
} }
} }
else if (keep_tabs) else if (aall->keep_tabs)
i = opened_len; i = aall->opened_len;
if (wp->w_alist != alist) if (wp->w_alist != aall->alist)
{ {
// Use the current argument list for all windows // Use the current argument list for all windows
// containing a file from it. // containing a file from it.
alist_unlink(wp->w_alist); alist_unlink(wp->w_alist);
wp->w_alist = alist; wp->w_alist = aall->alist;
++wp->w_alist->al_refcount; ++wp->w_alist->al_refcount;
} }
break; break;
@@ -1049,9 +1022,9 @@ do_arg_all(
} }
wp->w_arg_idx = i; wp->w_arg_idx = i;
if (i == opened_len && !keep_tabs)// close this window if (i == aall->opened_len && !aall->keep_tabs)// close this window
{ {
if (buf_hide(buf) || forceit || buf->b_nwindows > 1 if (buf_hide(buf) || aall->forceit || buf->b_nwindows > 1
|| !bufIsChanged(buf)) || !bufIsChanged(buf))
{ {
// If the buffer was changed, and we would like to hide it, // If the buffer was changed, and we would like to hide it,
@@ -1074,8 +1047,9 @@ do_arg_all(
} }
// don't close last window // don't close last window
if (ONE_WINDOW if (ONE_WINDOW
&& (first_tabpage->tp_next == NULL || !had_tab)) && (first_tabpage->tp_next == NULL
use_firstwin = TRUE; || !aall->had_tab))
aall->use_firstwin = TRUE;
else else
{ {
win_close(wp, !buf_hide(buf) && !bufIsChanged(buf)); win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
@@ -1089,7 +1063,7 @@ do_arg_all(
} }
// Without the ":tab" modifier only do the current tab page. // Without the ":tab" modifier only do the current tab page.
if (had_tab == 0 || tpnext == NULL) if (aall->had_tab == 0 || tpnext == NULL)
break; break;
// check if autocommands removed the next tab page // check if autocommands removed the next tab page
@@ -1098,54 +1072,56 @@ do_arg_all(
goto_tabpage_tp(tpnext, TRUE, TRUE); goto_tabpage_tp(tpnext, TRUE, TRUE);
} }
}
// Open a window for files in the argument list that don't have one. /*
// ARGCOUNT may change while doing this, because of autocommands. * Open upto "count" windows for the files in the argument list 'aall->alist'.
if (count > opened_len || count <= 0) */
count = opened_len; static void
arg_all_open_windows(arg_all_state_T *aall, int count)
{
win_T *wp;
int tab_drop_empty_window = FALSE;
int i;
int split_ret = OK;
int p_ea_save;
// Don't execute Win/Buf Enter/Leave autocommands here.
++autocmd_no_enter;
++autocmd_no_leave;
last_curwin = curwin;
last_curtab = curtab;
win_enter(lastwin, FALSE);
// ":tab drop file" should re-use an empty window to avoid "--remote-tab" // ":tab drop file" should re-use an empty window to avoid "--remote-tab"
// leaving an empty tab page when executed locally. // leaving an empty tab page when executed locally.
if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1 if (aall->keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
&& curbuf->b_ffname == NULL && !curbuf->b_changed) && curbuf->b_ffname == NULL && !curbuf->b_changed)
{ {
use_firstwin = TRUE; aall->use_firstwin = TRUE;
tab_drop_empty_window = TRUE; tab_drop_empty_window = TRUE;
} }
for (i = 0; i < count && !got_int; ++i) for (i = 0; i < count && !got_int; ++i)
{ {
if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) if (aall->alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
arg_had_last = TRUE; arg_had_last = TRUE;
if (opened[i] > 0) if (aall->opened[i] > 0)
{ {
// Move the already present window to below the current window // Move the already present window to below the current window
if (curwin->w_arg_idx != i) if (curwin->w_arg_idx != i)
{ {
FOR_ALL_WINDOWS(wpnext) FOR_ALL_WINDOWS(wp)
{ {
if (wpnext->w_arg_idx == i) if (wp->w_arg_idx == i)
{ {
if (keep_tabs) if (aall->keep_tabs)
{ {
new_curwin = wpnext; aall->new_curwin = wp;
new_curtab = curtab; aall->new_curtab = curtab;
} }
else if (wpnext->w_frame->fr_parent else if (wp->w_frame->fr_parent
!= curwin->w_frame->fr_parent) != curwin->w_frame->fr_parent)
{ {
emsg(_(e_window_layout_changed_unexpectedly)); emsg(_(e_window_layout_changed_unexpectedly));
i = count; i = count;
break; break;
} }
else else
win_move_after(wpnext, curwin); win_move_after(wp, curwin);
break; break;
} }
} }
@@ -1156,7 +1132,7 @@ do_arg_all(
// trigger events for tab drop // trigger events for tab drop
if (tab_drop_empty_window && i == count - 1) if (tab_drop_empty_window && i == count - 1)
--autocmd_no_enter; --autocmd_no_enter;
if (!use_firstwin) // split current window if (!aall->use_firstwin) // split current window
{ {
p_ea_save = p_ea; p_ea_save = p_ea;
p_ea = TRUE; // use space from all windows p_ea = TRUE; // use space from all windows
@@ -1172,35 +1148,111 @@ do_arg_all(
curwin->w_arg_idx = i; curwin->w_arg_idx = i;
if (i == 0) if (i == 0)
{ {
new_curwin = curwin; aall->new_curwin = curwin;
new_curtab = curtab; aall->new_curtab = curtab;
} }
(void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL, (void)do_ecmd(0, alist_name(&AARGLIST(aall->alist)[i]), NULL, NULL,
ECMD_ONE, ECMD_ONE,
((buf_hide(curwin->w_buffer) ((buf_hide(curwin->w_buffer)
|| bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0) || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
+ ECMD_OLDBUF, curwin); + ECMD_OLDBUF, curwin);
if (tab_drop_empty_window && i == count - 1) if (tab_drop_empty_window && i == count - 1)
++autocmd_no_enter; ++autocmd_no_enter;
if (use_firstwin) if (aall->use_firstwin)
++autocmd_no_leave; ++autocmd_no_leave;
use_firstwin = FALSE; aall->use_firstwin = FALSE;
} }
ui_breakcheck(); ui_breakcheck();
// When ":tab" was used open a new tab for a new window repeatedly. // When ":tab" was used open a new tab for a new window repeatedly.
if (had_tab > 0 && tabpage_index(NULL) <= p_tpm) if (aall->had_tab > 0 && tabpage_index(NULL) <= p_tpm)
cmdmod.cmod_tab = 9999; cmdmod.cmod_tab = 9999;
} }
}
/*
* do_arg_all(): Open up to "count" windows, one for each argument.
*/
static void
do_arg_all(
int count,
int forceit, // hide buffers in current windows
int keep_tabs) // keep current tabs, for ":tab drop file"
{
arg_all_state_T aall;
win_T *last_curwin;
tabpage_T *last_curtab;
int prev_arglist_locked = arglist_locked;
#ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
{
emsg(_(e_invalid_in_cmdline_window));
return;
}
#endif
if (ARGCOUNT <= 0)
{
// Don't give an error message. We don't want it when the ":all"
// command is in the .vimrc.
return;
}
setpcmark();
aall.use_firstwin = FALSE;
aall.had_tab = cmdmod.cmod_tab;
aall.new_curwin = NULL;
aall.new_curtab = NULL;
aall.forceit = forceit;
aall.keep_tabs = keep_tabs;
aall.opened_len = ARGCOUNT;
aall.opened = alloc_clear(aall.opened_len);
if (aall.opened == NULL)
return;
// Autocommands may do anything to the argument list. Make sure it's not
// freed while we are working here by "locking" it. We still have to
// watch out for its size being changed.
aall.alist = curwin->w_alist;
++aall.alist->al_refcount;
arglist_locked = TRUE;
#ifdef FEAT_GUI
need_mouse_correct = TRUE;
#endif
// Try closing all windows that are not in the argument list.
// Also close windows that are not full width;
// When 'hidden' or "forceit" set the buffer becomes hidden.
// Windows that have a changed buffer and can't be hidden won't be closed.
// When the ":tab" modifier was used do this for all tab pages.
arg_all_close_unused_windows(&aall);
// Open a window for files in the argument list that don't have one.
// ARGCOUNT may change while doing this, because of autocommands.
if (count > aall.opened_len || count <= 0)
count = aall.opened_len;
// Don't execute Win/Buf Enter/Leave autocommands here.
++autocmd_no_enter;
++autocmd_no_leave;
last_curwin = curwin;
last_curtab = curtab;
win_enter(lastwin, FALSE);
/*
* Open upto "count" windows.
*/
arg_all_open_windows(&aall, count);
// Remove the "lock" on the argument list. // Remove the "lock" on the argument list.
alist_unlink(alist); alist_unlink(aall.alist);
arglist_locked = prev_arglist_locked; arglist_locked = prev_arglist_locked;
--autocmd_no_enter; --autocmd_no_enter;
// restore last referenced tabpage's curwin // restore last referenced tabpage's curwin
if (last_curtab != new_curtab) if (last_curtab != aall.new_curtab)
{ {
if (valid_tabpage(last_curtab)) if (valid_tabpage(last_curtab))
goto_tabpage_tp(last_curtab, TRUE, TRUE); goto_tabpage_tp(last_curtab, TRUE, TRUE);
@@ -1208,13 +1260,13 @@ do_arg_all(
win_enter(last_curwin, FALSE); win_enter(last_curwin, FALSE);
} }
// to window with first arg // to window with first arg
if (valid_tabpage(new_curtab)) if (valid_tabpage(aall.new_curtab))
goto_tabpage_tp(new_curtab, TRUE, TRUE); goto_tabpage_tp(aall.new_curtab, TRUE, TRUE);
if (win_valid(new_curwin)) if (win_valid(aall.new_curwin))
win_enter(new_curwin, FALSE); win_enter(aall.new_curwin, FALSE);
--autocmd_no_leave; --autocmd_no_leave;
vim_free(opened); vim_free(aall.opened);
} }
/* /*

View File

@@ -703,6 +703,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 */
/**/
388,
/**/ /**/
387, 387,
/**/ /**/