Patch 8.1.1140
Problem:    Not easy to find out what neighbors a window has.
Solution:   Add more arguments to winnr(). (Yegappan Lakshmanan, closes #3993)
Files:      runtime/doc/eval.txt, src/evalfunc.c, src/proto/window.pro,
            src/testdir/test_window_cmd.vim, src/window.c


*** ../vim-8.1.1139/runtime/doc/eval.txt        2019-04-06 13:18:06.733335092 
+0200
--- runtime/doc/eval.txt        2019-04-08 19:56:34.570615478 +0200
***************
*** 10139,10155 ****
                                                        *winnr()*
  winnr([{arg}])        The result is a Number, which is the number of the 
current
                window.  The top window has number 1.
!               When the optional argument is "$", the number of the
!               last window is returned (the window count). >
!                       let window_count = winnr('$')
! <             When the optional argument is "#", the number of the last
!               accessed window is returned (where |CTRL-W_p| goes to).
!               If there is no previous window or it is in another tab page 0
!               is returned.
                The number can be used with |CTRL-W_w| and ":wincmd w"
                |:wincmd|.
                Also see |tabpagewinnr()| and |win_getid()|.
! 
                                                        *winrestcmd()*
  winrestcmd()  Returns a sequence of |:resize| commands that should restore
                the current window sizes.  Only works properly when no windows
--- 10198,10227 ----
                                                        *winnr()*
  winnr([{arg}])        The result is a Number, which is the number of the 
current
                window.  The top window has number 1.
! 
!               The optional argument {arg} supports the following values:
!                       $       the number of the last window (the window
!                               count).
!                       #       the number of the last accessed window (where
!                               |CTRL-W_p| goes to).  If there is no previous
!                               window or it is in another tab page 0 is
!                               returned.
!                       {N}j    the number of the Nth window below the
!                               current window (where |CTRL-W_j| goes to).
!                       {N}k    the number of the Nth window above the current
!                               window (where |CTRL-W_k| goes to).
!                       {N}h    the number of the Nth window left of the
!                               current window (where |CTRL-W_h| goes to).
!                       {N}l    the number of the Nth window right of the
!                               current window (where |CTRL-W_l| goes to).
                The number can be used with |CTRL-W_w| and ":wincmd w"
                |:wincmd|.
                Also see |tabpagewinnr()| and |win_getid()|.
!               Examples: >
!                       let window_count = winnr('$')
!                       let prev_window = winnr('#')
!                       let wnum = winnr('3k')
! <
                                                        *winrestcmd()*
  winrestcmd()  Returns a sequence of |:resize| commands that should restore
                the current window sizes.  Only works properly when no windows
*** ../vim-8.1.1139/src/evalfunc.c      2019-04-07 14:21:26.230339328 +0200
--- src/evalfunc.c      2019-04-08 19:53:26.131435229 +0200
***************
*** 13982,13987 ****
--- 13982,13989 ----
      twin = (tp == curtab) ? curwin : tp->tp_curwin;
      if (argvar->v_type != VAR_UNKNOWN)
      {
+       int     invalid_arg = FALSE;
+ 
        arg = tv_get_string_chk(argvar);
        if (arg == NULL)
            nr = 0;             /* type error; errmsg already given */
***************
*** 13995,14000 ****
--- 13997,14028 ----
        }
        else
        {
+           long        count;
+           char_u      *endp;
+ 
+           // Extract the window count (if specified). e.g. winnr('3j')
+           count = strtol((char *)arg, (char **)&endp, 10);
+           if (count <= 0)
+               count = 1;      // if count is not specified, default to 1
+           if (endp != NULL && *endp != '\0')
+           {
+               if (STRCMP(endp, "j") == 0)
+                   twin = win_vert_neighbor(tp, twin, FALSE, count);
+               else if (STRCMP(endp, "k") == 0)
+                   twin = win_vert_neighbor(tp, twin, TRUE, count);
+               else if (STRCMP(endp, "h") == 0)
+                   twin = win_horz_neighbor(tp, twin, TRUE, count);
+               else if (STRCMP(endp, "l") == 0)
+                   twin = win_horz_neighbor(tp, twin, FALSE, count);
+               else
+                   invalid_arg = TRUE;
+           }
+           else
+               invalid_arg = TRUE;
+       }
+ 
+       if (invalid_arg)
+       {
            semsg(_(e_invexpr2), arg);
            nr = 0;
        }
