Basic Syntax Highlighting
This post was started on 2020-06-29. It was published on 2020-06-29.
One of the big reasons I’m diving into the “write your website generator” rabbit-hole is that I can have posts with nice syntax-highlighted blocks of code without onerous copy-pasting between Spacemacs and WordPress (or some other blogging platform), and with the flexbility to add better styling or other features to the code in question. So for today, we’ll try to set up syntax highlighting for code blocks in Colophon.
Luckily for us, Pollen (on which Colophon is based) already has support for syntax highlighting, either via Pygments or Highlight.js. We want Colophon to produce static, self-contained HTML (as much as possible), so Pygments is the better choice.
To start off, we follow the
Pollen
instructions and install Python 3 and Pygments. I’m on a Mac and macOS Catalina
ships with an older Python 2.7. I used Homebrew to
install Python 3 and then used pip to
install Pygments. I aliased the bare commands to the Python 3 versions, and made
sure that the pygmentize
utility was on my PATH
:
# Set up Python3 using aliases
alias python=$(which python3)
alias pip=$(which pip3)
PATH=$PATH:$HOME/Library/Python/3.7/bin
Unfortunately, while this sets up Python 3 and Pygments for use from a shell, it
takes a little more work to get it working with Pollen—alias
commands
won’t work outside of a shell, and the Pollen support for Pygments doesn’t use
the pygmentize
utility.
But once again, Pollen gives us an out: the Pollen helper code provides a
highlight
function that takes a python-executable
argument which can point to the
correct version of Python. I could provide the value "python3"
for that
argument every time I write out a code block, but that would get repetitive and
clunky, just the thing we want to avoid. Instead, I wrote a basic
tag function
that sets the python-executable
and passes on everything else to the
underlying highlight
function:
(define (codeblock #:line-numbers? [line-numbers? #t]
lang . lines)
(apply highlight
#:python-executable "python3"
#:line-numbers? line-numbers?
lang lines)
)
I provided #:line-numbers?
argument so that individual code blocks can
decide whether or not to show line numbers. The highlight
function also
has arguments for providing an outer CSS class and a set of lines to highlight.
I can expose those later if needed.
With that in place, Pollen and Pygments together turn the code blocks into HTML with different parts for different pieces of syntax. The last remaining thing is to add some CSS so that the HTML is colored and styled correctly. Pygments supports a bunch of different styles and will generate CSS for a particular style with the following incantation:
pygmentize -S <style name> -f html -a .highlight
I’m also working on a theming system for Colophon (spoilers!), but for now, pasting into the resulting CSS into the style file is good enough.
Bringing everything together, basic syntax highlighting works. In fact, this
post uses the codeblock
s to provide the highlighted snippets above. There
are a few rough edges. I’d like to bring Pygment styles into the theming system
I’m planning for Colophon. Also, because of the way the Pollen wrapper around
Pygment works, line numbers can’t be toggled on a per block basis—either all
blocks have line numbers, or all don’t. As you can imagine, this is
inconvenient, and will have to be fixed long term. I will have to sit down and
redo the Pollen-Pygments interface at some in the not-too-distant future, but I
think this is enough for a few hours’ work.