I am writing a plugin which needs to have two windows displayed at the same time:

|   |   |
| A | B |

I need to keep in memory a reference to those windows as I execute my plugin. This is because I need to be able to jump between the two windows automaticaly.

I use the winnr() function that returns the current window number, which I can use later like so:

let s:winA = winnr()
let s:winB = winnr()

" stuff

" go to window A
execute s:winA . "wincmd w"

But in this case, both variables will have the value 1, this is because the winnr() return the position of the current window in the tab display.

I tried to use the bufnr('%') which return the buffer number for the current buffer. This is great, but when I do:

let s:bufA = bufnr('%')
let s:bufB = bufnr('%')

" stuff

" go to buffer A
execute 'buffer '. s:bufA

The current window load the buffer, and the cursor will not jump to the existing window containing the buffer.

Here is my question:

How to store permanent information about windows so the cursor can jump on it later?

2 Answers 2


I think what you are looking for is the function win_getid() combined to the function win_gotoid().

:h win_getid() says:

win_getid([{win} [, {tab}]])

Get the window ID for the specified window.
When {win} is missing use the current window.
With {win} this is the window number. The top window has number 1.

The advantage of these functions is that ID is linked to a window and does not change when the position of the window is changed

Your script would become something like:

let s:winA = win_getid()
let s:winB = win_getid()

" stuff

" go to window A
call win_gotoid(s:winA)

You can't store a window number reliably because it changes every time a window is created and destroyed. You can use winbufnr() if you know the buffer's ID.

When the buffer doesn't matter, I use a window variable to keep track of the windows I open:

let w:_plugin_variable = 1

The variable above is just a boolean, but you could use your own identifier if you want to keep windows paired to each other. For example:

let w:_plugin_variable = ['parent', 123]
let w:_plugin_variable = ['child', 123]

The first item being the relationship and the second as some special identifier. This way is useful if both windows might contain the same buffer but have different settings/purposes.

To find the windows, you just iterate over all window numbers to get the variable you're looking for:

for i in range(1, winnr('$'))
  let id = getwinvar(i, '_plugin_variable', -1)
  if id != -1
    " Do something with the information.

In the loop above, i is the window's number. You can get settings from the window with getwinvar(i, '&textwidth') or switch to it with execute i 'wincmd w'.

The same thing can be done with tabs using tabpagenr(), tabpagewinnr(), gettabvar(), gettabwinvar(), etc.

  • Nice! Do you think there's performance drawback from doing this?
    – nobe4
    Jul 10, 2016 at 15:40
  • 1
    @nobe4 I'm pretty sure that any performance impact would be unnoticeable since you'd be dealing with dozens of windows at most (per tab) in realistic scenarios.
    – Tommy A
    Jul 10, 2016 at 15:57
  • 1
    See also this answer (useful in a wider context). Jul 10, 2016 at 19:17

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.