A guide to modifying the default {distill} syntax highlighting theme, including colour choice considerations, and its implementation in {distilltools}
Note: This post was originally written by Ella Kaye and was copied here on May 27, 2021 - see the original post here for a potentially updated version.
The {distill} package for R can be used to build easy-to-maintain websites written only in R Markdown, such as this one.1
I wrote a function to modify the default syntax highlighting theme. This modify_default_highlighting
function is now part of the {distilltools} package.
Hereâs the function in action, to get the theme used on this site:
# get distilltools, requires remotes >= 2.2
remotes::install_github("EllaKaye/distilltools")
library(distilltools)
modify_default_highlighting(
name = "ek_syntax_highlighting",
numeric = "#B6005B", # replaces the default red
strings = "#008643", # replaces the default green
functions = "#005BB6", # replaces the default purple
control = "#5B00B6", # replaces the default blue
constant = "#B65B00" # replaces the default brown
)
And hereâs the theme in action:
library(dplyr)
library(palmerpenguins)
penguins %>%
mutate(
long_flipper = case_when(
species == "Adelie" & flipper_length_mm > 195 ~ TRUE,
species == "Chinstrap" & flipper_length_mm > 200 ~ TRUE,
species == "Gentoo" & flipper_length_mm > 225 ~ TRUE,
TRUE ~ FALSE
)
) %>%
mutate(
long_bill = case_when(
species == "Adelie" & bill_length_mm > 42 ~ TRUE,
species == "Chinstrap" & bill_length_mm > 52 ~ TRUE,
species == "Gentoo" & bill_length_mm > 50 ~ TRUE,
TRUE ~ FALSE
)
)
This is the first in a series of two posts on implementing a custom syntax highlighting theme for a website or blog built with {distill}. Read on here for why and how this function was built, what it does and doesnât do, and its inclusion in the {distilltools} package. This post also outlines the criteria that were important to me when choosing colours for my theme, but take a look at Part 2, custom syntax highlighting for {distill}: creating the palette, for a deep dive into considerations about colour choices, in respect to both colour theory and accessibility, and how I ensured my criteria were met.
Before I delve into how to create a custom syntax highlighting scheme, I want to take a minute to admire the default. The authors of {distill}, in particular Alison Hill, have thought and worked hard to ensure that {distill} provides a good user experience, both for the siteâs author AND for those reading it. One of the key considerations for the latter is a default syntax highlighting scheme with colours that are optimised for accessibility and colour contrast. I say more about what that means below and in Part 2. Also, it appears that the colours in the scheme work well together, and overall, on the many {distill} websites where Iâve seen the scheme used, I think it looks really good! For a great example of the default in action, check out this code-chunk-heavy post by Tom Mock.
When I used the default syntax highlighting theme on my site I found, to my eye, that the red used for numeric variables clashed with the bright pink (closest colour name ârazzmatazzâ) Iâve used in my logo and elsewhere throughout the site. So, I decided to tweak the default theme swapping the red for my pink and, to match it, more vibrant versions of the remaining colours.
My first task was to find out whether this was possible, and if, so, how. Thankfully, the {distill} documentation contains a section on syntax highlighting, showing that there is an option to give distill_article
a path to a custom .theme
file. The linked pandoc documentation on syntax highlighting demonstrates how to use pandoc in the command line to save a personal version of the pygments
highlighting theme. The documentation points out that that copy of the pygments .theme
file can then be edited to create a custom theme.
Once I had a general strategy of copying and editing an existing .theme
file, my next task was to find the .theme
file for the default used in {distill}, because thatâs what Iâd already decided to take as my starting point.
I cloned the distill repo from GitHub and opened it in RStudio.2 From there I began my detective work with one of my favourite RStudio features, âFind in Filesâ (⧠+ â + f on a Mac), which searches across all files in a project. I searched for âhighlightâ and followed various trails until I discovered that the default is called arrow.theme
and is stored in inst/rmarkdown/templates/distill_article/resources/
. Thankfully, because itâs in the inst
folder, the file is accessible to users who have the {distill} package installed. In the RStudio project for my website, I created a new script, syntax_highlighting.R
, in the R
folder I have in my root directory, then I ran the following to save a copy of arrow.theme
into my websiteâs root directory:
arrow_theme_path <- system.file(
"rmarkdown/templates/distill_article/resources/arrow.theme",
package = "distill"
)
file.copy(arrow_theme_path, "arrow.theme")
When I had run that once, I commented out the above lines. I donât want any future changes in arrow.theme
in {distill} to break what I do next.
From there I could open up my copy of the arrow.theme
file and manually inspect it. I use a great Mac app for building colour palettes, ColorSlurp.3 The basic version is free, though the pro version has useful features for testing accessibility - more on that in Part 2. I set up a new palette in ColorSlurp and, for each hex colour code I encountered, I saved it there.
There are 29 types of text-styles
in the theme, of which:
Comment
and Documentation
Variable
Other
, ControlFlow
and Keyword
Function
BaseN
, Float
) and things like Alert
and Error
Constant
null
I was happy to stick with the groupings, grey, off-black and null
in the default, so now I knew I had to pick five colours for my theme.
I had four criteria for building a colour palette to use for my syntax highlighting theme:
I was originally going to write up how I went about building such a palette, both in terms of the thought process and tools used, as part of this post, but it was getting a little long4, so Iâve spun it out into a separate post,custom syntax highlighting for {distill} part 2: creating the palette.
At the end of the process, the palette for my syntax highlighting scheme is as in Figure 1.
arrow.theme
With all the pieces in place, itâs now just a case of swapping out the default colour codes for our own choices. Although itâs possible to manually edit the arrow.theme
file we now have in our directory, to aid reproducibility, and with a view to writing this up as a function, I edited it using R code instead. I read in the file, substituted the hex codes, then saved the resulting theme into a new ek_syntax_highlighting.theme
file (leaving arrow.theme
unchanged). Below are two approaches, one using base R, the other in the tidyverse, that I put in my syntax_highlighting.R
script.
# read in the default theme
theme <- readLines("arrow.theme")
# base R approach
theme <- gsub("#AD0000", "#B6005B", theme) # red -> pink
theme <- gsub("#8f5902", "#B65B00", theme) # brown -> brown
theme <- gsub("#007BA5", "#5B00B6", theme) # blue -> purple
theme <- gsub("#20794D", "#B65B00", theme) # green -> green
theme <- gsub("#4758AB", "#005BB6", theme) # purple -> blue
# alternatively, tidyverse approach
library(stringr)
library(magrittr)
theme <- readLines("arrow.theme") %>%
str_replace_all("#AD0000", "#B6005B") %>% # red -> pink
str_replace_all("#8f5902", "#B65B00") %>% # brown -> brown
str_replace_all("#007BA5", "#5B00B6") %>% # blue -> purple
str_replace_all("#20794D", "#008643") %>% # green -> green
str_replace_all("#4758AB", "#005BB6") # purple -> blue
# save new theme
writeLines(theme, "ek_syntax_highlighting.theme")
I now have the file ek_syntax_highlighting.theme
in my root directory, with my colour choices.
It is, of course, possible to modify it further, either manually or by making further substutions in the code above. There is a quirk, though: if I swap one of the default hex codes for my own colour choice, that implements just fine, but if I swap any of the null
s for a colour, that doesnât show up when I apply the theme.
When I figure out code to do something that I think I might want to do again, or think others might find useful, I generally like to write it up as a function, and thatâs what Iâve done with the above, wrapping it in a function called modify_default_highlighting
and putting it in the {distilltools} package. {distilltools} is in the very early stages of development, an (expanding) collection of tools to support the creation and styling of content on websites created using {distill}.
When I first announced the package, I included in the âfuture functionalityâ section of the package README the intention to add a create_highlight_theme
function. I donât think what Iâve done is quite versatile or fully-featured enough to warrant that name. Instead, I called it modify_default_highlighting
because thatâs all it does, allowing you to swap out the five colours in the default scheme for five colours of your choosing. It does, however, create a .theme
file in your working directory, that can be further edited manually, or with your own R code, if further modifications are desired.
The first argument to modify_default_highlighting
is name
, the name you want to give your theme (which will create the file name.theme
). It then takes five colour arguments, which can be specified either in the hex form â#RRGGBBâ or as a named colour, from the colour names in grDevices::colors(). For a list of the colour names available in R, see page 3 of the R color cheatsheet for a one page summary, or Colors in R for a slightly less visually overwhelming list. The final argument, overwrite
(defaults to TRUE
) specifies whether to overwrite name.theme
if it already exists in the working directory. Hereâs the function in action again, this time using colour names (note that I have not tested the visual properties of this as a palette, just dropped in some colour names into the function):
library(distilltools)
modify_default_highlighting(
name = "ek_syntax_highlighting",
numeric = "deeppink", # replaces the default red
strings = "forestgreen", # replaces the default green
functions = "darkorchid3", # replaces the default purple
control = "royalbkue3", # replaces the default blue
constant = "darkorange1" # replaces the default brown
)
Once you have you custom .theme
file, youâll want to apply it to your site. According to the {distill} documentation, you can apply a syntax highlighting theme with the following YAML:
---
output:
distill::distill_article:
highlight: my_highlighting.theme
---
Here, the available options for highlight
include default
, rstudio
(the default RStudio editor theme), and the haddock
, kate
, monochrome
, pygments
and tango
pandoc highlighting themes. Also, most importantly for us, it can also take the path to a .theme
file.
Presumably, we should be able to add this to our _site.yml
file to have the theme apply site-wide (though note youâll have to rebuild the site and re-knit any posts where you want to it apply). However, thatâs not working for me. I have raised an issue about it. If you face the same problem, it would be helpful if you could comment there too.
There is a workaround, though, which is that the above YAML can also be included in individual .Rmd articles, in which case the theme applies just fine, though note that if your .theme
file is in you root directory, youâll need to give the full path to it.5 And if it sounds like a bit of a pain to have to add that every time you write a new post, consider creating a template for your posts, including those lines, and then starting new posts with the {distilltools} function create_post_from_template()
.6
For more on resources and inspirations for setting up a {distill} website, see my previous post, Welcome to my {distill} website.âŠď¸
From RStudio, go to âFileâ in the menu bar, then âNew ProjectâŚâ Chose âVersion Controlâ, then âGitâ, then enter https://github.com/rstudio/distill.git
as the âRepository URL:â and click âCreate ProjectââŠď¸
I donât have experience of colour apps on other operating systems, but a quick search for ColorSlurp alternatives suggest there are a bunch to pick from.âŠď¸
As part of the process of writing the post, I learnt much more about colour theory, and alternatives to the approach that I had originally taken, and I wanted to share it all!âŠď¸
If you happen to inspect the source code for this post, you might notice that I have copied ek_syntax_highlighting.theme
into the directory. This is not necessary for my site (using the full path to the .theme
folder in my root directory is sufficient). However, I needed to do this to get the theme to show in the version of this post in the distillery.âŠď¸
Note that the create_post_from_template()
function is likely to get wrapped into {distill} itself, or its functionality included in distill::create_post()
, and will be depreciated from {distilltools} if so. (I have had some discussion with the {distill} team about this and will be submitting a PR in the near future.)âŠď¸
If you see mistakes or want to suggest changes, please create an issue on the source repository.
Text and figures are licensed under Creative Commons Attribution CC BY-SA 4.0. Source code is available at https://github.com/jhelvy/distillery, unless otherwise noted. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".
For attribution, please cite this work as
Kaye (2021, May 25). The Distillery: Custom Syntax Highlighting for {distill} Part 1: Modifying the default theme. Retrieved from https://distillery.rbind.io/posts/2021-05-25-custom-syntax-highlighting-for-distill-part-1-modifying-the-default-theme/
BibTeX citation
@misc{kaye2021custom, author = {Kaye, Ella}, title = {The Distillery: Custom Syntax Highlighting for {distill} Part 1: Modifying the default theme}, url = {https://distillery.rbind.io/posts/2021-05-25-custom-syntax-highlighting-for-distill-part-1-modifying-the-default-theme/}, year = {2021} }