Vim

For most text editing and programming tasks, I use Vim. I started using it around 2011 as my first “serious” text editor, and although I sometimes use and have experimented with others (e.g. Emacs), I haven’t really felt a desire to switch.

This page documents some of my musings from using Vim; most of it has probably already been said elsewhere.

I probably spend too much time configuring Vim. I am well past the point where configuring and installing new plugins for Vim pays off in terms of increased productivity. I’ve been trying to cut down on configuration, but find myself doing it anyway because I find it relaxing.

You can see my current vimrc in my dotfiles repository.

You can also see my contributions to the Vim Tips Wiki.

:g-based folding

It’s certainly possible to use something like nelstrom/vim-markdown-folding to get proper folding in Vim. But what if one is on a remote machine, for instance? It’s always useful to know efficient ways to work in Vim even when one does not have access to one’s accustomed plugins. Here’s a cool way to navigate a long markdown document, assuming all headers begin with #. It’s possible to use :g/pattern to search for an expression in the current buffer and print the results. For markdown files, just type :g/^# to see all headers, for instance. Then, once one has found the heading one was looking for, note the line number (say, 10) and then type :10<CR> to get there.

To generate the headings in a new split window, do something like this:

:redir @a
:silent global/^#/print
:redir END
:vnew | put a
:g/^$/d

Then save it in a file and :source it, or yank it and execute with @". You can also view the output at any time without putting it in a new window using :echo @a. For some reason, chaining the above commands like

:redir @a | silent global/^#/print | redir END

only captures the first line of output from the :global command. I think it’s because :global tries to use everything after it as the ex command it executes. Doing

:redir @a | silent global/^#/print \| redir END

seems to work.

Plugins or not?

Note, this section isn’t balanced.

Lately I’ve been thinking that it’s perhaps more desirable to simply learn Vim well instead of trying to customize Vim “needlessly”; are many plugins merely distractions? In other words, maybe relying so heavily on some Vim plugins might just be an indication that you don’t know Vim well. See for instance Kevin Beckford’s answer to Vim: How can I learn to write a vimrc?:

Preferentially, waste time reading how vim works, rather than scripting it. Vimscript is an interesting language, but I feel learning the options that would go into a .vimrc is more important.

Something like a “Unix philosophy for text editing”:

Or as roel_v points out on Hacker News:

I’ve used vim for coming on 15 years now, so I feel that I may qualify as ‘experienced’. My biggest productivity gain was giving up on endless customization after I had reached a certain proficiency (e.g., everything in the original article is rather basic vim usage) and comfortable workflow for specific development purposes (e.g. when switching to a new language, I spend some time setting vim up to solve the most glaring pain points and once it feels comfortable, I stop customizing). All the mucking about with various baroque plugins and ever-more-marginal keystroke-saving key mappings costs a lot more time than what can be gained from it. For example, I used to have a bunch of mappings that would insert documentation blocks in various forms. Just misremembering the mapping once a day causes enough workflow disruption to undo any gains from having them in the first place. Nowadays I just type comments / docblocks by hand. It’s a few more keystrokes, but a lot more natural and flexible.

Also, staying as close as possible to the default settings makes it a lot easier to move to other environments and/or upgrade. Although now that I have my .vimrc in my Dropbox it doesn’t matter as much as it used to.

Another “essence” of Vim, as Tim Pope says:

Don’t use a map when a command will do. Vim doesn’t even have a map for :write.

Though maybe the most important metric is: if adding a new feature slows down your text editor, you have to think: does having this feature speed me up enough that the slower editor is still better than not having that feature? I do think that having some mappings (like jj and kk to escape from insert mode) really do increase my editing speed. The same argument could be made for some plugins like vim-fugitive.

See also the “light” versus “dark” distinction explained in Sharpen your Vim with snippets.

See also “On sharpening the saw”, which pushes for learning the base Vim really well, but also accepting plugins that extend Vim in a way Vim was “meant to be” (e.g. surround.vim, fugitive.vim, etc., are all “Vimlike” plugins).

