Vim has a makeprg setting that can be more helpful than you might imagine. Here are a few ways to take advantage of it.

This started out as a small post on how to preview markdown documents in Vim using makeprg, but somehow I got carried away. More on the markdown thing in a bit.

When you type :make in Vim, the value of makeprg is executed in a subprocess. Traditionally this value is set to make, but you can set this to anything you like. You can see the current value by typing :set makeprg. When you combine this with Vim’s support for filetype plugins, there’s a decent amount of value that I think is sometimes overlooked. So this article is an attempt to explain some of the things you can do with makeprg and filetype detection.

Filetype Plugins

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

In order to make use of filetype plugins, vim must be told to enable this feature. This is enabled by default on many installations, but some (perhaps MacOS X) require the user to enable it explicitly. Place this line in your vimrc:

filetype plugin on

Using a filetype plugin, we can set makeprg to something useful depending on the type of a file it happens to be. Adding your own filetype plugin is easy, just create a file of the form: <filetype>.vim inside the ~/.vim/after/ftplugin directory. The after subdirectory is technically optional, but I prefer it as it keeps things isolated from other installed plugins. The after subdirectory is sourced last as Vim initializes itself, so putting your options there ensures they aren’t clobbered by other plugins.

For a given Vim buffer, you can see the filetype by typing :set ft. Some people put this information in their statusline, which can be helpful if you’re writing Vim plugins or just want to make sure things are being detected correctly.

For example, if I want to define custom settings for the C filetype, I would create ~/.vim/after/ftplugin/c.vim and put my settings there. Any time a file of type C is loaded, my settings are applied. We can use this mechanism to set a custom makeprg for certain filetypes.

Customizing makeprg for Markdown

I take all of my notes in Markdown, which is nearly plain text with a tiny amount of markup. This allows me to quickly convert my personal notes into decent looking html documentation. It seems to be a regular occurrence that my notes become the initial documentation for the project or subproject that I’m working on. Many wiki’s support Markdown, so it ends up saving me work by just keeping everything in that format.

Even though Markdown’s syntax is very lean and simple, I still end up forgetting some of it from time to time. I find it useful to generate and view the HTML output for the buffer that I’m working on periodically to make sure things look right. This is really easy by setting a custom makeprg for the markdown filetype.

The Hammer Plugin

Robert Gleeson wrote a Vim plugin called Hammer that basically does exactly what I explain here and quite a bit more. It might be perfect for you, but for me it’s much more than I need. I’ve had problems when the version of Ruby on the system is not the same as what Vim was compiled with. Check it out though, you might love it.

A Simpler Approach

All I want is to type :make and have Vim generate an HTML version in /tmp that I can point my browser to. So I put the following in ~/.vim/after/ftplugin/markdown.vim:

set makeprg=redcarpet\ %\ >/tmp/%<.html

Let’s take a quick look at what’s going on here:

  • The above setting is applied only when editing a markdown buffer. Personally, I use redcarpet to parse markdown, but there are many others that you can substitute here.

  • Spaces in option strings must be escaped so Vim knows when to stop parsing.

  • % expands to the name of the file currently being edited.

  • %< expands to the name of the file without the trailing extension. This allows us to change the name of the file and add the html extension.

So the above command calls redcarpet on the filename and redirects the output to /tmp/<filename>.html. That’s it, super simple. Once this completes, I point my browser to file:/tmp and load the file I’m interested in.

This same approach can be taken with ReStructured Text by putting the following in ~/.vim/after/ftplugin/rst.vim:

set makeprg=rst2html.py\ %\ /tmp/%<.html`

Extra Credit

For C, we could set makeprg to call gcc directly instead of make if a Makefile is not found in the current working directory. I find this very helpful when creating a scratch source file to test certain behaviour or a quick theory. Here’s what the contents of ~/.vim/after/ftplugin/c.vim might look like:

if !filereadable(expand("%:p:h")."/Makefile")
    setlocal makeprg=gcc\ -Wall\ -Wextra\ -o\ %<\ %
endif

Now when you load a file of type C and there is no Makefile, typing :make will compile your source file into an executable of the same name (minus the extension). I use this all the time. You could do the same thing for C++ by changing the filename to cpp.vim and changing gcc to g++.

Future Work

It would be cool to copy the target filename to the clipboard for easy pasting into the browser’s URL bar.

Update:

I handle this with the following

setlocal makeprg=markdown\ %\ >%<.html

" Open corresponding html file
nmap <Leader>v :!google-chrome %<.html<CR><CR>

which may be replaced by the browser and file position of your preference.

– Bijan Chokoufe