highlight.go

 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}