Just over 5 years ago, I spent a month learning and using Vim. Ultimately, I went back to Sublime Text with an occasional dalliance with VSCode.
I don’t know what sparked it. But I somehow found myself back trying Vim in September 2019. Here I am. About a month later and I’m feeling pretty content in Vim-land.
Not sure why I am happy with Vim this time around. Has Vim changed? Have I?
I certainly believe that this time around I was ready to have a ‘beginners mind’ and embrace the Vim way.
The biggest mistake I probably made originally was trying to make Vim be like Sublime/VSCode. This time around I have made a conscious effort to do things in a manner Vim intended. Let me try to substantiate that nebulous claim:
Knowing where I am in a file is different in Vim land. It’s done by looking at a percentage amount in the status bar. Or, in my case, a percentage value displayed in the Airline plugin to the bottom right of the Vim window. This percentage value is shown alongside the current line and column number. For example,
91% 11/12 :237 tells me I am 91% down the file on line 11 of 12 and currently on column number 237.
That’s very different than Sublime’s mini-map where you get a visual sense of the code and your position in it. Not as fancy, but Vim still gives me what I need. In short order my brain has adapted and I’m not missing the mini-map.
Another example is multiple-cursors. There is no direct native analogue to that in Vim. However, there are certainly ways to achieve the same goal.
Suppose we have a list of 10 lines of text that we want to wrap in HTML tags; let’s add a class name at the same time. In Sublime, we might hold down the relevant key and drag down the edge of the text in question with the cursor, type our beginning tag e.g.
<div class="thing"> then press the relevant ‘super’ key and end-of-line key combo shortcut to place all cursors at the end of the line, type our closing tag and then press escape to exit multi-cursor mode.
One way to achieve the same result in Vim would be:
<C-V> to enter visual block mode
10j$ to select the 10 lines we want to operate on and select to the end of each line
S to enter Surround
Type the tag
Same result. Both techniques require some practice. Having done both I think there is little between them.
The one benefit Vim has is that it’s a language, which, when you know it even a little, you can kind of think about how you would express on operation by using the correct nouns and verbs to Vim. Expressing yourself gets more and more powerful and there is a smug satisfaction that comes from the moment when you think of a problem, and ponder, “I wonder if…” and the noun/verb combo you enter does exactly what you hope it would. Achievement unlocked!
Another example of embracing the Vim way is spell checking. It lacks some of the visual niceties of modern editors but it is rapid and functional.
Vim has spell checking built in. You just need to enable it. You can also limit it to certain languages if you like. When enabled, mis-spelled words get an underline.
[s takes you to a previous error.
]s takes you to the next. When you land on one,
z= brings up the list of suggestions. Press the number of the one you want, press enter and it is corrected. Need to add a word to the dictionary?
zg adds the current spelling to the dictionary.
This lacks a fancy graphical pop-up but it’s very fast; no mouse === more speed!
Vim and the eco-system in 2019
In terms of Vim and its eco-system, that’s improved subtly but greatly in the intervening years.
NeoVim > Vim, init.vim > .vimrc
NeoVim is a modern re-thinking of Vim. I’ve been watching NeoVim for a few years. This time out, opting for it over the standard Vim seemed like a no-brainer. Install was straightforward enough and the only real difference is that user preferences are managed in a init.vim file instead of a
From my humble point of view, the sign of a mature Vim user is a stable
.vimrc/init.vim file. I wouldn’t say mine is entirely stable but I’m certainly no longer updating it on an hourly basis as I was in the first few days. Mine is here: https://gist.github.com/benfrain/4fe3aa3f54101d4565911998218ed724
I’m not going through everything in there but I will call out some of the feature plugins that deserve special mention.
Getting around, opening files etc
The short answer to this problem is 3 letters long: FZF. Install this for both Terminal and Vim then you get a blazing fast fuzzy finder. I have it set so that
<CTRL>-p opens the pane, along with a little preview window of the files as you tab through them.
I also use FZF as the manner I navigate buffers (think of buffers as tabs in standard editor parlance). I have
<Leader>-b mapped to open a the FZF drawer with my buffers listed. Typing the appropriate number and enter and I’m in.
Airline has been around for years and there are a few lighter alternatives available. Eleline and Lightline come to mind. However, I have Airline doing exactly what I need currently so for once I have ‘left well alone’.
Code completion and linting
Another three letter answer to this problem: COC. Conquerer Of Completion is essentially the engine that runs code completion in VSCode. It works like a dream in Vim; you get everything you would get in VSCode. Simply install the relevant language packs with
:CocInstall and the relevant completion is installed. So, say I wanted the HTML completion, I can just enter:
:CocInstall coc-html from normal mode and the HTML completion is installed.
In the past, the code completion in Vim didn’t quite work and I remember a bunch of faff getting it to work as I would expect (coming from Sublime). No such problem here. It works perfectly.
Linting for free
Because COC.vim is essentially the VSCode completion and language server, you also get linting out of the box. The same error warnings you’d get in VSCode are here in Vim too.
Sublime Text has long had good Markdown editing tools. I’ve adopted Goyo and the associated Limelight for this job. Not only do you get a nice central editing experience with distractions such as Airline removed. Limelight also provides a highlight for the paragraph you are writing in whilst others are dimmed.
I use the Nord colour scheme and there is a great version for iTerm2. https://github.com/arcticicestudio/nord-iterm2.
There is also an accompanying Nord theme for Vim (grab it from the aforementioned init.vim) which I love.
By the way, if you want a bumper pack of different colour schemes for iTerm, head over to https://github.com/mbadolato/iTerm2-Color-Schemes
Finally, on the subject of pimping iTerm in general, Stefan Judis has a good post on the subject: https://www.stefanjudis.com/blog/declutter-emojify-and-prettify-your-iterm2-terminal/.
I’ve been playing with and learning SwiftUI lately and the single biggest frustration I have is that there is no auto-format option in Xcode (you can select-all and press CTRL+i though). Thankfully, in web development land we have Prettier. It’s just a plugin away in Vim land too. Thank. Goodness!
Fonts and ligatures
Ligatures: some people love them, some hate them. Personally, I am a fan. However, as I work via iTerm and iTerm advises they prevent GPU acceleration I have them disabled. But they are there if you want them. In iTerm at least!
Start (Neo)Vim with an application
Here is the scenario. You are looking at a JS file in the Finder of macOS and want to open it in Vim. Ordinarily, you would head to the Terminal, start up Vim and run
: edit with the path to the file in question (perhaps you drag in the location from the Finder to speed things up).
There is another way. You can use AppleScript to make an ‘App’ of Vim. It’s a 5-minute copy and paste job. I tried a few tutorials but the one that worked for me with NeoVim was this one: https://gregrs-uk.github.io/2018–11–01/open-files-neovim-iterm2-macos-finder/. Now you can open files directly in Vim from the Finder. The only piece of the puzzle I have yet to crack is how to get that file opened as another buffer of an existing Vim instance.
Saving and restoring sessions
Once thing I have always loved about Sublime is that you can open it and it restores the project you are working on. Turns out this is simple in Vim too. Here are the relevant functions lifted from my init.vim file. Apologies, but I can’t remember to who credit for these functions should be accredited!
function! MakeSession() let b:sessiondir = $HOME . "/.config/nvim/sessions" . getcwd() if (filewritable(b:sessiondir) != 2) exe 'silent !mkdir -p ' b:sessiondir redraw! endif let b:filename = b:sessiondir . '/session.vim' exe "mksession! " . b:filename endfunction function! LoadSession() let b:sessiondir = $HOME . "/.config/nvim/sessions" . getcwd() let b:sessionfile = b:sessiondir . "/session.vim" if (filereadable(b:sessionfile)) exe 'source ' b:sessionfile else echo "No session loaded." endif endfunction " Controls the open/close Vim functions augroup vimSessions autocmd! " Adding automatons for when entering or leaving Vim au VimEnter * nested :call LoadSession() au VimLeave * :call MakeSession() augroup END
I still can’t do project wide search and replace
One thing I still miss is the peerless search and replace functionality of Sublime Text. I’m going to be kinder on myself this time around. For the odd times I need to do that, at least to begin with, I’m going to do it with Sublime Text. I’m hoping in time I’ll move to doing it with Vim, with what currently still seems like largely unintelligible gibberish!
How long will my new found harmony with Vim last? Who knows. The only thing I can tell you right now is that I’m enjoying it and feel productive with it.
There’s more plugins available to make front-end coding in Vim more pleasurable than ever before.
Oh, and I’m regretting selling that Happy Hacking Pro 2 keyboard I sold back in 2015 🙁