Small things

Working with long lines

Details about working with long lines are covered in “Working with long lines” on the Vim Tips Wiki, which I wrote.

Here are some other details that I didn’t want to cover on that page, especially with regard to the point “Giving up on Vim for these files and using editors that work fine with long lines (gedit, GNU Emacs, etc.)”.

In editing Wikipedia, I’ve found it useful to learn CUA keybindings like Ctrl-, Ctrl-Backspace, and so forth, which can be used directly on browsers like Firefox. This suffices for most editing tasks, and I have the extension It’s All Text! installed and set up to open GVim for more complicated tasks (like search-and-replace), where dealing with long lines in Vim is preferable to dealing with such tasks in the browser’s text field. I’ve also found Emacs useful (with a bit of practice) if I am dealing with a file that neither Vim nor a CUA editor can easily deal with.

From my old .vimrc

It’s sometimes interesting to read my old .vimrc to note things that I used to accomplish in a really convoluted manner (and which sometimes Vim did natively!). Here I want to list some of these.

set list listchars=eol:$,extends:>,precedes:<,nbsp:_,tab:>-,trail:@

I used to have extends and precedes, although I later realized I didn’t really like them for the following reason: When editing long lines, these hide the first character of each visual line, making the text difficult to read. I also switched tab to >\  (i.e. greater than, backslash, space), which, when combined with a ctermbg highlight color, makes it possible to see the spaces.

Next, I used to have several lines like the following to help automate LateX document compilation:

autocmd filetype tex nnoremap <buffer> <silent> <localleader><localleader> :!latexmk -pdf %<CR>

But Vim already has :make, which is more versatile anyway, and doesn’t require configuration for each filetype.

I used to set manual abbreviations like the following to help with typos:

iabbrev adn and
iabbrev nad and
iabbrev teh the
iabbrev het the
iabbrev ehty they
iabbrev hety they
iabbrev tehn then
iabbrev waht what
iabbrev THen Then

But Vim has the much more general <C-x>s, which, combined with other types of autocompletion, becomes incredibly powerful.

Also in general I used to have a lot more lines in my .vimrc, many of which I couldn’t be bothered to memorize.

I used to also have:

nnoremap <silent> <C-n> :tabn<CR>
nnoremap <silent> <C-p> :tabp<CR>

This is fine, but I mostly needed to quickly switch between tabs because I was using them instead of buffers. In other words, I was unable to think of editing buffers in a “Vim mindset”, which caused me to treat tabs in a naive manner. See this answer as well as this question for more.

Also mappings like:

nnoremap <silent> <leader>nh :nohlsearch<CR>
nnoremap <silent> <leader>I :set list!<CR>
nnoremap <silent> <leader>N :set number!<CR>
nnoremap <leader>p :set paste! paste?<CR>

These show that I was unaware of unimpaired.vim.

I also had a habit of adding new plugins almost by whim, which may have been a positive thing (in that I was able to experiment with more possible editing workflows) but ended up not really being necessary, and also discouraged me from actually learning Vim—because why read through the help pages when a flashy plugin will solve my problem?

Right now my approach consists of (1) not creating new mappings to solve problems for me (cf. the Tim Pope quote above); (2) not making any changes to my configuration that would require different “muscle memory” from the default Vim/Neovim configuration—to quote Tim Pope again, I want to keep my changes in configuration to those which are a “cosmetic improvement with no impact on muscle memory”. In fact both (1) and (2) have a lot in common, and (2) might be construed as a more general formulation of (1).

I used to do gg"+yG``, when the ex-mode :%y + is much simpler.

Syntax files

Vim syntax files seem to have the problem of either coloring things incorrectly (often happens with complicated or nested structures in Markdown or LaTeX), or, even when syntactically correct, overzealously. There isn’t much point in coloring most things on the screen because that just makes it difficult to distinguish parts.

In markup languages, the two most important parts of syntax coloring are the following:

I take some inspiration from Vim’s own mail.vim, which is both helpful (in coloring URLs and not spell-checking within them) and unobtrusive (by not even distinguishing common markup for e.g. *emphasis*).

