]> granicus.if.org Git - vim/commitdiff
patch 8.1.2020: it is not easy to change the window layout v8.1.2020
authorBram Moolenaar <Bram@vim.org>
Tue, 10 Sep 2019 19:22:58 +0000 (21:22 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 10 Sep 2019 19:22:58 +0000 (21:22 +0200)
Problem:    It is not easy to change the window layout.
Solution:   Add win_splitmove(). (Andy Massimino, closes #4561)

runtime/doc/eval.txt
src/evalfunc.c
src/evalwindow.c
src/proto/evalwindow.pro
src/testdir/test_window_cmd.vim
src/version.c

index 2ee1c247cdcc7ff983cfabdf03a9fad3f22ee90b..f19e0c04a741802b3c1111a587ee2548c9398e70 100644 (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
index dafd3b6af29e96ec29f99fbcee71ef45e35adcb8..438aac8eac44ebdd62304d86869e667153498e64 100644 (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},
index 351492c0b9056ad668a87ed63e2bf361719c8a37..08bdb9559cee6bd5bb2696fd3380cefdc93c0af9 100644 (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
  */
index c201a2e2d91078ce8cb3a85156cdbb292c4fcbe0..e3faa96eb595d78472bcb648eb88e176026f1cf9 100644 (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);
index 9bdae2c68b43cf52958b00e164c0ce59fd38c970..ffe8f431d463e15ffeec115818e132165579eb02 100644 (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
index afbf0bcee69f9337e62ef027be6be624553f65e3..44b6a5183fcc6bf7e0f03b54c56413bbbdced7a7 100644 (file)
@@ -757,6 +757,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2020,
 /**/
     2019,
 /**/