Thursday, January 19, 2012

One Key To Toggle Them All

...whether to paste or to nopaste, that is the quintain
Real estate in the Vim Keymap World is a bit sparse. Vim steals for itself nearly every sane key combination, leaving the paltry <leader> basement space for us lowly users to occupy. Vim does leave most of the Function Keys alone, though, making them a popular squatters choice in ~/.virmc . But there’s only twelve of them (on non superhero keyboards) so you don’t want to go wasting them either. The Vim docs (:help 'pastetoggle) suggest mapping <F10> to enable paste mode and <F11> to disable it. Meh. That’s TWO WHOLE F keys for one logical operation (and its inversion - its… toggle). Surely we can do better…
Paste Toggle on a Single Key
paste_toggle.vim
" Paste Toggle
" Barry Arthur, Jan 2012

" show paste toggle in insert mode
set showmode

" toggle (invert) the current paste state and show new state
function! PasteToggle()
  set invpaste
  set paste?
endfunction

" map for normal mode
nnoremap <F11> :call PasteToggle()<CR>

" map for visual mode
vnoremap <F11> :<c-u>call PasteToggle()<CR>gv

" insert mode handled by pastetoggle option
set pastetoggle=<f11>

Now we have paste toggle on a single key, working from most places you’d want it. Copy that code and put it in ~/.vim/plugin/paste_toggle.vim on linux and mac. On windows, copy it to $HOME/vimfiles/plugin/paste_toggle.vim. Make that path if you don’t already have it. Restart your vim and test your shiny new <F11> key in normal, visual and insert modes.Of course, you can make it any key you want instead of <F11>. Joy.

Thanks to osse for catching a silly bug on the vnoremap - forgetting to put <c-u> at the start of the map will cause the function to be called for each line currently selected - definitely not the behaviour we want here.

2 comments:

  1. Just set pastetoggle= is enough, you don't need your normal/visual/insert mode maps. Try it.

    ReplyDelete
    Replies
    1. Thank you for your feedback.

      While set pastetoggle= alone does provide the functionality of toggling paste in all modes, it only provides feedback in insert mode. The function provides feedback and the maps cater for the other modes.

      The insert mode map was redundant, so I removed that one.

      Apart from the purpose at hand, I showed this function with the combination of set inv and set ? together as a common idiom for toggling an option and showing its new state.

      Delete