diff options
author | Bram Moolenaar <Bram@vim.org> | 2019-09-10 21:22:58 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2019-09-10 21:22:58 +0200 |
commit | d20dcb3d011da6111153109f6e46fbd5c7fe9fb6 (patch) | |
tree | 177b708d63b5bdace192c344b5a431298a575df2 /src | |
parent | 410e98a70bc00ea4bed51e55a8fe20e56a72c087 (diff) | |
download | vim-git-d20dcb3d011da6111153109f6e46fbd5c7fe9fb6.tar.gz |
patch 8.1.2020: it is not easy to change the window layoutv8.1.2020
Problem: It is not easy to change the window layout.
Solution: Add win_splitmove(). (Andy Massimino, closes #4561)
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 1 | ||||
-rw-r--r-- | src/evalwindow.c | 86 | ||||
-rw-r--r-- | src/proto/evalwindow.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_window_cmd.vim | 33 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 123 insertions, 0 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index dafd3b6af..438aac8ea 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -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}, diff --git a/src/evalwindow.c b/src/evalwindow.c index 351492c0b..08bdb9559 100644 --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -744,6 +744,92 @@ f_win_screenpos(typval_T *argvars, typval_T *rettv) } /* + * 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 */ void diff --git a/src/proto/evalwindow.pro b/src/proto/evalwindow.pro index c201a2e2d..e3faa96eb 100644 --- a/src/proto/evalwindow.pro +++ b/src/proto/evalwindow.pro @@ -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); diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 9bdae2c68..ffe8f431d 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -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 diff --git a/src/version.c b/src/version.c index afbf0bcee..44b6a5183 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2020, +/**/ 2019, /**/ 2018, |