Syntax-highlighting markdown fenced code blocks in Emacs

The syntax-highlighted fenced code blocks in GitHub flavored markdown, or GFM, are a beautiful and useful invention. One starts a code block with three or more backticks or tildes, followed by the name of the language, and then proceeds to show one’s code, which, at least on GitHub, is then syntax highlighted.

In other words, something like this in your markdown:

```python
def computer_says(no):
    print("computer says %s" % (no,))
```

Would become this in the preview:

def computer_says(no):
    print("computer says %s" % (no,))

When I’m editing my markdown, I’d obviously like to see this language-specific highlighting interspersed with my normal markdown highlighting. SublimeText’s MarkdownEditing package does a superb job of this, but of course we’re currently rediscovering the universe that is Emacs.

DuckDuckGoing around, we run into at least two Emacs packages that do this: mmm-mode and polymode. We decided to try out both of them, finally ending up (quite happy) with the result shown in this screenshot:

Editing this post with emacs, markdown-mode and mmm-mode
Editing this post with emacs, markdown-mode and mmm-mode

polymode

After git cloning polymode into my ~/.emacs.d, I installed it according to the instructions, by adding the following to my ~/.emacs.d/init.el:

(setq load-path
      (append '("~/.emacs.d/polymode/" "~/.emacs.d/polymode/modes")
              load-path))

(require 'poly-R)
(require 'poly-markdown)

Initially I had just the poly-markdown require, but that yielded an empty variable error. With this configuration, opening any .md file should activate the poly-markdown mode.

poly-markdown creates an indirect buffer for every code block that you create. This means if you switch buffers using for example C-x C-b, you’ll see for each file you’re editing with poly-markdown as many extra buffers as there are fenced code blocks in your file.

When you start a new fenced code block, polymode picks this up automatically. When you load a new colour theme, the code blocks don’t always pick it up immediately, but this can be lived with.

mmm-mode

This all worked in my case, but I wanted to try out mmm-mode as well. While not as hip and generic as polymode, this has been around for quite a while longer, and has seen much testing.

I installed mmm-mode from ELPA with M-x package-install RET mmm-mode (yes, it’s that easy) and then changed my .emacs.d/init.el as follows:

(require 'mmm-mode)

(mmm-add-classes
'((markdown-python
:submode python-mode
:face mmm-declaration-submode-face
:front "^```python[\n\r]+"
:back "^```$")))

(setq mmm-global-mode 't)
(mmm-add-mode-ext-class 'markdown-mode nil 'markdown-python)

I’m only showing Python here, but I’ve defined classes and added them to markdown-mode for JavaScript and emacs-lisp as well. There’s probably a better way to define the extra classes for a whole list of languages, but my (lack of) elisp skills doesn’t know about it yet.

conclusion

I definitely liked mmm-mode better. It doesn’t create all of those indirect buffers (which do affect my workflow). When you create a new fenced code block, it doesn’t highlight this until you do e.g. M-x mmm-parse-buffer. However, I like this sort of determinism. Other than that, mmm-mode felt generally more stable and responsive than polymode. This no surprise; although polymode shows great potential, it’s still in alpha. Because I need something that works now, I’ll hold onto my mmm-mode for a while longer.

3 thoughts on “Syntax-highlighting markdown fenced code blocks in Emacs”

  1. Awesome, I’d been looking for something like this for a while. Polymode seems nice so far, though it doesn’t seem to work with gfm-mode, only markdown-mode. I might try and send them a patch at some point for this. Thanks for writing this up!

  2. Have you by chance figured out how to solve the indentation problem with single quotes (apostrophes)? As I’m sure you’ve noticed, when you have an odd number of single quotes in your markdown text the function indentation doesn’t work properly; likewise, if you have unbalanced single quotes (e.g. an apostrophe in a comment) then it highlights the remaining portion of the markdown text as if it were a python quote.

    1. I am afraid not with markdown mode. I solved the problem by switching to orgmode. 😉 Seriously though, if you’re using Emacs, orgmode is 100x better than markdown for everything.

Leave a Reply

Your email address will not be published. Required fields are marked *