summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-04-08 20:01:47 +0200
committerBram Moolenaar <Bram@vim.org>2019-04-08 20:01:47 +0200
commit46ad288b9b2a6eb0430cf802ff5ce68a58629897 (patch)
treec4122a4f891cd211e2604b690cefef88b2d7c8ff
parent9845f36aa6ba28e0aa388bb635d4bb8ab56f1a47 (diff)
downloadvim-git-46ad288b9b2a6eb0430cf802ff5ce68a58629897.tar.gz
patch 8.1.1140: not easy to find out what neighbors a window hasv8.1.1140
Problem: Not easy to find out what neighbors a window has. Solution: Add more arguments to winnr(). (Yegappan Lakshmanan, closes #3993)
-rw-r--r--runtime/doc/eval.txt29
-rw-r--r--src/evalfunc.c28
-rw-r--r--src/proto/window.pro2
-rw-r--r--src/testdir/test_window_cmd.vim45
-rw-r--r--src/version.c2
-rw-r--r--src/window.c66
6 files changed, 146 insertions, 26 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 8a4a54c55..c454f96dc 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -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
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 7f8330f99..76f1125a1 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 0efff64eb..5020b2f03 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 5189e681f..38fd10d94 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 314f4b702..7c3490e7e 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 b905fbf39..4dda512af 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);
}
/*