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