chroma.go

 1package diffview
 2
 3import (
 4	"fmt"
 5	"image/color"
 6	"io"
 7	"strings"
 8
 9	"github.com/alecthomas/chroma/v2"
10	"github.com/charmbracelet/crush/internal/ansiext"
11	"github.com/charmbracelet/lipgloss/v2"
12)
13
14var _ chroma.Formatter = chromaFormatter{}
15
16// chromaFormatter is a custom formatter for Chroma that uses Lip Gloss for
17// foreground styling, while keeping a forced background color.
18type chromaFormatter struct {
19	bgColor color.Color
20}
21
22// Format implements the chroma.Formatter interface.
23func (c chromaFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) error {
24	for token := it(); token != chroma.EOF; token = it() {
25		value := strings.TrimSuffix(token.Value, "\n")
26		value = ansiext.Escape(value)
27
28		entry := style.Get(token.Type)
29		if entry.IsZero() {
30			if _, err := fmt.Fprint(w, value); err != nil {
31				return err
32			}
33			continue
34		}
35
36		s := lipgloss.NewStyle().
37			Background(c.bgColor)
38
39		if entry.Bold == chroma.Yes {
40			s = s.Bold(true)
41		}
42		if entry.Underline == chroma.Yes {
43			s = s.Underline(true)
44		}
45		if entry.Italic == chroma.Yes {
46			s = s.Italic(true)
47		}
48		if entry.Colour.IsSet() {
49			s = s.Foreground(lipgloss.Color(entry.Colour.String()))
50		}
51
52		if _, err := fmt.Fprint(w, s.Render(value)); err != nil {
53			return err
54		}
55	}
56	return nil
57}