2021-03-26 22:57:47 +03:00
|
|
|
package lipgloss
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/muesli/reflow/ansi"
|
|
|
|
"github.com/muesli/termenv"
|
|
|
|
)
|
|
|
|
|
2022-10-05 05:10:54 +03:00
|
|
|
// whitespace is a whitespace renderer.
|
|
|
|
type whitespace struct {
|
2022-06-28 20:28:35 +03:00
|
|
|
re *Renderer
|
2021-03-26 22:57:47 +03:00
|
|
|
style termenv.Style
|
|
|
|
chars string
|
|
|
|
}
|
|
|
|
|
2022-10-05 05:10:54 +03:00
|
|
|
// newWhitespace creates a new whitespace renderer. The order of the options
|
2022-06-28 20:28:35 +03:00
|
|
|
// matters, it you'r using WithWhitespaceRenderer, make sure it comes first as
|
|
|
|
// other options might depend on it.
|
2022-10-05 05:10:54 +03:00
|
|
|
func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace {
|
|
|
|
w := &whitespace{re: r}
|
2022-06-28 20:28:35 +03:00
|
|
|
for _, opt := range opts {
|
|
|
|
opt(w)
|
|
|
|
}
|
|
|
|
return w
|
|
|
|
}
|
|
|
|
|
2021-04-06 05:08:36 +03:00
|
|
|
// Render whitespaces.
|
2022-10-05 05:10:54 +03:00
|
|
|
func (w whitespace) render(width int) string {
|
2021-03-26 22:57:47 +03:00
|
|
|
if w.chars == "" {
|
|
|
|
w.chars = " "
|
|
|
|
}
|
|
|
|
|
2021-03-30 17:45:47 +03:00
|
|
|
r := []rune(w.chars)
|
|
|
|
j := 0
|
|
|
|
b := strings.Builder{}
|
2021-03-26 22:57:47 +03:00
|
|
|
|
2021-03-30 17:45:47 +03:00
|
|
|
// Cycle through runes and print them into the whitespace.
|
|
|
|
for i := 0; i < width; {
|
|
|
|
b.WriteRune(r[j])
|
|
|
|
j++
|
|
|
|
if j >= len(r) {
|
|
|
|
j = 0
|
|
|
|
}
|
|
|
|
i += ansi.PrintableRuneWidth(string(r[j]))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill any extra gaps white spaces. This might be necessary if any runes
|
|
|
|
// are more than one cell wide, which could leave a one-rune gap.
|
|
|
|
short := width - ansi.PrintableRuneWidth(b.String())
|
2021-03-26 22:57:47 +03:00
|
|
|
if short > 0 {
|
2021-03-30 17:45:47 +03:00
|
|
|
b.WriteString(strings.Repeat(" ", short))
|
2021-03-26 22:57:47 +03:00
|
|
|
}
|
|
|
|
|
2021-03-30 17:45:47 +03:00
|
|
|
return w.style.Styled(b.String())
|
2021-03-26 22:57:47 +03:00
|
|
|
}
|
|
|
|
|
2022-02-14 19:39:57 +03:00
|
|
|
// WhitespaceOption sets a styling rule for rendering whitespace.
|
2022-10-05 05:10:54 +03:00
|
|
|
type WhitespaceOption func(*whitespace)
|
2022-10-03 20:11:44 +03:00
|
|
|
|
2021-03-30 17:45:47 +03:00
|
|
|
// WithWhitespaceForeground sets the color of the characters in the whitespace.
|
2021-03-31 05:19:38 +03:00
|
|
|
func WithWhitespaceForeground(c TerminalColor) WhitespaceOption {
|
2022-10-05 05:10:54 +03:00
|
|
|
return func(w *whitespace) {
|
2022-10-03 20:11:44 +03:00
|
|
|
w.style = w.style.Foreground(c.color(w.re))
|
2021-03-30 17:45:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-14 19:39:57 +03:00
|
|
|
// WithWhitespaceBackground sets the background color of the whitespace.
|
2021-03-31 05:19:38 +03:00
|
|
|
func WithWhitespaceBackground(c TerminalColor) WhitespaceOption {
|
2022-10-05 05:10:54 +03:00
|
|
|
return func(w *whitespace) {
|
2022-10-03 20:11:44 +03:00
|
|
|
w.style = w.style.Background(c.color(w.re))
|
2021-03-26 22:57:47 +03:00
|
|
|
}
|
|
|
|
}
|
2021-03-30 17:45:47 +03:00
|
|
|
|
|
|
|
// WithWhitespaceChars sets the characters to be rendered in the whitespace.
|
|
|
|
func WithWhitespaceChars(s string) WhitespaceOption {
|
2022-10-05 05:10:54 +03:00
|
|
|
return func(w *whitespace) {
|
2021-03-30 17:45:47 +03:00
|
|
|
w.chars = s
|
|
|
|
}
|
|
|
|
}
|