main
1package lipgloss
2
3import (
4 "strings"
5
6 "github.com/charmbracelet/x/ansi"
7 "github.com/muesli/termenv"
8)
9
10// whitespace is a whitespace renderer.
11type whitespace struct {
12 re *Renderer
13 style termenv.Style
14 chars string
15}
16
17// newWhitespace creates a new whitespace renderer. The order of the options
18// matters, if you're using WithWhitespaceRenderer, make sure it comes first as
19// other options might depend on it.
20func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace {
21 w := &whitespace{
22 re: r,
23 style: r.ColorProfile().String(),
24 }
25 for _, opt := range opts {
26 opt(w)
27 }
28 return w
29}
30
31// Render whitespaces.
32func (w whitespace) render(width int) string {
33 if w.chars == "" {
34 w.chars = " "
35 }
36
37 r := []rune(w.chars)
38 j := 0
39 b := strings.Builder{}
40
41 // Cycle through runes and print them into the whitespace.
42 for i := 0; i < width; {
43 b.WriteRune(r[j])
44 j++
45 if j >= len(r) {
46 j = 0
47 }
48 i += ansi.StringWidth(string(r[j]))
49 }
50
51 // Fill any extra gaps white spaces. This might be necessary if any runes
52 // are more than one cell wide, which could leave a one-rune gap.
53 short := width - ansi.StringWidth(b.String())
54 if short > 0 {
55 b.WriteString(strings.Repeat(" ", short))
56 }
57
58 return w.style.Styled(b.String())
59}
60
61// WhitespaceOption sets a styling rule for rendering whitespace.
62type WhitespaceOption func(*whitespace)
63
64// WithWhitespaceForeground sets the color of the characters in the whitespace.
65func WithWhitespaceForeground(c TerminalColor) WhitespaceOption {
66 return func(w *whitespace) {
67 w.style = w.style.Foreground(c.color(w.re))
68 }
69}
70
71// WithWhitespaceBackground sets the background color of the whitespace.
72func WithWhitespaceBackground(c TerminalColor) WhitespaceOption {
73 return func(w *whitespace) {
74 w.style = w.style.Background(c.color(w.re))
75 }
76}
77
78// WithWhitespaceChars sets the characters to be rendered in the whitespace.
79func WithWhitespaceChars(s string) WhitespaceOption {
80 return func(w *whitespace) {
81 w.chars = s
82 }
83}