Patch 8.1.2020
Problem:    It is not easy to change the window layout.
Solution:   Add win_splitmove(). (Andy Massimino, closes #4561)
Files:      runtime/doc/eval.txt, src/evalfunc.c, src/evalwindow.c,
            src/proto/evalwindow.pro, src/testdir/test_window_cmd.vim


*** ../vim-8.1.2019/runtime/doc/eval.txt        2019-09-08 21:51:36.449843947 
+0200
--- runtime/doc/eval.txt        2019-09-10 21:15:07.066394525 +0200
***************
*** 2870,2875 ****
--- 2875,2882 ----
  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}
***************
*** 10130,10135 ****
--- 10146,10173 ----
                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
                associated with window {nr}.  {nr} can be the window number or
*** ../vim-8.1.2019/src/evalfunc.c      2019-09-08 21:51:36.449843947 +0200
--- src/evalfunc.c      2019-09-10 21:10:59.351329244 +0200
***************
*** 850,855 ****
--- 850,856 ----
      {"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},
*** ../vim-8.1.2019/src/evalwindow.c    2019-09-07 15:45:09.977228927 +0200
--- src/evalwindow.c    2019-09-10 21:21:03.581049143 +0200
***************
*** 744,749 ****
--- 744,835 ----
  }
  
  /*
+  * 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
*** ../vim-8.1.2019/src/proto/evalwindow.pro    2019-09-07 15:45:09.977228927 
+0200
--- src/proto/evalwindow.pro    2019-09-10 21:10:59.351329244 +0200
***************
*** 19,24 ****
--- 19,25 ----
  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);
*** ../vim-8.1.2019/src/testdir/test_window_cmd.vim     2019-09-08 
21:51:36.453843927 +0200
--- src/testdir/test_window_cmd.vim     2019-09-10 21:21:45.492890991 +0200
***************
*** 857,860 ****
--- 857,893 ----
    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
*** ../vim-8.1.2019/src/version.c       2019-09-09 22:04:19.366736952 +0200
--- src/version.c       2019-09-10 21:22:06.432811971 +0200
***************
*** 759,760 ****
--- 759,762 ----
  {   /* Add new patch number below this line */
+ /**/
+     2020,
  /**/

-- 
You are Dead.  Do you wish to restart, load, or quit?

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/201909101923.x8AJNbVt021077%40masaka.moolenaar.net.

Raspunde prin e-mail lui