diff options
author | Marco Hinz <mh.codebro+github@gmail.com> | 2019-04-10 10:16:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-10 10:16:32 +0200 |
commit | 21b108fe445452e6e35621184fc77623dc64f9a3 (patch) | |
tree | 8e861512afe04e03aee45fdd7a3129e8cd694d7b /src | |
parent | ddd0eb6f5120a09b97867d2561ea61309038ccd2 (diff) | |
download | rneovim-21b108fe445452e6e35621184fc77623dc64f9a3.tar.gz rneovim-21b108fe445452e6e35621184fc77623dc64f9a3.tar.bz2 rneovim-21b108fe445452e6e35621184fc77623dc64f9a3.zip |
vim-patch:8.1.1140: not easy to find out what neighbors a window has (#9873)
Problem: Not easy to find out what neighbors a window has.
Solution: Add more arguments to winnr(). (Yegappan Lakshmanan)
https://github.com/vim/vim/commit/46ad288b9b2a6eb0430cf802ff5ce68a58629897
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 26 | ||||
-rw-r--r-- | src/nvim/testdir/test_window_cmd.vim | 45 | ||||
-rw-r--r-- | src/nvim/window.c | 109 |
3 files changed, 141 insertions, 39 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 9a67b01307..86333acbef 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16755,6 +16755,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) twin = (tp == curtab) ? curwin : tp->tp_curwin; if (argvar->v_type != VAR_UNKNOWN) { + bool invalid_arg = false; const char *const arg = tv_get_string_chk(argvar); if (arg == NULL) { nr = 0; // Type error; errmsg already given. @@ -16766,6 +16767,31 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) nr = 0; } } else { + // Extract the window count (if specified). e.g. winnr('3j') + char_u *endp; + long count = strtol((char *)arg, (char **)&endp, 10); + if (count <= 0) { + // if count is not specified, default to 1 + count = 1; + } + if (endp != NULL && *endp != '\0') { + if (strequal((char *)endp, "j")) { + twin = win_vert_neighbor(tp, twin, false, count); + } else if (strequal((char *)endp, "k")) { + twin = win_vert_neighbor(tp, twin, true, count); + } else if (strequal((char *)endp, "h")) { + twin = win_horz_neighbor(tp, twin, true, count); + } else if (strequal((char *)endp, "l")) { + twin = win_horz_neighbor(tp, twin, false, count); + } else { + invalid_arg = true; + } + } else { + invalid_arg = true; + } + } + + if (invalid_arg) { EMSG2(_(e_invexpr2), arg); nr = 0; } diff --git a/src/nvim/testdir/test_window_cmd.vim b/src/nvim/testdir/test_window_cmd.vim index 57fb36abb8..d3b496635d 100644 --- a/src/nvim/testdir/test_window_cmd.vim +++ b/src/nvim/testdir/test_window_cmd.vim @@ -646,4 +646,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/nvim/window.c b/src/nvim/window.c index e135d7436d..237338f974 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4019,24 +4019,25 @@ tabpage_T *win_find_tabpage(win_T *win) return NULL; } -/* - * Move to window above or below "count" times. - */ -static void -win_goto_ver ( - int up, /* TRUE to go to win above */ - long count -) +/// Get the above or below neighbor window of the specified window. +/// +/// Returns the specified window if the neighbor is not found. +/// Returns the previous window if the specifiecied window is a floating window. +/// +/// @param up true for the above neighbor +/// @param count nth neighbor window +/// +/// @return found window +win_T *win_vert_neighbor(tabpage_T *tp, win_T *wp, bool up, long count) { frame_T *fr; frame_T *nfr; frame_T *foundfr; - foundfr = curwin->w_frame; + foundfr = wp->w_frame; - if (curwin->w_floating) { - win_goto(prevwin); - return; + if (wp->w_floating) { + return prevwin; } while (count--) { @@ -4046,14 +4047,17 @@ win_goto_ver ( */ fr = foundfr; for (;; ) { - if (fr == topframe) + if (fr == tp->tp_topframe) { goto end; - if (up) + } + if (up) { nfr = fr->fr_prev; - else + } else { nfr = fr->fr_next; - if (fr->fr_parent->fr_layout == FR_COL && nfr != NULL) + } + if (fr->fr_parent->fr_layout == FR_COL && nfr != NULL) { break; + } fr = fr->fr_parent; } @@ -4067,11 +4071,12 @@ win_goto_ver ( } fr = nfr->fr_child; if (nfr->fr_layout == FR_ROW) { - /* Find the frame at the cursor row. */ + // 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) while (fr->fr_next != NULL) @@ -4080,28 +4085,40 @@ 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. - */ -static void -win_goto_hor ( - int left, /* TRUE to go to left win */ - long count -) +/// Move to window above or below "count" times. +/// +/// @param up true to go to win above +/// @param count go count times into direction +static void win_goto_ver(bool up, long count) +{ + win_T *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. +/// +/// Returns the specified window if the neighbor is not found. +/// Returns the previous window if the specifiecied window is a floating window. +/// +/// @param left true for the left neighbor +/// @param count nth neighbor window +/// +/// @return found window +win_T *win_horz_neighbor(tabpage_T *tp, win_T *wp, bool left, long count) { frame_T *fr; frame_T *nfr; frame_T *foundfr; - foundfr = curwin->w_frame; + foundfr = wp->w_frame; - if (curwin->w_floating) { - win_goto(prevwin); - return; + if (wp->w_floating) { + return prevwin; } while (count--) { @@ -4111,14 +4128,17 @@ win_goto_hor ( */ fr = foundfr; for (;; ) { - if (fr == topframe) + if (fr == tp->tp_topframe) { goto end; - if (left) + } + if (left) { nfr = fr->fr_prev; - else + } else { nfr = fr->fr_next; - if (fr->fr_parent->fr_layout == FR_ROW && nfr != NULL) + } + if (fr->fr_parent->fr_layout == FR_ROW && nfr != NULL) { break; + } fr = fr->fr_parent; } @@ -4135,7 +4155,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) @@ -4145,8 +4165,19 @@ 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. +/// +/// @param left true to go to left window +/// @param count go count times into direction +static void win_goto_hor(bool left, long count) +{ + win_T *win = win_horz_neighbor(curtab, curwin, left, count); + if (win != NULL) { + win_goto(win); + } } /* |