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.

Airline showing the current cursor position

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 <div class="thing">

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!

Spell checking

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.

Vim highlighting spelling errors

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 .vimrc file.

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.

FZF plugin showing file matches and a preview

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 showing the current cursor position FZF showing buffers to choose from

Airline

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

COC.vim showing possible completions

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.

cos.vim showing a CSS error

Writing/markdown editing

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.

Goyo showing a highlighted paragraph of markdown

Colour schemes

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/.

Prettier

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 replaceUse Ripgrep for project-wide find 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!

Update 24.11.19: For the last few weeks I have been using ripgrep, for all my search and replace jobs. Whenever I want to find some random text string in my project, I can just type :Rg string-here and it is immediately found. Choosing an item from the list takes me not just to the file but the exact piece of text in that file. If you find yourself getting into this, I can recommend this tutorial on YouTube: https://nickjanetakis.com/blog/find-and-replace-text-in-1-or-more-files-using-vim-fzf-and-ripgrep

Summary

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 πŸ™