Patch 9.0.0388

2 views
Skip to first unread message

Bram Moolenaar

unread,
Sep 5, 2022, 1:28:38 PM9/5/22
to vim...@googlegroups.com

Patch 9.0.0388
Problem: The do_arg_all() function is too long.
Solution: Split the function in smaller parts. (Yegappan Lakshmanan,
closes #11062)
Files: src/arglist.c


*** ../vim-9.0.0387/src/arglist.c 2022-09-05 14:33:42.202419990 +0100
--- src/arglist.c 2022-09-05 18:24:52.327375787 +0100
***************
*** 574,594 ****
alist_new();
}

if (*eap->arg != NUL)
{
if (check_arglist_locked() == FAIL)
return;
- // ":args file ..": define new argument list, handle like ":next"
- // Also for ":argslocal file .." and ":argsglobal file ..".
ex_next(eap);
}
! else if (eap->cmdidx == CMD_args)
{
char_u **items;

- // ":args": list arguments.
if (ARGCOUNT <= 0)
! return;

items = ALLOC_MULT(char_u *, ARGCOUNT);
if (items == NULL)
--- 574,596 ----
alist_new();
}

+ // ":args file ..": define new argument list, handle like ":next"
+ // Also for ":argslocal file .." and ":argsglobal file ..".
if (*eap->arg != NUL)
{
if (check_arglist_locked() == FAIL)
return;
ex_next(eap);
+ return;
}
!
! // ":args": list arguments.
! if (eap->cmdidx == CMD_args)
{
char_u **items;

if (ARGCOUNT <= 0)
! return; // empty argument list

items = ALLOC_MULT(char_u *, ARGCOUNT);
if (items == NULL)
***************
*** 602,613 ****
items[i] = alist_name(&ARGLIST[i]);
list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
vim_free(items);
}
! else if (eap->cmdidx == CMD_arglocal)
{
garray_T *gap = &curwin->w_alist->al_ga;

- // ":argslocal": make a local copy of the global argument list.
if (GA_GROW_FAILS(gap, GARGCOUNT))
return;

--- 604,618 ----
items[i] = alist_name(&ARGLIST[i]);
list_in_columns(items, ARGCOUNT, curwin->w_arg_idx);
vim_free(items);
+
+ return;
}
!
! // ":argslocal": make a local copy of the global argument list.
! if (eap->cmdidx == CMD_arglocal)
{
garray_T *gap = &curwin->w_alist->al_ga;

if (GA_GROW_FAILS(gap, GARGCOUNT))
return;

***************
*** 919,995 ****
}

/*
! * 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"
! {
! int i;
! win_T *wp, *wpnext;
char_u *opened; // Array of weight for which args are open:
// 0: not opened
// 1: opened in other tab
// 2: opened in curtab
// 3: opened in curtab and curwin
- //
int opened_len; // length of opened[]
! int use_firstwin = FALSE; // use first window for arglist
! int tab_drop_empty_window = FALSE;
! int split_ret = OK;
! int p_ea_save;
! alist_T *alist; // argument list to be used
! buf_T *buf;
! tabpage_T *tpnext;
! int had_tab = cmdmod.cmod_tab;
! win_T *old_curwin, *last_curwin;
! tabpage_T *old_curtab, *last_curtab;
! win_T *new_curwin = NULL;
! 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_curtab = curtab;

! #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.
! if (had_tab > 0)
goto_tabpage_tp(first_tabpage, TRUE, TRUE);
for (;;)
{
--- 924,968 ----
}

/*
! * State used by the :all command to open all the files in the argument list in
! * separate windows.
*/
! typedef struct {
! alist_T *alist; // argument list to be used
! int had_tab;
! int keep_tabs;
! int forceit;
!
! int use_firstwin; // use first window for arglist
char_u *opened; // Array of weight for which args are open:
// 0: not opened
// 1: opened in other tab
// 2: opened in curtab
// 3: opened in curtab and curwin
int opened_len; // length of opened[]
! win_T *new_curwin;
! tabpage_T *new_curtab;
! } arg_all_state_T;

