Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a shortcut for moving between Vim windows?

Tags:

vim

window

buffer

Let’s say I have single Vim tab displaying 9 buffers (equally separated, like a 3×3 table).

Currently, to get from the top left window to the bottom right one, I have to press 3, Ctrl+W, J, and then 3, Ctrl+W, L. This is cumbersome, and I would like to just be able to press Ctrl+9 to go to the 9th window, and Ctrl+3 to go to the 3rd window, etc.

Is there any easy way I can map something like this in Vim?

like image 314
Kamilski81 Avatar asked Jun 19 '11 16:06

Kamilski81


People also ask

How do I quickly switch between windows in Vim?

To move from the current Vim window to the next one, type CTRL-W j (or CTRL-W <down> or CTRL-W CTRL-J).

How do I switch between terminals in Vim?

Use ctrl-w N to switch to "terminal-normal mode", which will let you navigate around. It could be useful to then copy content to the clipboard. Then return to regular terminal mode, simply type i just like how you'd enter insert mode from a regular window. ctrl-w : will open command mode like in regular Vim.


2 Answers

There's a much simpler solution than using the mouse or hard-set movement mappings; they will break if the window numberings are different from what you have in mind for a 3x3 matrix, or if you decide to work with less than 9 windows. Here's how:

Include the following in your .vimrc:

let i = 1
while i <= 9
    execute 'nnoremap <Leader>' . i . ' :' . i . 'wincmd w<CR>'
    let i = i + 1
endwhile

Now you can just press <Leader><number> and be taken to the window number you want. I wouldn't recommend going beyond 9, because IMO, the utility of having multiple viewports follows a Rayleigh distribution and quickly becomes useless with too many viewports in one window.

It will be helpful if you have the window number displayed in your statusline to aid you in quickly figuring out which window you're on and which window you want to go to. To do that, use this little function and add it accordingly in your statusline.

function! WindowNumber()
    let str=tabpagewinnr(tabpagenr())
    return str
endfunction

See it in action in your statusline:

set laststatus=2
set statusline=win:%{WindowNumber()}

Note that the above line will replace your statusline. It was just meant for illustration purposes, to show how to call the function. You should place it where ever you think is appropriate in your statusline. Here's what mine looks like:

enter image description here


Update

romainl asked for my status line in the comments, so here it is:

"statusline
hi StatusLine term=bold cterm=bold ctermfg=White ctermbg=235
hi StatusHostname term=bold cterm=bold ctermfg=107 ctermbg=235 guifg=#799d6a
hi StatusGitBranch term=bold cterm=bold ctermfg=215 ctermbg=235 guifg=#ffb964

function! MyGitBranchStyle()
    let branch = GitBranch()
    if branch == ''
        let branchStyle = ''
    else
        let branchStyle = 'git:' . branch
    end
    return branchStyle
endfunction

function! WindowNumber()
    let str=tabpagewinnr(tabpagenr())
    return str
endfunction

set laststatus=2
set statusline=%#StatusLine#%F%h%m%r\ %h%w%y\ col:%c\ lin:%l\,%L\ buf:%n\ win:%{WindowNumber()}\ reg:%{v:register}\ %#StatusGitBranch#%{MyGitBranchStyle()}\ \%=%#StatusLine#%{strftime(\"%d/%m/%Y-%H:%M\")}\ %#StatusHostname#%{hostname()}

The last line should be a single line (be careful if your setup automatically breaks it into multiple lines). I know there are ways to keep it organized with incremental string joins in each step, but I'm too lazy to change it. :) The GitBranch() function (with other git capabilities) is provided by the git.vim plugin. There's a bug in it as noted here and I use the fork with the bug fix. However, I'm leaving both links and the blog here to give credit to all.

Also, note that I use a dark background, so you might have to change the colours around a bit if you are using a light scheme (and also to suit your tastes).

like image 84
abcd Avatar answered Sep 20 '22 16:09

abcd


Better, more general answer:

Use countCtrl+wCtrl+w to jump to the count window below/right of the current one.

For example, if you're in the top left of a 3x3 grid and want to jump to the bottom left you'd use 7Ctrl+wCtrl+w.

Specific 3x3 grid answer:

If you're always using a 3x3 layout you could try these mappings for the numpad, which always jump to the top left and then move the appropriate amount from there, with the key's position on the keypad jumping to the window's with 'equivalent' position on the screen:

noremap <k7> 1<c-w><c-w>
noremap <k8> 2<c-w><c-w>
noremap <k9> 3<c-w><c-w>
noremap <k4> 4<c-w><c-w>
noremap <k5> 5<c-w><c-w>
noremap <k6> 6<c-w><c-w>
noremap <k1> 7<c-w><c-w>
noremap <k2> 8<c-w><c-w>
noremap <k3> <c-w>b

Edited: turns out c-w c-w goes to the top left at the start automatically. The explicit 1 is required in the first mapping, as c-w c-w without a count toggles between the current and the previously selected window.

(The Ctrl-W t mapping always goes to the top-left most window, the Ctrl-W b mapping always goes to the bottom-rightmost).

Alternatively you could map each number to jump to the Nth window, so k6 would be 6 c-w c-w, rather than trying to lay out the keys as on screen.

like image 30
actionshrimp Avatar answered Sep 16 '22 16:09

actionshrimp