In situ Syntax Highlighting in macOS Applications Like Keynote – Eric’s Archived Thoughts
Earlier this month, I returned to CSS Day for the first time since<br>2018 to deliver my first in-person talk since 2022. “Forging Our Own<br>Paths” should be available at some point; in the meantime, for the six or<br>seven people in my audience who might need to do something similar, I’d<br>like to share a small macOS workflow I developed to make syntax-highlighting<br>code blocks in situ in Keynote a lot simpler. The<br>end result is to have an entry (or entries) in the Services submenu of<br>the contextual (right-click) menu for highlighted text. All this is adapted from an old blog<br>post I found copied in a few places, and which needed some updates to<br>make things work in 2026.
This is what it looks like for me. It could look much the same for you!
First, install highlight. I used brew install highlight, and the rest of this piece assumes you’ve done it that way. If you install it another way, such that it ends up in a different location than Homebrew would give it, you’ll need to modify a variable value later on, which I’ll point out when we get there.
Next, you need to install the following (also available as a gist) as a shell script called keynote-highlight:
#! /bin/bash<br>set -e<br>while getopts 'h:o:i:s:t:' OPTION; do<br>case "$OPTION" in<br>h)<br>highlighthome="$OPTARG"<br>;;<br>o)<br>outputrtf="$OPTARG"<br>;;<br>i)<br>inputrtf="$OPTARG"<br>;;<br>s)<br>syntax="$OPTARG"<br>;;<br>t)<br>theme="$OPTARG"<br>;;<br>?)<br>echo "script usage incorrect?" >&2<br>exit 1<br>;;<br>esac<br>done<br>shift "$(($OPTIND -1))"
#=============================
inputrtf="$(pbpaste -pboard -prefer public.rtf)"
regex="fcharset0 ([a-zA-Z0-9 ]+);"<br>if [[ "$inputrtf" =~ $regex ]]<br>then<br>fontface=${BASH_REMATCH[1]}<br>else<br>fontface="Courier"<br>fi
regex="fs([0-9]{1,5})"<br>if [[ "$inputrtf" =~ $regex ]]<br>then<br>fontsize=${BASH_REMATCH[1]}<br>fontsize2=$((fontsize/2))<br>else<br>fontsize2="12"<br>fi
if [ -z "$theme" ]; then<br>theme="candy"<br>fi
if [ -z "$highlighthome" ]; then<br>highlighthome="/opt/homebrew/bin/highlight"<br>fi
highlighted=$("$highlighthome" --out-format="rtf" --syntax="$syntax" --style="$theme" --font="$fontface" --font-size="$fontsize2" --no-trailing-nl --stdout)<br>echo "$highlighted"
Put the script wherever you store your shell scripts, and make sure<br>it’s both executable and can be invoked from the command line. I<br>believe, without any real basis for doing so, that if you<br>already have syntax-highlight<br>installed, which is (among other things) a wrapper around<br>highlight, you could use it by modifying the<br>highlighthome variable assignment to point to it rather<br>than highlight, as well as modifying a variable in an<br>upcoming bit of code. But, as I say, I’m just guessing about that.
Once the shell script is installed and ready to execute, launch<br>Automator and create a new Quick Action. Call it “Syntax Highlight CSS”<br>or something similar. If you want to set up highlighting for other kinds<br>of code, like HTML or any of the nearly 250<br>languages (!!!) highlight supports, each language has<br>to be given its own Quick Action. Thus, if you want them all next to<br>each other in the Services menu, pick an appropriate naming scheme. For<br>this one, we’re doing CSS, but later you’ll see how you can quickly set<br>up this same thing for other formats.
At the top of the right-hand panel in the new Quick Action workflow,<br>check the “Workflow receives current” dropdown to make sure it’s set to<br>either “Automatic (rich text)” or “rich text”, the latter if you plan to<br>never, ever use this in any non-RTF setting. I go with the Automatic<br>option. If you want to restrict the action to a particular application,<br>like Keynote, change the dropdown that says “any application” to pick a<br>specific application. I leave mine to be available in any application,<br>just in case I’m ever syntax highlighting code in TextEdit or something. I also set the color to “Red”, because clearly that makes it go<br>faster.
With all those things set, the first thing to add to the workflow is<br>a “Copy to Clipboard” action. That’s it for this step, just add that and<br>leave it alone.
Now, add a “Run AppleScript” action. Paste the following (also available<br>as a gist) into the textbox that contains the boilerplate skeleton<br>(replace the skeleton):
on run {input, parameters}<br>set highlightHome to "/opt/homebrew/bin/highlight"<br>set syntaxType to "css"<br>set themeName to "navy"<br>set command to "PATH_TO_SCRIPT/keynote-highlight -h " & highlightHome & " -s " & syntaxType & " -t " & themeName<br>do shell script "/bin/bash -c 'pbpaste | " & command & " | pbcopy'"<br>delay 0.1<br>tell application "System Events" to keystroke "v" using command down<br>end run
Change the PATH_TO_SCRIPT in there to wherever you put<br>the shell script, save the workflow, and it should be ready to go!
What the Automator workflow should look like.
…unless your copy of highlight lives somewhere else or<br>you’re trying out using syntax-highlight in its place, or<br>you have a different theme you’d like to use. In either case, change the<br>value...