! /*
! * 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;
! buf_T *buf;
! int i;
! win_T *old_curwin;
! tabpage_T *old_curtab;

old_curwin = curwin;
old_curtab = curtab;

! if (aall->had_tab > 0)
goto_tabpage_tp(first_tabpage, TRUE, TRUE);
for (;;)
{
***************
*** 999,1015 ****
wpnext = wp->w_next;
buf = wp->w_buffer;
if (buf->b_ffname == NULL
! || (!keep_tabs && (buf->b_nwindows > 1
|| wp->w_width != Columns)))
! i = opened_len;
else
{
// check if the buffer in this window is in the arglist
! for (i = 0; i < opened_len; ++i)
{
! if (i < alist->al_ga.ga_len
! && (AARGLIST(alist)[i].ae_fnum == buf->b_fnum
! || fullpathcmp(alist_name(&AARGLIST(alist)[i]),
buf->b_ffname, TRUE, TRUE) & FPC_SAME))
{
int weight = 1;
--- 972,988 ----
wpnext = wp->w_next;
buf = wp->w_buffer;
if (buf->b_ffname == NULL
! || (!aall->keep_tabs && (buf->b_nwindows > 1
|| wp->w_width != Columns)))
! i = aall->opened_len;
else
{
// check if the buffer in this window is in the arglist
! for (i = 0; i < aall->opened_len; ++i)
{
! if (i < aall->alist->al_ga.ga_len
! && (AARGLIST(aall->alist)[i].ae_fnum == buf->b_fnum
! || fullpathcmp(alist_name(&AARGLIST(aall->alist)[i]),
buf->b_ffname, TRUE, TRUE) & FPC_SAME))
{
int weight = 1;
***************
*** 1021,1046 ****
++weight;
}

! if (weight > (int)opened[i])
{
! opened[i] = (char_u)weight;
if (i == 0)
{
! if (new_curwin != NULL)
! new_curwin->w_arg_idx = opened_len;
! new_curwin = wp;
! new_curtab = curtab;
}
}
! else if (keep_tabs)
! i = opened_len;

! if (wp->w_alist != alist)
{
// Use the current argument list for all windows
// containing a file from it.
alist_unlink(wp->w_alist);
! wp->w_alist = alist;
++wp->w_alist->al_refcount;
}
break;
--- 994,1019 ----
++weight;
}

! if (weight > (int)aall->opened[i])
{
! aall->opened[i] = (char_u)weight;
if (i == 0)
{
! if (aall->new_curwin != NULL)
! aall->new_curwin->w_arg_idx = aall->opened_len;
! aall->new_curwin = wp;
! aall->new_curtab = curtab;
}
}
! else if (aall->keep_tabs)
! i = aall->opened_len;

! if (wp->w_alist != aall->alist)
{
// Use the current argument list for all windows
// containing a file from it.
alist_unlink(wp->w_alist);
! wp->w_alist = aall->alist;
++wp->w_alist->al_refcount;
}
break;
***************
*** 1049,1057 ****
}
wp->w_arg_idx = i;

! if (i == opened_len && !keep_tabs)// close this window
{
! if (buf_hide(buf) || forceit || buf->b_nwindows > 1
|| !bufIsChanged(buf))
{
// If the buffer was changed, and we would like to hide it,
--- 1022,1030 ----
}
wp->w_arg_idx = i;

! if (i == aall->opened_len && !aall->keep_tabs)// close this window
{
! if (buf_hide(buf) || aall->forceit || buf->b_nwindows > 1
|| !bufIsChanged(buf))
{
// If the buffer was changed, and we would like to hide it,
***************
*** 1074,1081 ****
}
// don't close last window
if (ONE_WINDOW
! && (first_tabpage->tp_next == NULL || !had_tab))
! use_firstwin = TRUE;
else
{
win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
--- 1047,1055 ----
}
// don't close last window
if (ONE_WINDOW
! && (first_tabpage->tp_next == NULL
! || !aall->had_tab))
! aall->use_firstwin = TRUE;
else
{
win_close(wp, !buf_hide(buf) && !bufIsChanged(buf));
***************
*** 1089,1095 ****
}

// Without the ":tab" modifier only do the current tab page.
! if (had_tab == 0 || tpnext == NULL)
break;

// check if autocommands removed the next tab page
--- 1063,1069 ----
}

// Without the ":tab" modifier only do the current tab page.
! if (aall->had_tab == 0 || tpnext == NULL)
break;

// check if autocommands removed the next tab page
***************
*** 1098,1151 ****

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.
! if (count > opened_len || count <= 0)
! count = 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);
// ":tab drop file" should re-use an empty window to avoid "--remote-tab"
// leaving an empty tab page when executed locally.
! if (keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
&& curbuf->b_ffname == NULL && !curbuf->b_changed)
{
! use_firstwin = TRUE;
tab_drop_empty_window = TRUE;
}

for (i = 0; i < count && !got_int; ++i)
{
! if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
arg_had_last = TRUE;
! if (opened[i] > 0)
{
// Move the already present window to below the current window
if (curwin->w_arg_idx != i)
{
! FOR_ALL_WINDOWS(wpnext)
{
! if (wpnext->w_arg_idx == i)
{
! if (keep_tabs)
{
! new_curwin = wpnext;
! new_curtab = curtab;
}
! else if (wpnext->w_frame->fr_parent
! != curwin->w_frame->fr_parent)
{
emsg(_(e_window_layout_changed_unexpectedly));
i = count;
break;
}
else
! win_move_after(wpnext, curwin);
break;
}
}
--- 1072,1127 ----

goto_tabpage_tp(tpnext, TRUE, TRUE);
}
+ }

! /*
! * Open upto "count" windows for the files in the argument list 'aall->alist'.
! */
! 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;

// ":tab drop file" should re-use an empty window to avoid "--remote-tab"
// leaving an empty tab page when executed locally.
! if (aall->keep_tabs && BUFEMPTY() && curbuf->b_nwindows == 1
&& curbuf->b_ffname == NULL && !curbuf->b_changed)
{
! aall->use_firstwin = TRUE;
tab_drop_empty_window = TRUE;
}

for (i = 0; i < count && !got_int; ++i)
{
! if (aall->alist == &global_alist && i == global_alist.al_ga.ga_len - 1)
arg_had_last = TRUE;
! if (aall->opened[i] > 0)
{
// Move the already present window to below the current window
if (curwin->w_arg_idx != i)
{
! FOR_ALL_WINDOWS(wp)
{
! if (wp->w_arg_idx == i)
{
! if (aall->keep_tabs)
{
! aall->new_curwin = wp;
! aall->new_curtab = curtab;
}
! else if (wp->w_frame->fr_parent
! != curwin->w_frame->fr_parent)
{
emsg(_(e_window_layout_changed_unexpectedly));
i = count;
break;
}
else
! win_move_after(wp, curwin);
break;
}
}
***************
*** 1156,1162 ****
// trigger events for tab drop
if (tab_drop_empty_window && i == count - 1)
--autocmd_no_enter;
! if (!use_firstwin) // split current window
{
p_ea_save = p_ea;
p_ea = TRUE; // use space from all windows
--- 1132,1138 ----
// trigger events for tab drop
if (tab_drop_empty_window && i == count - 1)
--autocmd_no_enter;
! if (!aall->use_firstwin) // split current window
{
p_ea_save = p_ea;
p_ea = TRUE; // use space from all windows
***************
*** 1172,1206 ****
curwin->w_arg_idx = i;
if (i == 0)
{
! new_curwin = curwin;
! new_curtab = curtab;
}
! (void)do_ecmd(0, alist_name(&AARGLIST(alist)[i]), NULL, NULL,
! ECMD_ONE,
! ((buf_hide(curwin->w_buffer)
! || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
! + ECMD_OLDBUF, curwin);
if (tab_drop_empty_window && i == count - 1)
++autocmd_no_enter;
! if (use_firstwin)
++autocmd_no_leave;
! use_firstwin = FALSE;
}
ui_breakcheck();

// When ":tab" was used open a new tab for a new window repeatedly.
! if (had_tab > 0 && tabpage_index(NULL) <= p_tpm)
cmdmod.cmod_tab = 9999;
}

// Remove the "lock" on the argument list.
! alist_unlink(alist);
arglist_locked = prev_arglist_locked;

--autocmd_no_enter;

// restore last referenced tabpage's curwin
! if (last_curtab != new_curtab)
{
if (valid_tabpage(last_curtab))
goto_tabpage_tp(last_curtab, TRUE, TRUE);
--- 1148,1258 ----
curwin->w_arg_idx = i;
if (i == 0)
{
! aall->new_curwin = curwin;
! aall->new_curtab = curtab;
}
! (void)do_ecmd(0, alist_name(&AARGLIST(aall->alist)[i]), NULL, NULL,
! ECMD_ONE,
! ((buf_hide(curwin->w_buffer)
! || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0)
! + ECMD_OLDBUF, curwin);
if (tab_drop_empty_window && i == count - 1)
++autocmd_no_enter;
! if (aall->use_firstwin)
++autocmd_no_leave;
! aall->use_firstwin = FALSE;
}
ui_breakcheck();

// When ":tab" was used open a new tab for a new window repeatedly.
! if (aall->had_tab > 0 && tabpage_index(NULL) <= p_tpm)
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.
! alist_unlink(aall.alist);
arglist_locked = prev_arglist_locked;

--autocmd_no_enter;

// restore last referenced tabpage's curwin
! if (last_curtab != aall.new_curtab)
{
if (valid_tabpage(last_curtab))
goto_tabpage_tp(last_curtab, TRUE, TRUE);
***************
*** 1208,1220 ****
win_enter(last_curwin, FALSE);
}
// to window with first arg
! if (valid_tabpage(new_curtab))
! goto_tabpage_tp(new_curtab, TRUE, TRUE);
! if (win_valid(new_curwin))
! win_enter(new_curwin, FALSE);

--autocmd_no_leave;
! vim_free(opened);
}

/*
--- 1260,1272 ----
win_enter(last_curwin, FALSE);
}
// to window with first arg
! if (valid_tabpage(aall.new_curtab))
! goto_tabpage_tp(aall.new_curtab, TRUE, TRUE);
! if (win_valid(aall.new_curwin))
! win_enter(aall.new_curwin, FALSE);

--autocmd_no_leave;
! vim_free(aall.opened);
}

/*
*** ../vim-9.0.0387/src/version.c 2022-09-05 16:53:17.115566769 +0100
--- src/version.c 2022-09-05 18:16:41.403970414 +0100
***************
*** 705,706 ****
--- 705,708 ----
{ /* Add new patch number below this line */
+ /**/
+ 388,
/**/

--
hundred-and-one symptoms of being an internet addict:
7. You finally do take that vacation, but only after buying a USB modem
and a laptop.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages