" Navigation Enhancer v2.0 by joey.neuralyte.org " " aka Retrace Your Steps " " When moving the cursor between windows, given a choice of target windows, " Vim normally uses the *cursor position* to choose the destination window. " " However I think a more intuitive approach when there may be more than one " potential target window is to pick the one which was *used most recently*. " " Or perhaps more accurately, we want the window that we *last entered from, in " that direction*. " " So now if I casually move between windows in one direction, and then in the " opposite direction, I should always return to the window I started from! " BUG: When you split a window, it may cause the numbers of other windows to " change! "" Override Vim's default keymaps for window navigation: noremap k :call SeekBestWindow("k","j") noremap j :call SeekBestWindow("j","k") noremap h :call SeekBestWindow("h","l") noremap l :call SeekBestWindow("l","h") "" I also like them to work in Insert mode! inoremap k :call SeekBestWindow("k","j")a inoremap j :call SeekBestWindow("j","k")a inoremap h :call SeekBestWindow("h","l")a inoremap l :call SeekBestWindow("l","h")a "" You may also use /// "" Warning: these may conflict with other plugins, e.g. windows_remember_size.vim map k map j map h map l imap k imap j imap h imap l "" Also in GVim, we need to re-load joeykeymap.vim to get etc. calling "" the script binds above. "" Or leave the defaults unchanged, and instead override my preferred shortcuts: "" This became a pain when my compatibility mappings were intercepting these, "" so I tried to unmap all my shortcuts. " silent! unmap " silent! unmap " silent! unmap " silent! unmap " silent! iunmap " silent! iunmap " silent! iunmap " silent! iunmap "" Problem: We must unmap these or C-Up mapping fails in xterms. "" But then we should re-map them for terms which recognise them only! " silent! unmap  " silent! unmap  " silent! unmap  " silent! unmap  " noremap :call SeekBestWindow("k","j") " inoremap :call SeekBestWindow("k","j")a " noremap :call SeekBestWindow("j","k") " inoremap :call SeekBestWindow("j","k")a " noremap :call SeekBestWindow("h","l") " inoremap :call SeekBestWindow("h","l")a " noremap :call SeekBestWindow("l","h") " inoremap :call SeekBestWindow("l","h")a function! s:SeekBestWindow(realDirection,reverseDirection) " User has requested travel in realDirection, and reverseDirection should be " the opposite of that. let l:startWin = winnr() let l:moveDone = 0 if exists("w:lastWinInDir_".a:realDirection) let l:targetWin = eval("w:lastWinInDir_".a:realDirection) " echo "Last window from that direction was ".l:targetWin if l:targetWin == l:startWin " Window numbers have become confused. This move is no use! else " Go to the recommended target window noautocmd exec l:targetWin."wincmd w" " Check that this movement is still valid " We do that by moving back again, and seeing if we get back where we " started from. noautocmd exec "wincmd ".a:reverseDirection if winnr() == l:startWin " Yes this move is fine exec l:targetWin."wincmd w" let l:moveDone = 1 else " No this move might not be valid! " (This could be caused by window layout having changed.) " Or it might be a valid move, but on the way back Vim would naturally " pick a different route. In that case, travelling *this way* is " probably trivial, and we can let Vim do it normally. " echo "We may no longer reach ".l:targetWin." from here!" noautocmd exec l:startWin."wincmd w" endif endif endif if !l:moveDone " echo "Doing normal move" exec "wincmd ".a:realDirection endif " Record the route back (but not if we didn't actually move!) if winnr() != l:startWin exec "let w:lastWinInDir_".a:reverseDirection." = ".l:startWin endif endfunction