1package highlight
2
3import (
4 "bytes"
5 "image/color"
6
7 "github.com/alecthomas/chroma/v2"
8 "github.com/alecthomas/chroma/v2/formatters"
9 "github.com/alecthomas/chroma/v2/lexers"
10 chromaStyles "github.com/alecthomas/chroma/v2/styles"
11 "github.com/charmbracelet/crush/internal/tui/styles"
12)
13
14func SyntaxHighlight(source, fileName string, bg color.Color) (string, error) {
15 // Determine the language lexer to use
16 l := lexers.Match(fileName)
17 if l == nil {
18 l = lexers.Analyse(source)
19 }
20 if l == nil {
21 l = lexers.Fallback
22 }
23 l = chroma.Coalesce(l)
24
25 // Get the formatter
26 f := formatters.Get("terminal16m")
27 if f == nil {
28 f = formatters.Fallback
29 }
30
31 style := chroma.MustNewStyle("crush", styles.GetChromaTheme())
32
33 // Modify the style to use the provided background
34 s, err := style.Builder().Transform(
35 func(t chroma.StyleEntry) chroma.StyleEntry {
36 r, g, b, _ := bg.RGBA()
37 t.Background = chroma.NewColour(uint8(r>>8), uint8(g>>8), uint8(b>>8))
38 return t
39 },
40 ).Build()
41 if err != nil {
42 s = chromaStyles.Fallback
43 }
44
45 // Tokenize and format
46 it, err := l.Tokenise(nil, source)
47 if err != nil {
48 return "", err
49 }
50
51 var buf bytes.Buffer
52 err = f.Format(&buf, s, it)
53 return buf.String(), err
54}