Add rough draft
This commit is contained in:
parent
7839e30c28
commit
a7e155de6d
183
posts/2025-06-20-chroma.md
Normal file
183
posts/2025-06-20-chroma.md
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
{
|
||||||
|
blurb: "Add a new lexer to chroma"
|
||||||
|
}
|
||||||
|
|
||||||
|
## Intro
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ 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`
|
||||||
|
:::
|
||||||
|
|
||||||
|
```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:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ 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:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ 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](https://go.dev/ref/mod#go-mod-file-replace):
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ 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`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
code := `print "Hello, #{@name}!"`
|
||||||
|
|
||||||
|
fmt.Println(quick.Highlight(os.Stdout, code, "moonscript", "html", "monokai"))
|
||||||
|
```
|
||||||
|
|
||||||
|
And we have it:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ 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.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ RECORD=true go test ./lexers
|
||||||
|
```
|
||||||
|
|
||||||
|
Visually inspect and verify that the expected data is correct.
|
||||||
|
|
||||||
|
## Run tests
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ go test ./lexers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bonus!: Use local `pygments` with `pygments2chroma_xml.py`
|
||||||
|
|
||||||
|
These lines in `pygments2chroma_xml.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
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:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ 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.
|
||||||
|
|
||||||
|
```console
|
||||||
|
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.
|
||||||
|
|
||||||
|
```console
|
||||||
|
<lexer>
|
||||||
|
<config>
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
If you wanted to save
|
Loading…
x
Reference in New Issue
Block a user