0

Consider a window layout as this (which I've set up esentially at random).

┌───────┬───────┬───────┬────────┐
│       │       │       │        │
│   x   │   y   │   z   │        │
│       │       │       │        │
├───────┴───────┴───────┤        │
│                       │        │
│           u           │        │
│                       │        │
├───────────────────────┤        │
│                       │        │
│           v           │        │
│                       │        │
├───────────────────────┴────────┤
│                                │
│                                │
└────────────────────────────────┘

Is there a way, if the cursor is in any of x, y, or z, to retrieve the list of all three windows?

The reason I think it is possible, in principle, is that there's one command that has to query for that list of windows, that is Ctrl-Wr.

Similarly, I think it would be possible to make the same query when the cursor is in u or v, in which case the answer would be a list of u, v, and [x,z,y].

In this case too, the error E443 tells me that the query was done and gave the correct answer.

2 Answers 2

2

You can use the winlayout() function to get information about the layout of the windows (rows and columns).

With the above window layout, this function will return (something similar to the following):

['col', [['row', [['col', [['row', [['leaf', 1007], ['leaf', 1006], ['leaf', 1005]]], ['leaf', 1004], ['leaf', 1003]]], ['leaf', 1002]]], ['leaf', 1000]]]

The numbers in the output are the window identifiers.

0

Try this Vimscript:

function! GetSimilarWindowsInDirection(dir)
    let prev_winnr = winnr()
    let orig_w = winwidth(0)
    let orig_h = winheight(0)

    let similar_windows = []

    if a:dir=='j' || a:dir == 'k'
        let match_prop = 'width'
    elseif a:dir == 'l' || a:dir == 'h'
        let match_prop = 'height'
    else
        return
    endif

    " Check Nth window in the direction given for similar width
    let N = 1
    while v:true
        let new_winnr = winnr(N.a:dir)

        if new_winnr == prev_winnr
            " We hit the edge, no more windows to find
            break
        endif

        if match_prop == 'width'
            let new_w = winwidth(new_winnr)
            if new_w != orig_w | break |endif

        elseif match_prop == 'height'
            let new_h = winheight(new_winnr)
            if new_h != orig_h | break |endif

        endif

        call add(similar_windows, new_winnr)

        let prev_winnr = new_winnr
        let N+=1
    endwhile

    return similar_windows

endfunction

function! GetSimilarWindows(type)
    let similar_windows = [winnr()]

    if a:type == 'col'
        call extend(similar_windows, GetSimilarWindowsInDirection('j'))
        call extend(similar_windows, GetSimilarWindowsInDirection('k'))
    elseif a:type == 'row'
        call extend(similar_windows, GetSimilarWindowsInDirection('h'))
        call extend(similar_windows, GetSimilarWindowsInDirection('l'))

    endif

    return sort(similar_windows,'n')

endfunction

With the cursor in window y in your diagram: echo GetSimilarWindows('row') will return [1,2,3]

2
  • 1
    Instead of jumping to the neighbor window to get the window number, you can use the winnr() vimhelp.org/eval.txt.html#winnr%28%29 function with the 'h' 'j', 'k' or 'l' argument to get the left/below/above/right window number. You can also prefix this argument with a number to get the n'th neighbor window. Sep 4, 2021 at 17:07
  • I edited my Vimscript to a better algorith with help from your comment too. In a 3x3 grid, my previous code wouldn't identify a complete row or column. I changed the requirement to equal width for columns and equal height for rows. Sep 4, 2021 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.