]> granicus.if.org Git - vim/commitdiff
patch 8.1.1140: not easy to find out what neighbors a window has v8.1.1140
authorBram Moolenaar <Bram@vim.org>
Mon, 8 Apr 2019 18:01:47 +0000 (20:01 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 8 Apr 2019 18:01:47 +0000 (20:01 +0200)
Problem:    Not easy to find out what neighbors a window has.
Solution:   Add more arguments to winnr(). (Yegappan Lakshmanan, closes #3993)

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

index 8a4a54c55b08a91194247a760e82fa182e189e71..c454f96dcbafeba1d7b94d5156beb9ce22b579e0 100644 (file)
@@ -10198,17 +10198,30 @@ winline()     The result is a Number, which is the screen line of the cursor
                                                        *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 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
index 7f8330f999e25450109f24ab2f7396e0200d0d2f..76f1125a1db2370cd42e10d635b97e6e521689b6 100644 (file)
@@ -13982,6 +13982,8 @@ get_winnr(tabpage_T *tp, typval_T *argvar)
     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 */
@@ -13994,6 +13996,32 @@ get_winnr(tabpage_T *tp, typval_T *argvar)
                nr = 0;
        }
        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;
index 0efff64eb3531b4bc405d55d509177c3f4afc52c..5020b2f037dbf97a585199de25a15def3bff93c6 100644 (file)
@@ -37,6 +37,8 @@ void tabpage_move(int nr);
 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);
index 5189e681fc6045aa2d5645ba77e78d32271ee9ca..38fd10d948a3675f9600cc4520fec8378cd900ec 100644 (file)
@@ -743,4 +743,49 @@ func Test_relative_cursor_second_line_after_resize()
   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
index 314f4b7025686dec73a4a185581a3c2eceea5889..7c3490e7e5ab480b64e90de1167791cd78b6473f 100644 (file)
@@ -771,6 +771,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1140,
 /**/
     1139,
 /**/
index b905fbf3972830413612fea52a1459a8a4999a64..4dda512af2a6a715d7d56ce1d71f683c2b5c0edd 100644 (file)
@@ -4218,18 +4218,19 @@ win_find_tabpage(win_T *win)
 #endif
 
 /*
- * Move to window above or below "count" times.
+ * 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.
  */
-    static void
-win_goto_ver(
-    int                up,             /* TRUE to go to win above */
-    long       count)
+    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 = curwin->w_frame;
+    foundfr = wp->w_frame;
     while (count--)
     {
        /*
@@ -4239,7 +4240,7 @@ win_goto_ver(
        fr = foundfr;
        for (;;)
        {
-           if (fr == topframe)
+           if (fr == tp->tp_topframe)
                goto end;
            if (up)
                nfr = fr->fr_prev;
@@ -4266,7 +4267,7 @@ win_goto_ver(
                /* 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)
+                                        <= wp->w_wincol + wp->w_wcol)
                    fr = fr->fr_next;
            }
            if (nfr->fr_layout == FR_COL && up)
@@ -4276,23 +4277,38 @@ win_goto_ver(
        }
     }
 end:
-    if (foundfr != NULL)
-       win_goto(foundfr->fr_win);
+    return foundfr != NULL ? foundfr->fr_win : NULL;
 }
 
 /*
- * Move to left or right window.
+ * Move to window above or below "count" times.
  */
     static void
-win_goto_hor(
-    int                left,           /* TRUE to go to left win */
+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 = curwin->w_frame;
+    foundfr = wp->w_frame;
     while (count--)
     {
        /*
@@ -4302,7 +4318,7 @@ win_goto_hor(
        fr = foundfr;
        for (;;)
        {
-           if (fr == topframe)
+           if (fr == tp->tp_topframe)
                goto end;
            if (left)
                nfr = fr->fr_prev;
@@ -4329,7 +4345,7 @@ win_goto_hor(
                /* 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)
+                                        <= wp->w_winrow + wp->w_wrow)
                    fr = fr->fr_next;
            }
            if (nfr->fr_layout == FR_ROW && left)
@@ -4339,8 +4355,22 @@ win_goto_hor(
        }
     }
 end:
-    if (foundfr != NULL)
-       win_goto(foundfr->fr_win);
+    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);
 }
 
 /*