mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 14:58:18 +00:00
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)
46ad288b9b
This commit is contained in:
@@ -8405,17 +8405,30 @@ winline() The result is a Number, which is the screen line of the cursor
|
|||||||
*winnr()*
|
*winnr()*
|
||||||
winnr([{arg}]) The result is a Number, which is the number of the current
|
winnr([{arg}]) The result is a Number, which is the number of the current
|
||||||
window. The top window has number 1.
|
window. The top window has number 1.
|
||||||
When the optional argument is "$", the number of the
|
|
||||||
last window is returned (the window count). >
|
The optional argument {arg} supports the following values:
|
||||||
let window_count = winnr('$')
|
$ the number of the last window (the window
|
||||||
< When the optional argument is "#", the number of the last
|
count).
|
||||||
accessed window is returned (where |CTRL-W_p| goes to).
|
# the number of the last accessed window (where
|
||||||
If there is no previous window or it is in another tab page 0
|
|CTRL-W_p| goes to). If there is no previous
|
||||||
is returned.
|
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"
|
The number can be used with |CTRL-W_w| and ":wincmd w"
|
||||||
|:wincmd|.
|
|:wincmd|.
|
||||||
Also see |tabpagewinnr()| and |win_getid()|.
|
Also see |tabpagewinnr()| and |win_getid()|.
|
||||||
|
Examples: >
|
||||||
|
let window_count = winnr('$')
|
||||||
|
let prev_window = winnr('#')
|
||||||
|
let wnum = winnr('3k')
|
||||||
|
<
|
||||||
*winrestcmd()*
|
*winrestcmd()*
|
||||||
winrestcmd() Returns a sequence of |:resize| commands that should restore
|
winrestcmd() Returns a sequence of |:resize| commands that should restore
|
||||||
the current window sizes. Only works properly when no windows
|
the current window sizes. Only works properly when no windows
|
||||||
|
@@ -16755,6 +16755,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar)
|
|||||||
|
|
||||||
twin = (tp == curtab) ? curwin : tp->tp_curwin;
|
twin = (tp == curtab) ? curwin : tp->tp_curwin;
|
||||||
if (argvar->v_type != VAR_UNKNOWN) {
|
if (argvar->v_type != VAR_UNKNOWN) {
|
||||||
|
bool invalid_arg = false;
|
||||||
const char *const arg = tv_get_string_chk(argvar);
|
const char *const arg = tv_get_string_chk(argvar);
|
||||||
if (arg == NULL) {
|
if (arg == NULL) {
|
||||||
nr = 0; // Type error; errmsg already given.
|
nr = 0; // Type error; errmsg already given.
|
||||||
@@ -16766,6 +16767,31 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar)
|
|||||||
nr = 0;
|
nr = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
EMSG2(_(e_invexpr2), arg);
|
||||||
nr = 0;
|
nr = 0;
|
||||||
}
|
}
|
||||||
|
@@ -646,4 +646,49 @@ func Test_relative_cursor_second_line_after_resize()
|
|||||||
let &so = so_save
|
let &so = so_save
|
||||||
endfunc
|
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: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -4019,24 +4019,25 @@ tabpage_T *win_find_tabpage(win_T *win)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Get the above or below neighbor window of the specified window.
|
||||||
* Move to window above or below "count" times.
|
///
|
||||||
*/
|
/// Returns the specified window if the neighbor is not found.
|
||||||
static void
|
/// Returns the previous window if the specifiecied window is a floating window.
|
||||||
win_goto_ver (
|
///
|
||||||
int up, /* TRUE to go to win above */
|
/// @param up true for the above neighbor
|
||||||
long count
|
/// @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 *fr;
|
||||||
frame_T *nfr;
|
frame_T *nfr;
|
||||||
frame_T *foundfr;
|
frame_T *foundfr;
|
||||||
|
|
||||||
foundfr = curwin->w_frame;
|
foundfr = wp->w_frame;
|
||||||
|
|
||||||
if (curwin->w_floating) {
|
if (wp->w_floating) {
|
||||||
win_goto(prevwin);
|
return prevwin;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
@@ -4046,14 +4047,17 @@ win_goto_ver (
|
|||||||
*/
|
*/
|
||||||
fr = foundfr;
|
fr = foundfr;
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
if (fr == topframe)
|
if (fr == tp->tp_topframe) {
|
||||||
goto end;
|
goto end;
|
||||||
if (up)
|
}
|
||||||
|
if (up) {
|
||||||
nfr = fr->fr_prev;
|
nfr = fr->fr_prev;
|
||||||
else
|
} else {
|
||||||
nfr = fr->fr_next;
|
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;
|
break;
|
||||||
|
}
|
||||||
fr = fr->fr_parent;
|
fr = fr->fr_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4067,11 +4071,12 @@ win_goto_ver (
|
|||||||
}
|
}
|
||||||
fr = nfr->fr_child;
|
fr = nfr->fr_child;
|
||||||
if (nfr->fr_layout == FR_ROW) {
|
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
|
while (fr->fr_next != NULL
|
||||||
&& frame2win(fr)->w_wincol + fr->fr_width
|
&& frame2win(fr)->w_wincol + fr->fr_width
|
||||||
<= curwin->w_wincol + curwin->w_wcol)
|
<= wp->w_wincol + wp->w_wcol) {
|
||||||
fr = fr->fr_next;
|
fr = fr->fr_next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nfr->fr_layout == FR_COL && up)
|
if (nfr->fr_layout == FR_COL && up)
|
||||||
while (fr->fr_next != NULL)
|
while (fr->fr_next != NULL)
|
||||||
@@ -4080,28 +4085,40 @@ win_goto_ver (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
if (foundfr != NULL)
|
return foundfr != NULL ? foundfr->fr_win : NULL;
|
||||||
win_goto(foundfr->fr_win);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// Move to window above or below "count" times.
|
||||||
* Move to left or right window.
|
///
|
||||||
*/
|
/// @param up true to go to win above
|
||||||
static void
|
/// @param count go count times into direction
|
||||||
win_goto_hor (
|
static void win_goto_ver(bool up, long count)
|
||||||
int left, /* TRUE to go to left win */
|
{
|
||||||
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 *fr;
|
||||||
frame_T *nfr;
|
frame_T *nfr;
|
||||||
frame_T *foundfr;
|
frame_T *foundfr;
|
||||||
|
|
||||||
foundfr = curwin->w_frame;
|
foundfr = wp->w_frame;
|
||||||
|
|
||||||
if (curwin->w_floating) {
|
if (wp->w_floating) {
|
||||||
win_goto(prevwin);
|
return prevwin;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
@@ -4111,14 +4128,17 @@ win_goto_hor (
|
|||||||
*/
|
*/
|
||||||
fr = foundfr;
|
fr = foundfr;
|
||||||
for (;; ) {
|
for (;; ) {
|
||||||
if (fr == topframe)
|
if (fr == tp->tp_topframe) {
|
||||||
goto end;
|
goto end;
|
||||||
if (left)
|
}
|
||||||
|
if (left) {
|
||||||
nfr = fr->fr_prev;
|
nfr = fr->fr_prev;
|
||||||
else
|
} else {
|
||||||
nfr = fr->fr_next;
|
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;
|
break;
|
||||||
|
}
|
||||||
fr = fr->fr_parent;
|
fr = fr->fr_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4135,7 +4155,7 @@ win_goto_hor (
|
|||||||
/* Find the frame at the cursor row. */
|
/* Find the frame at the cursor row. */
|
||||||
while (fr->fr_next != NULL
|
while (fr->fr_next != NULL
|
||||||
&& frame2win(fr)->w_winrow + fr->fr_height
|
&& frame2win(fr)->w_winrow + fr->fr_height
|
||||||
<= curwin->w_winrow + curwin->w_wrow)
|
<= wp->w_winrow + wp->w_wrow)
|
||||||
fr = fr->fr_next;
|
fr = fr->fr_next;
|
||||||
}
|
}
|
||||||
if (nfr->fr_layout == FR_ROW && left)
|
if (nfr->fr_layout == FR_ROW && left)
|
||||||
@@ -4145,8 +4165,19 @@ win_goto_hor (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
if (foundfr != NULL)
|
return foundfr != NULL ? foundfr->fr_win : NULL;
|
||||||
win_goto(foundfr->fr_win);
|
}
|
||||||
|
|
||||||
|
/// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user