# HG changeset patch # User Bram Moolenaar # Date 1641822303 -3600 # Node ID b94cdb5ef20ec215052c3cfc5da4449237f3834d # Parent ffff3ab24c59d8cb0d8627da83202c8fa290bccb patch 8.2.4052: not easy to resize a window from a plugin Commit: https://github.com/vim/vim/commit/ee63031b572eb7aea27be4c7e3dafba0daaf681b Author: Daniel Steinberg Date: Mon Jan 10 13:36:34 2022 +0000 patch 8.2.4052: not easy to resize a window from a plugin Problem: Not easy to resize a window from a plugin. Solution: Add win_move_separator() and win_move_statusline() functions. (Daniel Steinberg, closes #9486) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -695,6 +695,8 @@ win_gettype([{nr}]) String type of wind 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_move_separator({nr}) Number move window vertical separator +win_move_statusline({nr}) Number move window status line win_screenpos({nr}) List get screen position of window {nr} win_splitmove({nr}, {target} [, {options}]) Number move window {nr} to split of {target} @@ -9567,6 +9569,35 @@ win_id2win({expr}) *win_id2win()* Can also be used as a |method|: > GetWinid()->win_id2win() +win_move_separator({nr}, {offset}) *win_move_separator()* + Move window {nr}'s vertical separator (i.e., the right border) + by {offset} columns, as if being dragged by the mouse. {nr} + can be a window number or |window-ID|. A positive {offset} + moves right and a negative {offset} moves left. Moving a + window's vertical separator will change the width of the + window and the width of other windows adjacent to the vertical + separator. The magnitude of movement may be smaller than + specified (e.g., as a consequence of maintaining + 'winminwidth'). Returns TRUE if the window can be found and + FALSE otherwise. + + Can also be used as a |method|: > + GetWinnr()->win_move_separator(offset) + +win_move_statusline({nr}, {offset}) *win_move_statusline()* + Move window {nr}'s status line (i.e., the bottom border) by + {offset} rows, as if being dragged by the mouse. {nr} can be a + window number or |window-ID|. A positive {offset} moves down + and a negative {offset} moves up. Moving a window's status + line will change the height of the window and the height of + other windows adjacent to the status line. The magnitude of + movement may be smaller than specified (e.g., as a consequence + of maintaining 'winminheight'). Returns TRUE if the window can + be found and FALSE otherwise. + + Can also be used as a |method|: > + GetWinnr()->win_move_statusline(offset) + win_screenpos({nr}) *win_screenpos()* Return the screen position of window {nr} as a list with two numbers: [row, col]. The first window always has position diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt --- a/runtime/doc/usr_41.txt +++ b/runtime/doc/usr_41.txt @@ -963,6 +963,8 @@ Buffers, windows and the argument list: win_gotoid() go to window with ID win_id2tabwin() get tab and window nr from window ID win_id2win() get window nr from window ID + win_move_separator() move window vertical separator + win_move_statusline() move window status line win_splitmove() move window to a split of another window getbufinfo() get a list with buffer information gettabinfo() get a list with tab page information diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2398,6 +2398,10 @@ static funcentry_T global_functions[] = ret_list_number, f_win_id2tabwin}, {"win_id2win", 1, 1, FEARG_1, arg1_number, ret_number, f_win_id2win}, + {"win_move_separator", 2, 2, FEARG_1, arg2_number, + ret_number_bool, f_win_move_separator}, + {"win_move_statusline", 2, 2, FEARG_1, arg2_number, + ret_number_bool, f_win_move_statusline}, {"win_screenpos", 1, 1, FEARG_1, arg1_number, ret_list_number, f_win_screenpos}, {"win_splitmove", 2, 3, FEARG_1, arg3_number_number_dict, diff --git a/src/evalwindow.c b/src/evalwindow.c --- a/src/evalwindow.c +++ b/src/evalwindow.c @@ -836,6 +836,56 @@ f_win_id2win(typval_T *argvars, typval_T } /* + * "win_move_separator()" function + */ + void +f_win_move_separator(typval_T *argvars, typval_T *rettv) +{ + win_T *wp; + int offset; + + rettv->vval.v_number = FALSE; + + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_number_arg(argvars, 1) == FAIL)) + return; + + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL || win_valid_popup(wp)) + return; + + offset = (int)tv_get_number(&argvars[1]); + win_drag_vsep_line(wp, offset); + rettv->vval.v_number = TRUE; +} + +/* + * "win_move_statusline()" function + */ + void +f_win_move_statusline(typval_T *argvars, typval_T *rettv) +{ + win_T *wp; + int offset; + + rettv->vval.v_number = FALSE; + + if (in_vim9script() + && (check_for_number_arg(argvars, 0) == FAIL + || check_for_number_arg(argvars, 1) == FAIL)) + return; + + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL || win_valid_popup(wp)) + return; + + offset = (int)tv_get_number(&argvars[1]); + win_drag_status_line(wp, offset); + rettv->vval.v_number = TRUE; +} + +/* * "win_screenpos()" function */ void diff --git a/src/proto/evalwindow.pro b/src/proto/evalwindow.pro --- a/src/proto/evalwindow.pro +++ b/src/proto/evalwindow.pro @@ -18,6 +18,8 @@ void f_win_getid(typval_T *argvars, typv 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_move_separator(typval_T *argvars, typval_T *rettv); +void f_win_move_statusline(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_win_gettype(typval_T *argvars, typval_T *rettv); diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -1395,5 +1395,103 @@ func Test_window_minimal_size() set winminwidth& winminheight& endfunc +func Test_win_move_separator() + edit a + leftabove vsplit b + let w = winwidth(0) + " check win_move_separator from left window on left window + call assert_equal(1, winnr()) + for offset in range(5) + call assert_true(win_move_separator(0, offset)) + call assert_equal(w + offset, winwidth(0)) + call assert_true(0->win_move_separator(-offset)) + call assert_equal(w, winwidth(0)) + endfor + " check win_move_separator from right window on left window number + wincmd l + call assert_notequal(1, winnr()) + for offset in range(5) + call assert_true(1->win_move_separator(offset)) + call assert_equal(w + offset, winwidth(1)) + call assert_true(win_move_separator(1, -offset)) + call assert_equal(w, winwidth(1)) + endfor + " check win_move_separator from right window on left window ID + let id = win_getid(1) + for offset in range(5) + call assert_true(win_move_separator(id, offset)) + call assert_equal(w + offset, winwidth(id)) + call assert_true(id->win_move_separator(-offset)) + call assert_equal(w, winwidth(id)) + endfor + " check that win_move_separator doesn't error with offsets beyond moving + " possibility + call assert_true(win_move_separator(id, 5000)) + call assert_true(winwidth(id) > w) + call assert_true(win_move_separator(id, -5000)) + call assert_true(winwidth(id) < w) + " check that win_move_separator returns false for an invalid window + wincmd = + let w = winwidth(0) + call assert_false(win_move_separator(-1, 1)) + call assert_equal(w, winwidth(0)) + " check that win_move_separator returns false for a popup window + let id = popup_create(['hello', 'world'], {}) + let w = winwidth(id) + call assert_false(win_move_separator(id, 1)) + call assert_equal(w, winwidth(id)) + call popup_close(id) + %bwipe! +endfunc + +func Test_win_move_statusline() + edit a + leftabove split b + let h = winheight(0) + " check win_move_statusline from top window on top window + call assert_equal(1, winnr()) + for offset in range(5) + call assert_true(win_move_statusline(0, offset)) + call assert_equal(h + offset, winheight(0)) + call assert_true(0->win_move_statusline(-offset)) + call assert_equal(h, winheight(0)) + endfor + " check win_move_statusline from bottom window on top window number + wincmd j + call assert_notequal(1, winnr()) + for offset in range(5) + call assert_true(1->win_move_statusline(offset)) + call assert_equal(h + offset, winheight(1)) + call assert_true(win_move_statusline(1, -offset)) + call assert_equal(h, winheight(1)) + endfor + " check win_move_statusline from bottom window on top window ID + let id = win_getid(1) + for offset in range(5) + call assert_true(win_move_statusline(id, offset)) + call assert_equal(h + offset, winheight(id)) + call assert_true(id->win_move_statusline(-offset)) + call assert_equal(h, winheight(id)) + endfor + " check that win_move_statusline doesn't error with offsets beyond moving + " possibility + call assert_true(win_move_statusline(id, 5000)) + call assert_true(winheight(id) > h) + call assert_true(win_move_statusline(id, -5000)) + call assert_true(winheight(id) < h) + " check that win_move_statusline returns false for an invalid window + wincmd = + let h = winheight(0) + call assert_false(win_move_statusline(-1, 1)) + call assert_equal(h, winheight(0)) + " check that win_move_statusline returns false for a popup window + let id = popup_create(['hello', 'world'], {}) + let h = winheight(id) + call assert_false(win_move_statusline(id, 1)) + call assert_equal(h, winheight(id)) + call popup_close(id) + %bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4052, +/**/ 4051, /**/ 4050,