Note that Hacker News also has a very minimal markup that only converts code blocks (but not inline code!), italics, and URLs. Facebook messaging and posts also have limited formatting options, where URLs and certain other text (phone numbers, dollar amounts, @dailycute, @-mentions, names of people, etc.) are detected.

Do we see this trend only in markup languages, or also in programming languages? One point to consider is that in programming, indentation either does not matter (e.g. C) or it does not affect the highlighting (e.g. with Python, indentation matters, but one can always ignore all the current level of indentation and color as if the text is at the outermost level of indentation (?)). In contrast, Markdown makes heavy use of indentation to affect meaning and the coloring must be aware of this (e.g. to understand that one is in or not in a codeblock or blockquote); indeed, some markup languages like TeX allow the user to arbitrarily redefine the language (commonly seen with \makeatletter and \makeatother). Another difficulty with Markdown is the lack of standardization, which makes the coloring correct under some implementations but not others. Escaping methods might also be worth considering. Markdown code can take \(n\) backticks to include \(n-1\) backticks inside the code. This makes the source easier to read for a human, but for syntax highlighting, it’s easier to deal with one-off backslash escapes favored in languages like Python (since there is less context to maintain).

Using alternative Vim setups

Sometimes when I am editing a quick file, I don’t want to load all my plugins and custom setup (especially YCM – although vim-plug might have a way to speed this up that I’m not aware of), as that results in a slow startup that I don’t want to bother to wait for. I also like to experiment with radically different Vim configurations sometimes In these cases, it can be useful to have an alternative Vim setup, sort of like a second ~/.vim path, or an option like -u that also changes the .vim directory to something else. Here I change it to ~/.alt-vim.

First, from http://superuser.com/questions/561434/telling-vim-to-use-custom-vimrc-is-easy-but-how-to-tell-it-to-use-alternative, I have the following in my ~/.zshrc:

alias avim='vim --cmd '"'"'let &rtp = substitute(&rtp, $HOME."/\\.vim", $HOME."/.alt-vim", "g")'"'"' -Nu /home/issa/.alt-vim/init.vim'

I might change it to a shell script later, so I don’t have to deal with the nested quotes. The basic idea is to invoke Vim with:

vim --cmd 'let &rtp = substitute(&rtp, $HOME."/\\.vim", $HOME."/.alt-vim", "g")' -Nu $HOME/.alt-vim/init.vim

This sets both the vimrc as well as the runtime path, which controls where Vim searches for plugins. (Question: Does this use the same or different viminfo?) I’m also not sure why the above expression uses \. instead of just . (this is because in substitute, Vim interprets the second argument as a pattern rather than a verbatim string; note that because we are using double quote strings, we must use two backslashes to escape the dot).

Then I have in init.vim (after installing vim-plug – see below):

call plug#begin('~/.alt-vim/plugged')
Plug 'nelstrom/vim-visual-star-search'
Plug 'tpope/vim-abolish'
Plug 'tpope/vim-characterize'
Plug 'tpope/vim-commentary'
Plug 'tpope/vim-fugitive'
Plug 'tpope/vim-repeat'
Plug 'tpope/vim-speeddating'
Plug 'tpope/vim-surround'
Plug 'tpope/vim-unimpaired'
call plug#end()

source /home/issa/sensible.vim

where sensible.vim is just sensible.vim.

I also ran (prior to making init.vim):

curl -fLo ~/.alt-vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

which installs vim-plug.

Now all that is left is to run :PlugInstall from Vim to install the plugins.

Other problems

Despite using Vim for almost everything, I still have some problems with it:

Things to check in Neovim (or, the list of things that make me wary to switch to Neovim, and which I should check back on with Neovim because at some point the benefits may outweigh the costs):

Some intuitions

I began using Vim at the latest in the summer of 2011. In the course of 6+ years of using Vim, I’ve developed some intuitions; most of these I’ve only been able to articulate in the past year or so.

See also