0

I'm kind of fine with moving across windows using Ctrl+w followed by (sometimes a counter and) h, j, k, l, p, t, b, and I'm also fine with the similar key combinations to split the windows or to move or rotate them, but repeating the Ctrl+w everytime is a bit annoying.

Therefore I was thinking of writing some mapping to create a kind of "move-across-windows pseudo-mode" which should make things easier. Specifically I was thinking of mapping Ctrl+w such that it somehow

  1. "hides" all the existing mappings and keys (I don't say un-mapping because that would require recovering all the mappings afterward),
  2. maps those letters above to themselves preceded by Ctrl+w,
  3. maps the Escape key to undo what is done in 1. and 2.

Before diving in, however, I'd like to know if a plugin already exists that allows something along these lines.

I've written a plugin for this: WinZoZ

3 Answers 3

2

The typical ways to have sub modes:

  • be in a buffer with dedicated <buffer> local mappings
  • or enter a loop where we read key pressed and act accordingly.

The second point is more likely to correspond to what you're looking for:

  1. enter the windows navigation mode
  2. navigate
  3. exit

It's implemented by waiting on getchar(). And we can even provide a dedicated status line. Here is an example I have in lh-brackets:

if !hasmapto('BracketsManipMode')
    nnoremap <silent> <M-b>     :call BracketsManipMode("\<M-b>")<cr>
endif

function! BracketsManipMode(starting_key) " {{{
  redraw! " clear the msg line
  echohl StatusLineNC
  echo "\r-- brackets manipulation mode (x ( [ { < ' \" ` \\ <F1> q)"
  echohl None
  let key = getchar()
  let bracketsManip=nr2char(key)
  if (-1 != stridx("x".join(keys(s:k_pairs), '')."\\q",bracketsManip)) ||
        \ (key =~ "\\(\<F1>\\|\<Del>\\)")
    if     bracketsManip == "x"      || key == "\<Del>"
      call s:DeleteBrackets()    | redraw! | return ''
    elseif bracketsManip == "\\" | call s:ToggleBackslash()
    elseif has_key(s:k_pairs, bracketsManip)
      call s:ChangeTo(s:k_pairs[bracketsManip])
    elseif key == "\<F1>"
      redraw! " clear the msg line
      echo "\r *x* -- delete the current brackets pair\n"
      echo " *(* -- change the current brackets pair to round brackets ()\n"
      echo " *[* -- change the current brackets pair to square brackets []\n"
      echo " *{* -- change the current brackets pair to curly brackets {}\n"
      echo " *<* -- change the current brackets pair to angle brackets <>\n"
      echo " *'* -- change the current brackets pair to single quotes ''\n"
      echo " *\"* -- change the current brackets pair to double quotes \"\"\n"
      echo " *`* -- change the current brackets pair to back quotes ''\n"
      echo " *\\* -- toggle a backslash before the current brackets pair\n"
      echo " *q* -- quit the mode\n"
      continue
    elseif bracketsManip == "q"
      redraw! " clear the msg line
      return ''
      " else
    endif
    redraw! " clear the msg line
  else
    redraw! " clear the msg line
    return a:starting_key.bracketsManip
  endif
endfunction " }}}

Note: it deserved to be modernized: moved to an autoload plugin, annotated with abort...

1
  • I've created a small plugin for that. Would you like to review it here?
    – Enlico
    Commented Oct 28, 2020 at 21:22
2

At one point I had mapped <leader>w to <C-w>, but I found I didn't like that (occasionally I use vim's that aren't configured like mine, and that habit made doing so annoying.)

I do have winresizer installed, though to be honest I rarely use it these days. You can setup a shortcut (<C-e> by default) to enter rezise mode, where hjkl resize windows. There is also a focus mode, where you switch windows, and a move mode, where you move them around. You typically have to "accept" or "deny" the changes after you've made them (<enter> or q/<esc>, though you can configure <esc> to accept instead). This only applies to resize mode, as far as I can tell, though it might not be hard to make it apply to the other modes, if you were in the mood to do so.

2
1

A slightly different approach is to set up <Tab> to jump from one window to the next. If you don't have too many windows open, hitting <Tab> a few times is quicker than pretty much any other sequence of keys.

nnoremap <Tab> <C-W>w
nnoremap <S-Tab> <C-W>W

For when there are lots of windows, I use <Leader>n, where n is the window number (displayed in the status line), to jump directly to the desired window. Add this to your vimrc to set it up:

for i in range(1, 9)
  execute 'nnoremap <Leader>'.i.' :'.i.'wincmd w<CR>'
endfor

And also <Leader>0 to jump back to the previous window:

nnoremap <Leader>0 :wincmd p

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.