miti.sh/posts/2025-06-20-chroma.md

3.7 KiB

{ blurb: "Add a new lexer to chroma" } $index

Intro

Gitea uses Chroma for syntax highlighting. Chroma doesn't have a MoonScript lexer. It does has a Python script that can convert Pygments lexers, though, and Pygments has a MoonScript lexer.

Run MoonScript lexer generation script

To create the lexer, in the Chroma root directory run:

$ docker run --rm -it -w /opt -v $PWD:/opt python bash -c \
"pip install pystache pygments \
&& python _tools/pygments2chroma_xml.py \
pygments.lexers.scripting.MoonScriptLexer > lexers/embedded/moonscript.xml \
&& pip list"

Use the Chroma MoonScript lexer to highlight some code

Create a file like this:

::: filename-for-code-block main.go :::

package main

import (
	"fmt"
	"os"

	"github.com/alecthomas/chroma/v2/quick"
)

func main() {
    code := `package main

    func main() { }
    `

    fmt.Println(quick.Highlight(os.Stdout, code, "go", "html", "monokai"))
}

I did one of these:

$ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm \
go mod init main

Which gave me the go.mod file.

::: filename-for-code-block go.mod :::

module main

go 1.25

require (
	github.com/alecthomas/chroma/v2 v2.18.0 // indirect
	github.com/dlclark/regexp2 v1.11.5 // indirect
)

Then I did one of these:

$ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm \
go run main.go

And that should output markup (and styles) for highlighting that block of Go code to the console. But if we notice, it's importing the Chroma package from the GitHub repo. We want to use our local version of chroma, so we use go mod edit to replace the chroma import with our local version:

$ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm \
go mod edit -replace github.com/alecthomas/chroma/v2@v2.18.0=./chroma

Which adds this line to our go.mod file:

::: filename-for-code-block go.mod :::

...

replace github.com/alecthomas/chroma/v2 v2.18.0 => ./chroma

Now we can put some MoonScript in main.go.

code := `print "Hello, #{@name}!"`

fmt.Println(quick.Highlight(os.Stdout, code, "moonscript", "html", "monokai"))

And we have it:

$ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm \
go run main.go
go: downloading github.com/dlclark/regexp2 v1.11.5

That should output syntax highlighting using our local version of chroma.

Create testdata

Create a file in lexers/testdata called moonscript.actual. Add the tokens from the language in this file.

Record test output

Create another file called lexers/testdata/moonscript.expected. This is the file we will record to.

$ RECORD=true go test ./lexers

Visually inspect and verify that the expected data is correct.

Run tests

$ go test ./lexers

Bonus!: Use local pygments with pygments2chroma_xml.py

These lines in pygments2chroma_xml.py:

import pystache
from pygments import lexer as pygments_lexer
from pygments.token import _TokenType

Import pygments from pip? How do we get it to load a local version of pygments?

In Pygments root directory:

$ docker run --rm -it -w /opt -v $PWD:/opt \
-v ../gitea-syntax-highlight/chroma/_tools/pygments2chroma_xml.py:/opt/pygments2chroma_xml.py \
python bash -c "pip install pystache && pip list \
&& python pygments2chroma_xml.py pygments.lexers.scripting.LuaLexer"

Should see.

Package  Version
-------- -------
pip      25.0.1
pystache 0.6.8

That shows no remote pygments package is installed. After that you will see the lexer markup output.

<lexer>
  <config>
...