Comma mode for vim

Most keyboards have a Control and Meta key. Macs also have the Command key. Even with all the combinations of Control and Meta and Command with the letters and numbers, it’s sometimes hard to have enough space for keyboard shortcuts that don’t conflict and override each other. This is especially important in vim, where keyboard shortcuts are everything. Most of the good ones are taken already.

My keybindings

I adapted an idea from tinymode.vim and created another key modifier: the comma. Here are some of the keybindings I’ve set:

  • ,v creates a vertical split
  • ,t opens a new tab
  • ,1 toggles line wrapping
  • ,2 opens NERDTree
  • ,0 enables spellcheck and textwidth
  • ,q quits the current buffer
  • ,b opens CtrlP in buffer mode
  • ,c opens the cd prompt
  • ,f opens the filetype prompt
  • ,U toggles line numbers

The comma works just like Control or Meta. You can hold it down and press multiple keyboard shortcuts. For example, multiple q’s can be chained to close multiple buffers in succession. Or t and v can be chained to create a new 2-pane tab.

Configuration

These six lines form the core of comma mode:

nmap , :set timeoutlen=86400000<CR><SID>ldr
vmap , :set timeoutlen=86400000<CR><SID>ldr
nn <script> <SID>ldr, <SID>ldr
vn <script> <SID>ldr, <SID>ldr
nmap <SID>ldr :set timeoutlen=1000<CR>
vmap <SID>ldr :set timeoutlen=1000<CR>

Pressing the comma key will 1) set the key combination delay to an absurdly long time, and 2) set up the <SID>ldr keyword for the following comma command. Vim provides <SID> as a script-local unique identifier to help you avoid naming conflicts.

Chainable commands

Once comma mode is set up, you can add chainable commands. These commands can be chained together with other comma commands in succession.

nn <script> <SID>ldr1 :set wrap!<CR><SID>ldr
vn <script> <SID>ldr1 :set wrap!<CR><SID>ldr

Everything after the first <SID>ldr is the comma keybinding. In this case, just the number 1. An arbitrary command is run, and then the line ends with <SID>ldr to set up chaining for the next command.

Non-chainable commands

You can also add non-chainable commands. These are useful for comma shortcuts that open prompts, which you would never use with other comma shortcuts.

nn <script> <SID>ldrc :set timeoutlen=1000<CR>:cd 
vn <script> <SID>ldrc :set timeoutlen=1000<CR>:cd

There’s an invisible space at the end of these two lines, so the prompt is ready to accept a path. Non-chainable commands reset the timeoutlen to a default 1000. This is the same behavior as the null binding (the last two lines of the Configuration section), which runs when you run a non-existent comma command, or press ESC in comma mode.

Conclusion

Comma mode has been the #1 most productivity-boosting featured I’ve added to vim. Mapping semicolon to colon is a start, but it only takes :q from 4 keystrokes to 3 keystrokes (including the Enter key). With comma mode, this is now just 2 keystrokes — just the way keyboard shortcuts should be.