*** ../vim-8.1.1139/src/proto/window.pro        2019-02-13 22:45:21.512636158 
+0100
--- src/proto/window.pro        2019-04-08 19:53:26.131435229 +0200
***************
*** 37,42 ****
--- 37,44 ----
  void win_goto(win_T *wp);
  win_T *win_find_nr(int winnr);
  tabpage_T *win_find_tabpage(win_T *win);
+ win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, int up, long count);
+ win_T *win_horz_neighbor(tabpage_T *tp, win_T * wp, int left, long count);
  void win_enter(win_T *wp, int undo_sync);
  win_T *buf_jump_open_win(buf_T *buf);
  win_T *buf_jump_open_tab(buf_T *buf);
*** ../vim-8.1.1139/src/testdir/test_window_cmd.vim     2019-03-04 
13:18:15.977053527 +0100
--- src/testdir/test_window_cmd.vim     2019-04-08 19:53:26.131435229 +0200
***************
*** 743,746 ****
--- 743,791 ----
    let &so = so_save
  endfunc
  
+ " Tests for the winnr() function
+ func Test_winnr()
+   only | tabonly
+   call assert_equal(1, winnr('j'))
+   call assert_equal(1, winnr('k'))
+   call assert_equal(1, winnr('h'))
+   call assert_equal(1, winnr('l'))
+ 
+   " create a set of horizontally and vertically split windows
+   leftabove new | wincmd p
+   leftabove new | wincmd p
+   rightbelow new | wincmd p
+   rightbelow new | wincmd p
+   leftabove vnew | wincmd p
+   leftabove vnew | wincmd p
+   rightbelow vnew | wincmd p
+   rightbelow vnew | wincmd p
+ 
+   call assert_equal(8, winnr('j'))
+   call assert_equal(2, winnr('k'))
+   call assert_equal(4, winnr('h'))
+   call assert_equal(6, winnr('l'))
+   call assert_equal(9, winnr('2j'))
+   call assert_equal(1, winnr('2k'))
+   call assert_equal(3, winnr('2h'))
+   call assert_equal(7, winnr('2l'))
+ 
+   " Error cases
+   call assert_fails("echo winnr('0.2k')", 'E15:')
+   call assert_equal(2, winnr('-2k'))
+   call assert_fails("echo winnr('-2xj')", 'E15:')
+   call assert_fails("echo winnr('j2j')", 'E15:')
+   call assert_fails("echo winnr('ll')", 'E15:')
+   call assert_fails("echo winnr('5')", 'E15:')
+   call assert_equal(4, winnr('0h'))
+ 
+   tabnew
+   call assert_equal(8, tabpagewinnr(1, 'j'))
+   call assert_equal(2, tabpagewinnr(1, 'k'))
+   call assert_equal(4, tabpagewinnr(1, 'h'))
+   call assert_equal(6, tabpagewinnr(1, 'l'))
+ 
+   only | tabonly
+ endfunc
+ 
  " vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.1.1139/src/window.c        2019-03-30 19:49:03.262806533 +0100
--- src/window.c        2019-04-08 19:58:55.705969739 +0200
***************
*** 4218,4235 ****
  #endif
  
  /*
!  * Move to window above or below "count" times.
   */
!     static void
! win_goto_ver(
!     int               up,             /* TRUE to go to win above */
!     long      count)
  {
      frame_T   *fr;
      frame_T   *nfr;
      frame_T   *foundfr;
  
!     foundfr = curwin->w_frame;
      while (count--)
      {
        /*
--- 4218,4236 ----
  #endif
  
  /*
!  * Get the above or below neighbor window of the specified window.
!  *   up - TRUE for the above neighbor
!  *   count - nth neighbor window
!  * Returns the specified window if the neighbor is not found.
   */
!     win_T *
! win_vert_neighbor(tabpage_T *tp, win_T *wp, int up, long count)
  {
      frame_T   *fr;
      frame_T   *nfr;
      frame_T   *foundfr;
  
!     foundfr = wp->w_frame;
      while (count--)
      {
        /*
***************
*** 4239,4245 ****
        fr = foundfr;
        for (;;)
        {
!           if (fr == topframe)
                goto end;
            if (up)
                nfr = fr->fr_prev;
--- 4240,4246 ----
        fr = foundfr;
        for (;;)
        {
!           if (fr == tp->tp_topframe)
                goto end;
            if (up)
                nfr = fr->fr_prev;
***************
*** 4266,4272 ****
                /* Find the frame at the cursor row. */
                while (fr->fr_next != NULL
                        && frame2win(fr)->w_wincol + fr->fr_width
!                                        <= curwin->w_wincol + curwin->w_wcol)
                    fr = fr->fr_next;
            }
            if (nfr->fr_layout == FR_COL && up)
--- 4267,4273 ----
                /* Find the frame at the cursor row. */
                while (fr->fr_next != NULL
                        && frame2win(fr)->w_wincol + fr->fr_width
!                                        <= wp->w_wincol + wp->w_wcol)
                    fr = fr->fr_next;
            }
            if (nfr->fr_layout == FR_COL && up)
***************
*** 4276,4298 ****
        }
      }
  end:
!     if (foundfr != NULL)
!       win_goto(foundfr->fr_win);
  }
  
  /*
!  * Move to left or right window.
   */
      static void
! win_goto_hor(
!     int               left,           /* TRUE to go to left win */
      long      count)
  {
      frame_T   *fr;
      frame_T   *nfr;
      frame_T   *foundfr;
  
!     foundfr = curwin->w_frame;
      while (count--)
      {
        /*
--- 4277,4314 ----
        }
      }
  end:
!     return foundfr != NULL ? foundfr->fr_win : NULL;
  }
  
  /*
!  * Move to window above or below "count" times.
   */
      static void
! win_goto_ver(
!     int               up,             // TRUE to go to win above
      long      count)
  {
+     win_T     *win;
+ 
+     win = win_vert_neighbor(curtab, curwin, up, count);
+     if (win != NULL)
+       win_goto(win);
+ }
+ 
+ /*
+  * Get the left or right neighbor window of the specified window.
+  *   left - TRUE for the left neighbor
+  *   count - nth neighbor window
+  * Returns the specified window if the neighbor is not found.
+  */
+     win_T *
+ win_horz_neighbor(tabpage_T *tp, win_T * wp, int left, long count)
+ {
      frame_T   *fr;
      frame_T   *nfr;
      frame_T   *foundfr;
  
!     foundfr = wp->w_frame;
      while (count--)
      {
        /*
***************
*** 4302,4308 ****
        fr = foundfr;
        for (;;)
        {
!           if (fr == topframe)
                goto end;
            if (left)
                nfr = fr->fr_prev;
--- 4318,4324 ----
        fr = foundfr;
        for (;;)
        {
!           if (fr == tp->tp_topframe)
                goto end;
            if (left)
                nfr = fr->fr_prev;
***************
*** 4329,4335 ****
                /* Find the frame at the cursor row. */
                while (fr->fr_next != NULL
                        && frame2win(fr)->w_winrow + fr->fr_height
!                                        <= curwin->w_winrow + curwin->w_wrow)
                    fr = fr->fr_next;
            }
            if (nfr->fr_layout == FR_ROW && left)
--- 4345,4351 ----
                /* Find the frame at the cursor row. */
                while (fr->fr_next != NULL
                        && frame2win(fr)->w_winrow + fr->fr_height
!                                        <= wp->w_winrow + wp->w_wrow)
                    fr = fr->fr_next;
            }
            if (nfr->fr_layout == FR_ROW && left)
***************
*** 4339,4346 ****
        }
      }
  end:
!     if (foundfr != NULL)
!       win_goto(foundfr->fr_win);
  }
  
  /*
--- 4355,4376 ----
        }
      }
  end:
!     return foundfr != NULL ? foundfr->fr_win : NULL;
! }
! 
! /*
!  * Move to left or right window.
!  */
!     static void
! win_goto_hor(
!     int               left,           // TRUE to go to left win
!     long      count)
! {
!     win_T     *win;
! 
!     win = win_horz_neighbor(curtab, curwin, left, count);
!     if (win != NULL)
!       win_goto(win);
  }
  
  /*
*** ../vim-8.1.1139/src/version.c       2019-04-08 18:59:50.973019097 +0200
--- src/version.c       2019-04-08 20:00:11.881612574 +0200
***************
*** 773,774 ****
--- 773,776 ----
  {   /* Add new patch number below this line */
+ /**/
+     1140,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
232. You start conversations with, "Have you gotten an ISDN line?"

 /// 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].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui