0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.1.2020: it is not easy to change the window layout

Problem:    It is not easy to change the window layout.
Solution:   Add win_splitmove(). (Andy Massimino, closes #4561)
This commit is contained in:
Bram Moolenaar 2019-09-10 21:22:58 +02:00
parent 410e98a70b
commit d20dcb3d01
6 changed files with 147 additions and 0 deletions

View File

@ -2875,6 +2875,8 @@ win_gotoid({expr}) Number go to window with ID {expr}
win_id2tabwin({expr}) List get tab and window nr from window ID
win_id2win({expr}) Number get window nr from window ID
win_screenpos({nr}) List get screen position of window {nr}
win_splitmove({nr}, {target} [, {options}])
none move window {nr} to split of {target}
winbufnr({nr}) Number buffer number of window {nr}
wincol() Number window column of the cursor
winheight({nr}) Number height of window {nr}
@ -10143,6 +10145,28 @@ win_screenpos({nr}) *win_screenpos()*
Can also be used as a |method|: >
GetWinid()->win_screenpos()
<
win_splitmove({nr}, {target} [, {options}]) *win_splitmove()*
Move the window {nr} to a new split of the window {target}.
This is similar to moving to {target}, creating a new window
using |:split| but having the same contents as window {nr}, and
then closing {nr}.
Both {nr} and {target} can be window numbers or |window-ID|s.
Returns zero for success, non-zero for failure.
{options} is a Dictionary with the following optional entries:
"vertical" When TRUE, the split is created vertically,
like with |:vsplit|.
"rightbelow" When TRUE, the split is made below or to the
right (if vertical). When FALSE, it is done
above or to the left (if vertical). When not
present, the values of 'splitbelow' and
'splitright' are used.
Can also be used as a |method|: >
GetWinid()->win_splitmove(target)
<
*winbufnr()*
winbufnr({nr}) The result is a Number, which is the number of the buffer

View File

@ -850,6 +850,7 @@ static funcentry_T global_functions[] =
{"win_id2tabwin", 1, 1, FEARG_1, f_win_id2tabwin},
{"win_id2win", 1, 1, FEARG_1, f_win_id2win},
{"win_screenpos", 1, 1, FEARG_1, f_win_screenpos},
{"win_splitmove", 2, 3, FEARG_1, f_win_splitmove},
{"winbufnr", 1, 1, FEARG_1, f_winbufnr},
{"wincol", 0, 0, 0, f_wincol},
{"winheight", 1, 1, FEARG_1, f_winheight},

View File

@ -743,6 +743,92 @@ f_win_screenpos(typval_T *argvars, typval_T *rettv)
list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1);
}
/*
* Move the window wp into a new split of targetwin in a given direction
*/
static void
win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags)
{
int dir;
int height = wp->w_height;
win_T *oldwin = curwin;
if (wp == targetwin)
return;
// Jump to the target window
if (curwin != targetwin)
win_goto(targetwin);
// Remove the old window and frame from the tree of frames
(void)winframe_remove(wp, &dir, NULL);
win_remove(wp, NULL);
last_status(FALSE); // may need to remove last status line
(void)win_comp_pos(); // recompute window positions
// Split a window on the desired side and put the old window there
(void)win_split_ins(size, flags, wp, dir);
// If splitting horizontally, try to preserve height
if (size == 0 && !(flags & WSP_VERT))
{
win_setheight_win(height, wp);
if (p_ea)
win_equal(wp, TRUE, 'v');
}
#if defined(FEAT_GUI)
// When 'guioptions' includes 'L' or 'R' may have to remove or add
// scrollbars. Have to update them anyway.
gui_may_update_scrollbars();
#endif
if (oldwin != curwin)
win_goto(oldwin);
}
/*
* "win_splitmove()" function
*/
void
f_win_splitmove(typval_T *argvars, typval_T *rettv)
{
win_T *wp;
win_T *targetwin;
int flags = 0, size = 0;
wp = find_win_by_nr_or_id(&argvars[0]);
targetwin = find_win_by_nr_or_id(&argvars[1]);
if (wp == NULL || targetwin == NULL || wp == targetwin)
{
emsg(_(e_invalwindow));
rettv->vval.v_number = -1;
return;
}
if (argvars[2].v_type != VAR_UNKNOWN)
{
dict_T *d;
dictitem_T *di;
if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL)
{
emsg(_(e_invarg));
return;
}
d = argvars[2].vval.v_dict;
if (dict_get_number(d, (char_u *)"vertical"))
flags |= WSP_VERT;
if ((di = dict_find(d, (char_u *)"rightbelow", -1)) != NULL)
flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
size = (int)dict_get_number(d, (char_u *)"size");
}
win_move_into_split(wp, targetwin, size, flags);
}
/*
* "winbufnr(nr)" function
*/

View File

@ -19,6 +19,7 @@ void f_win_gotoid(typval_T *argvars, typval_T *rettv);
void f_win_id2tabwin(typval_T *argvars, typval_T *rettv);
void f_win_id2win(typval_T *argvars, typval_T *rettv);
void f_win_screenpos(typval_T *argvars, typval_T *rettv);
void f_win_splitmove(typval_T *argvars, typval_T *rettv);
void f_winbufnr(typval_T *argvars, typval_T *rettv);
void f_wincol(typval_T *argvars, typval_T *rettv);
void f_winheight(typval_T *argvars, typval_T *rettv);

View File

@ -857,4 +857,37 @@ func Test_winrestview()
bwipe!
endfunc
func Test_win_splitmove()
edit a
leftabove split b
leftabove vsplit c
leftabove split d
call assert_equal(0, win_splitmove(winnr(), winnr('l')))
call assert_equal(bufname(winbufnr(1)), 'c')
call assert_equal(bufname(winbufnr(2)), 'd')
call assert_equal(bufname(winbufnr(3)), 'b')
call assert_equal(bufname(winbufnr(4)), 'a')
call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'vertical': 1}))
call assert_equal(bufname(winbufnr(1)), 'c')
call assert_equal(bufname(winbufnr(2)), 'b')
call assert_equal(bufname(winbufnr(3)), 'd')
call assert_equal(bufname(winbufnr(4)), 'a')
call assert_equal(0, win_splitmove(winnr(), winnr('k'), {'vertical': 1}))
call assert_equal(bufname(winbufnr(1)), 'd')
call assert_equal(bufname(winbufnr(2)), 'c')
call assert_equal(bufname(winbufnr(3)), 'b')
call assert_equal(bufname(winbufnr(4)), 'a')
call assert_equal(0, win_splitmove(winnr(), winnr('j'), {'rightbelow': v:true}))
call assert_equal(bufname(winbufnr(1)), 'c')
call assert_equal(bufname(winbufnr(2)), 'b')
call assert_equal(bufname(winbufnr(3)), 'a')
call assert_equal(bufname(winbufnr(4)), 'd')
only | bd
call assert_fails('call win_splitmove(winnr(), 123)', 'E957:')
call assert_fails('call win_splitmove(123, winnr())', 'E957:')
call assert_fails('call win_splitmove(winnr(), winnr())', 'E957:')
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

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