diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/evalfunc.c | 28 | ||||
-rw-r--r-- | src/proto/window.pro | 2 | ||||
-rw-r--r-- | src/testdir/test_window_cmd.vim | 45 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/window.c | 66 |
5 files changed, 125 insertions, 18 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c index 7f8330f999..76f1125a1d 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -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 */ @@ -13995,6 +13997,32 @@ get_winnr(tabpage_T *tp, typval_T *argvar) } 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; } diff --git a/src/proto/window.pro b/src/proto/window.pro index 0efff64eb3..5020b2f037 100644 --- a/src/proto/window.pro +++ b/src/proto/window.pro @@ -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); diff --git a/src/testdir/test_window_cmd.vim b/src/testdir/test_window_cmd.vim index 5189e681fc..38fd10d948 100644 --- a/src/testdir/test_window_cmd.vim +++ b/src/testdir/test_window_cmd.vim @@ -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 diff --git a/src/version.c b/src/version.c index 314f4b7025..7c3490e7e5 100644 --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1140, +/**/ 1139, /**/ 1138, diff --git a/src/window.c b/src/window.c index b905fbf397..4dda512af2 100644 --- a/src/window.c +++ b/src/window.c @@ -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); } /* |