Michael Anhari

Blogging with Vim

Laptop, coffee mug, legal pad, pen and phone sitting on a wooden desk.

Just thought I'd give a disclaimer here that I no longer blog in vim or use jekyll to power this site so a few examples like footnotes aren't operational as they once were, but the vast majority of this article should still be relevant if you're looking to go that route.

You may be surprised at how well you can make vim a comfortable setting for authoring blog posts or any prose for that matter. The following is how I've configured vim (well, neovim but that's another post altogether) for writing pieces other than code.

Building a blog for the command line and vim

For starters, I used jekyll – a ruby based static site generator – to build this blog and I host it via GitHub Pages. This allows me to make any changes to my site with a simple git commit and push. Jekyll really is an amazing tool once you learn your way around. I'm much less likely to reach for a database having learned its quirks and tricks. It makes creating a static site a breeze.

Blogging convenience methods

Out of the box, Jekyll lacks a few convenience methods for common blogging tasks. I recommend using the jekyll-compose gem, which gives you the following easy-to-remember methods that will make your life blogging from the command line much better:

draft      # Creates a new draft post with the given NAME
post       # Creates a new post with the given NAME
publish    # Moves a draft into the _posts directory and sets the date
unpublish  # Moves a post back into the _drafts directory
page       # Creates a new page with the given NAME

Drafts can be pushed up without showing up on your site, and can be previewed on localhost via jekyll serve --drafts.

Kramdown footnotes

While I write my blog posts in markdown, I've actually configured jekyll to use kramdown to get access to more functionality like footnotes.1

Now onto the actual vim related stuff!

Dictionary and Thesaurus

Two things people tend to use while writing are dictionaries and thesauruses. Let's get you set up so both are merely a leader key away.

Now, I'm afraid I this will only work for macOS because it uses Apple's dictionary app. If you are on a mac, the following command will look up the current word underneath your cursor in macOS' dictionary app like so:

" look up the word under the cursor in Apple's dictionary
nnoremap <silent> <Leader>di :!open dict://<cword><cr><cr>

Using Apple's built-in dictionary to look up words in vim.

Wunderbar! Now lets grab a fantastic vim plugin from beloglazov that will give us access to thesaurus.com. This gives vi a couple of new commands for looking up any word (:Thesaurus <word>) and the current word under the cursor (:OnlineThesaurusCurrentWord). Here I use it to search for synonyms for "commands":

Using https://thesaurus.com to look synonyms from within vim.

This plugin will also return a short definition as well, so Linux users rejoice!

Spell-checking

Another feature most of us have come to rely on while writing prose in rich text editors is a spell-checker. Luckily, vim comes with a spell checking system out of the box (:help spell) which you can enable for markdown files by creating a file in ~/.vim/ftplugin/markdown.vim with the following configuration setlocal spell. We now have spell checking enabled in all markdown files, but let's take a closer look as to what's going on here.

If we read up on ftplugin files via :h ftplugin we'll see that we are creating a filetype plugin that will automatically be sourced by vim.

A filetype plugin is like a global plugin, except that it sets options and defines mappings for the current buffer only.

Let's also take a look at what setlocal is doing:

              *:setl* *:setlocal*
:setl[ocal] ...		Like ":set" but set only the value local to the
      current buffer or window.  Not all options have a
      local value. If the option does not have a local
      value the global value is set.
      With the "all" argument: display local values for all
      local options.
      Without argument: Display local values for all local
      options which are different from the default.
      When displaying a specific local option, show the
      local value. For a global/local boolean option, when
      the global value is being used, "--" is displayed
      before the option name.
      For a global option the global value is
      shown (but that might change in the future).

This is all well and good, but how much use is a spell checker that doesn't offer spell correction suggestions? Well, as you probably expected, vim brings spell suggestions to the party for free. Simply use the z= mapping when your cursor is over the misspelled word to receive a list of suggestions to choose from like so:

Spell-checking within vim.

Just a few more things on spell checking, I swear.

Vim also provides two mappings for jumping from one misspelled word to the next with ]s (next misspelled) and [s (previous misspelled word).

Here's where you start to feel spoiled. Vim allows you to build a list of words that you consider "good" (words that are properly spelled but marked as misspelled by vim's spell checker) and words that you consider "wrong" (words that vim mistakenly views as correctly spelled). You can achieve this via the zg (good words) and zw (wrong words) when the cursor is on the word you're targeting.

Where does this list go and how does it work? Again, let's head to vim's fantastic help documentation, :h spellfile:

Name of the word list file where words are added for the |zg| and |zw|
commands.  It must end in ".{encoding}.add".  You need to include the
path, otherwise the file is placed in the current directory.

…

For the file name the first language name that appears in 'spelllang' is used,
ignoring the region.

I've created my own spell checking file in ~/.vim/spell/english.utf-8.add.

Note: every time you add a word to your list using zg and zw a similarly named file with a tacked on .spl extension file that vim actually uses for spell checking will be regenerated based on your updated list of words.

Automatically fix words you commonly misspell

One of vim's features that I should use more liberally is its abbreviations.

If you enter a word that is an abbreviation, it is replaced with the word it stands for. This can be used to save typing for often used long words. And you can use it to automatically correct obvious spelling errors.

For example, my brain refuses to type destroy instead of destory, and the same goes for unknown instead of unkown. Vim, being a forgiving soul will go easy on me if I ask it to.

iabbrev destory destroy

augroup markdown
  autocmd FileType markdown iabbrev <buffer> ... …
augroup END

Since abbreviations can be set for Insert, Replace, and Command-line mode, I like to restrict my abbreviations to insert mode only with iabbrev. Also, some abbreviations I only want to trigger in markdown files when I'm writing posts. The augroup above takes care of that for me, and in this case it replaces three periods with the ellipses symbol. Now, moving on…

Linting your prose

Depending on how much Proust you have in you, you may not give a shit about writing style suggestions. If you feel like you could use it, take a look at setting up proselint with whichever vim plugin you use for linting.

Animated screen captures

I use the oddly named licecap app to capture any gifs I'd like to use in my posts. This is one of those "Dear God, had I known about this sooner" tools.

Markdown links

There are multiple ways of using creating links in markdown that I think you should be aware of when using the file format for your blog posts. Choose whichever you fancy.

Wrap up

That pretty much does it! These are all of the tools I like to use when writing blog posts in my favorite editor.

Footnotes

1.

Oh, you.

β†©οΈŽ

Newsletter

I'm working on sending out a weekly newsletter. I'll make it as easy as possible to unsubscribe at any time.