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}