To: vim_dev@googlegroups.com Subject: Patch 8.1.1140 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@Moolenaar.net -- 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 ///