Skip to content

Instantly share code, notes, and snippets.

@mheiber
Last active November 9, 2022 23:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mheiber/c5be4474a5a5356c767d5b87663aebb1 to your computer and use it in GitHub Desktop.
Save mheiber/c5be4474a5a5356c767d5b87663aebb1 to your computer and use it in GitHub Desktop.

Vim Advice

For best efficiency: Keep the Bindings, Leave the Editor

Most of the efficiency and joy of Vim is in the keybindings. All popular editors have Vim bindings. When first learning (and after), one can spare oneself a lot of pain by just focusing on the bindings.

The key idea is:

  • "insert mode" is for inserting text, and that is all.
  • "normal mode" is for navigating and manipulating code. Then all the keys can be used for useful things besides inserting text. What keys do is based mostly on easy-to-reachness and menmonics.

I recommend:

  • Vim tutor sections 1 through 4 (open vim and type :Tutor and press return/enter). This is helpful even if you don't plan to use actual Vim.
  • Then straight-up memorize the cheat sheet: https://bamanzi.github.io/scrapbook/data/20110925162521/. It's not much to memorize, and most bindings have nice mnemonics like b=back, e=end, n=next, p=paste, y=yank etc. Many things in the cheat sheet will have to be Googled to understand how they work; such as visual mode, macros, and marks.
  • map jk to <Esc> in insert mode so you don't have to reach for the escape key (Google how to do this for your editor). jk is a good choice because it's idempotent. Also, the following technique works in interview sites like coderpad.io and LeetCode, too, so you can rely on this way of escaping even in hostile environments: :imap jk <Esc>

There are a few keybindings that are de-facto "vim bindings" even though vim users get them from plugins: vim-surround (ci( to replace the text inside parentheses, for example) and vim-commentary (gc to comment a line of code, for example). The IntellIJ and VSCode Vim plugins/extensions either have these bindings by default or have them behind a flag, and they are essential for efficient code editing with vim bindings.

Warning for Windows users: You'll have to tell your editor when to send CTRL to the Vim emulation and when to have the editor do what it would normally do with CTRL. At the beginning the most important CTRL binding to let the Vim emulation handle is CTRL-R (redo).

Bonus: Once you've memorized the bindings, more efficiency and joy can come from composing them well. "Practical Vim" can help with this composition: https://www.amazon.com/Practical-Vim-Edit-Speed-Thought-ebook/dp/B018T6ZVPK/ref=sr_1_2?crid=B3ZSQ3FSNCUI&dchild=1&keywords=practical+vim&qid=1634066429&sprefix=practical+vim%2Caps%2C229&sr=8-2. You can preview the book before buying using Libgen.

Once one learns Vim keybindings, one must ask oneself: is it worth it to use Actual Vim? The answer is no. Vim is a time sink because it is broken out of the box by modern editor standards. Crafting a vimrc is (I imagine) like tending a bonsai tree over years: only do it if twaking a config file and using a half-broken editor sounds like a good use of your time on Earth. I've really enjoyed the time waste, but it is not justifiable if one's primary concern is efficiency.

Down the Rabbit Hole

Assuming you've learned Vim bindings and decided building your own usable editor out of Vim is your new hobby, the following are some tips. These tips are a combination of:

  • minimum needed to avoid pain
  • some tips I didn't see elsewhere that worked well for me

To easily get high-quality code actions, completions, go-to-definition, project-level-renaming for multiple programming languages, the only way I know of is by using Neovim and coc.nvim. Neovim is a fork of Vim. Built-in LSP in Neovim is not as useful as coc.nvim imo, see coc.nvim docs for the difference.

Additional plugins for a minimally-OK experience:

There are several plugin managers. I use Plug but suspect they all do roughly the same thing: download vim files based on a GitHub URI.

Some people will say that no plugins are necessary and that Vim has everything built-in. While everything can theoretically be done with stock Vim, it will be done slower and not as well. For example :find is not a suitable replacement for a fuzzy finder for languages that reuse file names frequently (or for large codebases).

Vim's alternatives to tabs are perhaps the best feature of Vim aside from bindings and programmability, and it's worth the time to use them well.

  • use buffers instead of tabs for files. A buffer is an in-memory representation of the contents of a file.
  • "split", "window", and "pane" are three words for the same thing.:vs splits the pane/window. :help window for more.
  • :b any_part_of_a_buffer_name switches to the buffer. This is one of Vim's most powerful features and seems to be underused. This only works well when you don't have many buffers open with similar names.
  • Add this to your vimrc: cnoremap <expr> %% getcmdtype() == ':' ? expand('%:h').'/' : '%%'. Then, to edit a file next to the one you're editing, do :e %%, hit tab, then use the completions to find your file. This is a tip from "Practical Vim".
  • use tabs only for workspaces. :tcd directory_name sets the working directory for a tab. I don't use tabs ever anymore. Things like :b fragment_of_file_name are not tab-aware. I use tmux windows for workspaces.

Some limitations and warnings:

  • Fine-grained regex-powered search is easier in VSCode. I still switch to VSCode for non-trivial searches when I want to filter files carefully. I got better with vim-ripgrep and don't usually need to do this anymore
  • Now matter how much config you throw at the problem, Vim won't really do auto-save, so abandon hope for auto-save.
    • update, it's pretty good now, vitality.vim works well in conjunction with tweaks to tmux config. Rabbit hole.
  • Strenuously avoid mapping keys in a way that shadows built-in Vim funtionality. For example, a lot of people map comma to something else, but the built-in comma command is incredibly useful in conjunction with f (find-in-line), see :help ,.
  • Getting Vim or Neovim's integrated terminal to work better than Vim+tmux might not be possible, at least not with massive time investment. It's hard to get the keybindings right, and hard to avoid vim-ception when you want to edit something in Vim in the directory in which you have the terminal or do things like edit commit messages. Instead, if you are used to an integrated editor:
    • Start a tmux session, then start Vim from the tmux session. Set up tmux with vim-like keybindings, such as binding h to switch to the left pane, j to the bottom pane, etc.. I usually keep a few Tmux panes under Vim. I put this shortcut in my .tmux.conf to hide these plain terminal splits quickly: bind-key f select-pane -U\; resize-pane -Z. This switches to the upper pane and zooms in.

And one more thing: VimScript is actually not bad for little customizations and can be a fun way to add new functionality without writing much code. For example, I really wanted a visual indication of location in a file without wasting space, and it took only a few lines of code.

Also, again, it's not worth it, other editors are probably more efficient even after years of artisanal vimrc crafting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment