{ blurb: "Add a new lexer to Chroma" } $index ## Introduction [Gitea](https://github.com/go-gitea/gitea) uses [Chroma](https://github.com/alecthomas/chroma) for syntax highlighting. Chroma is based on the Python syntax highlighter, [Pygments](https://github.com/pygments/pygments), and includes a [script](https://github.com/alecthomas/chroma/blob/484750a96fc430f49d6b69cc2a2a8b7a67691446/_tools/pygments2chroma_xml.py) to help convert Pygments lexers for use with Chroma. This post describes that process. ## Convert a Pygments lexer to a Chroma lexer with `pygments2chroma_xml.py` In the Chroma root directory, we run: ```console $ docker run --rm -it -w /opt -v $PWD:/opt python bash -c \ "pip install pystache pygments && pip list \ && python _tools/pygments2chroma_xml.py \ pygments.lexers.scripting.LuaLexer > lexers/embedded/lua.xml" ``` As output, we should see this in our terminal: ``` Package Version -------- ------- pip 25.0.1 Pygments 2.19.2 pystache 0.6.8 ``` This just helps us know what version of Pygments we generated our lexer from. The file `lexers/embedded/lua.xml` should now contain all the tokenization rules for the [Lua](https://www.lua.org) language. ::: filename-for-code-block `lexers/embedded/lua.xml` ::: ```xml Lua ... ``` ## Highlight some code with our new lexer Chroma provides a [simple example test file][1] we can modify to see what syntax highlighting with our new lexer looks like. First, though, we need to create a new Go module by running `go mod init`: ```console $ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm \ go mod init main go: creating new go.mod: module main go: to add module requirements and sums: go mod tidy ``` We will need required modules, so let's go ahead and run `go mod tidy` as the output suggests. ```console $ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm \ go mod tidy ``` We should now have 2 additional files, `go.mod` and `go.sum`. `go.sum` has some package hashes while `go.mod` should look like this: ::: filename-for-code-block `go.mod` ::: ``` module main go 1.25 require github.com/alecthomas/chroma/v2 v2.18.0 require github.com/dlclark/regexp2 v1.11.5 // indirect ``` Now we can create a `main.go` file and copy over the code from Chroma's example test file, but we update the `code` variable and the lexer we pass into the `Highlight` function for Lua: ::: filename-for-code-block `main.go` ::: ```go package main import ( "log" "os" "github.com/alecthomas/chroma/v2/quick" ) func main() { code := `print("hello")` err := quick.Highlight(os.Stdout, code, "lua", "html", "monokai") if err != nil { log.Fatal(err) } } ``` Now we can try running our `main.go` like this: ```console $ docker run --rm -it -w /opt -v $PWD:/opt golang:tip-bookworm go run main.go go: downloading github.com/alecthomas/chroma/v2 v2.18.0 go: downloading github.com/dlclark/regexp2 v1.11.5