diff options
-rw-r--r-- | runtime/doc/eval.txt | 30 | ||||
-rw-r--r-- | src/nvim/eval.c | 19 | ||||
-rw-r--r-- | src/nvim/eval.lua | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_window_id.vim | 20 | ||||
-rw-r--r-- | src/nvim/window.c | 35 |
5 files changed, 105 insertions, 0 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 7682a1a584..32783f0851 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2377,6 +2377,7 @@ win_screenpos({nr}) List get screen position of window {nr} winbufnr({nr}) Number buffer number of window {nr} wincol() Number window column of the cursor winheight({nr}) Number height of window {nr} +winlayout([{tabnr}]) List layout of windows in tab {tabnr} winline() Number window line of the cursor winnr([{expr}]) Number number of current window winrestcmd() String returns command to restore window sizes @@ -8538,6 +8539,35 @@ winheight({nr}) *winheight()* Examples: > :echo "The current window has " . winheight(0) . " lines." < +winlayout([{tabnr}]) *winlayout()* + The result is a nested List containing the layout of windows + in a tabpage. + + Without {tabnr} use the current tabpage, otherwise the tabpage + with number {tabnr}. If the tabpage {tabnr} is not found, + returns an empty list. + + For a leaf window, it returns: + ['leaf', {winid}] + For horizontally split windows, which form a column, it + returns: + ['col', [{nested list of windows}]] + For vertically split windows, which form a row, it returns: + ['row', [{nested list of windows}]] + + Example: > + " Only one window in the tab page + :echo winlayout() + ['leaf', 1000] + " Two horizontally split windows + :echo winlayout() + ['col', [['leaf', 1000], ['leaf', 1001]]] + " Three horizontally split windows, with two + " vertically split windows in the middle window + :echo winlayout(2) + ['col', [['leaf', 1002], ['row', ['leaf', 1003], + ['leaf', 1001]]], ['leaf', 1000]] +< *winline()* winline() The result is a Number, which is the screen line of the cursor in the window. This is counting screen lines from the top of diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 78a6092fa1..868305c88d 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -17872,6 +17872,25 @@ static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +// "winlayout()" function +static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + tabpage_T *tp; + + tv_list_alloc_ret(rettv, 2); + + if (argvars[0].v_type == VAR_UNKNOWN) { + tp = curtab; + } else { + tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp == NULL) { + return; + } + } + + get_framelayout(tp->tp_topframe, rettv->vval.v_list, true); +} + /* * "winline()" function */ diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index aad2de5d30..dea00c3edd 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -352,6 +352,7 @@ return { winbufnr={args=1}, wincol={}, winheight={args=1}, + winlayout={args={0, 1}}, winline={}, winnr={args={0, 1}}, winrestcmd={}, diff --git a/src/nvim/testdir/test_window_id.vim b/src/nvim/testdir/test_window_id.vim index b3b506d04d..d10d831650 100644 --- a/src/nvim/testdir/test_window_id.vim +++ b/src/nvim/testdir/test_window_id.vim @@ -101,3 +101,23 @@ func Test_win_getid_curtab() call assert_equal(win_getid(1), win_getid(1, 1)) tabclose! endfunc + +func Test_winlayout() + let w1 = win_getid() + call assert_equal(['leaf', w1], winlayout()) + + split + let w2 = win_getid() + call assert_equal(['col', [['leaf', w2], ['leaf', w1]]], winlayout()) + + split + let w3 = win_getid() + call assert_equal(['col', [['leaf', w3], ['leaf', w2], ['leaf', w1]]], winlayout()) + + 2wincmd w + vsplit + let w4 = win_getid() + call assert_equal(['col', [['leaf', w3], ['row', [['leaf', w4], ['leaf', w2]]], ['leaf', w1]]], winlayout()) + + only! +endfunc diff --git a/src/nvim/window.c b/src/nvim/window.c index 2ce3b7067b..e6b19cf88d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6658,6 +6658,41 @@ void win_findbuf(typval_T *argvars, list_T *list) } } +// Get the layout of the given tab page for winlayout(). +void get_framelayout(const frame_T *fr, list_T *l, bool outer) +{ + list_T *fr_list; + + if (fr == NULL) { + return; + } + + if (outer) { + // outermost call from f_winlayout() + fr_list = l; + } else { + fr_list = tv_list_alloc(2); + tv_list_append_list(l, fr_list); + } + + if (fr->fr_layout == FR_LEAF) { + if (fr->fr_win != NULL) { + tv_list_append_string(fr_list, "leaf", -1); + tv_list_append_number(fr_list, fr->fr_win->handle); + } + } else { + tv_list_append_string(fr_list, fr->fr_layout == FR_ROW ? "row" : "col", -1); + + list_T *const win_list = tv_list_alloc(kListLenUnknown); + tv_list_append_list(fr_list, win_list); + const frame_T *child = fr->fr_child; + while (child != NULL) { + get_framelayout(child, win_list, false); + child = child->fr_next; + } + } +} + void win_ui_flush_positions(void) { FOR_ALL_TAB_WINDOWS(tp, wp) { |