Merge pull request #14164 from andymass/vim-8.1.2020

[RFC] vim-patch 8.{1.2020,2.0093,2.0422}: add win_splitmove()
This commit is contained in:
Jan Edmund Lazo 2021-03-20 15:59:53 -04:00 committed by GitHub
commit 049213b419
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 169 additions and 0 deletions

View File

@ -2498,6 +2498,8 @@ win_gotoid({expr}) Number go to |window-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}
@ -9370,6 +9372,25 @@ win_screenpos({nr}) *win_screenpos()*
Return [0, 0] if the window cannot be found in the current
tabpage.
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.
*winbufnr()*
winbufnr({nr}) The result is a Number, which is the number of the buffer
associated with window {nr}. {nr} can be the window number or

View File

@ -392,6 +392,7 @@ return {
win_id2tabwin={args=1},
win_id2win={args=1},
win_screenpos={args=1},
win_splitmove={args={2, 3}},
winbufnr={args=1},
wincol={},
windowsversion={},

View File

@ -3980,6 +3980,87 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
tv_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 (oldwin != curwin) {
win_goto(oldwin);
}
}
// "win_splitmove()" function
static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
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
|| !win_valid(wp) || !win_valid(targetwin)
|| win_valid_floating(wp) || win_valid_floating(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 (tv_dict_get_number(d, "vertical")) {
flags |= WSP_VERT;
}
if ((di = tv_dict_find(d, "rightbelow", -1)) != NULL) {
flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE;
}
size = tv_dict_get_number(d, "size");
}
win_move_into_split(wp, targetwin, size, flags);
}
// "getwinpos({timeout})" function
static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{

View File

@ -808,6 +808,55 @@ func Test_winnr()
only | tabonly
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:')
tabnew
call assert_fails('call win_splitmove(1, win_getid(1, 1))', 'E957:')
tabclose
endfunc
func Test_floatwin_splitmove()
vsplit
let win2 = win_getid()
let popup_winid = nvim_open_win(0, 0, {'relative': 'win',
\ 'row': 3, 'col': 3, 'width': 12, 'height': 3})
call assert_fails('call win_splitmove(popup_winid, win2)', 'E957:')
call assert_fails('call win_splitmove(win2, popup_winid)', 'E957:')
call nvim_win_close(popup_winid, 1)
bwipe
endfunc
func Test_window_resize()
" Vertical :resize (absolute, relative, min and max size).
vsplit

View File

@ -1619,6 +1619,23 @@ static void win_init_some(win_T *newp, win_T *oldp)
win_copy_options(oldp, newp);
}
/// Return TRUE if "win" is floating window in the current tab page.
///
/// @param win window to check
bool win_valid_floating(const win_T *win)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win == NULL) {
return false;
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp == win) {
return wp->w_floating;
}
}
return false;
}
/// Check if "win" is a pointer to an existing window in the current tabpage.
///