// Eko: A terminal-native social media platform // Copyright (C) 2025 Kyren223 // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package ui import ( "strings" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/x/ansi" "github.com/muesli/termenv" ) // whitespace is a whitespace renderer. type whitespace struct { re *lipgloss.Renderer style termenv.Style chars string } // Render whitespaces. func (w whitespace) render(width int) string { if w.chars == "" { w.chars = " " } r := []rune(w.chars) j := 0 b := strings.Builder{} // 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.StringWidth(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.StringWidth(b.String()) if short > 0 { b.WriteString(strings.Repeat(" ", short)) } return w.style.Styled(b.String()) } // WhitespaceOption sets a styling rule for rendering whitespace. type WhitespaceOption func(*whitespace) // WithWhitespaceForeground sets the color of the characters in the whitespace. func WithWhitespaceForeground(c lipgloss.TerminalColor) WhitespaceOption { return func(w *whitespace) { w.style = w.style.Foreground(ToTermenvColor(w.re, c)) } } // WithWhitespaceBackground sets the background color of the whitespace. func WithWhitespaceBackground(c lipgloss.TerminalColor) WhitespaceOption { return func(w *whitespace) { w.style = w.style.Background(ToTermenvColor(w.re, c)) } } // WithWhitespaceChars sets the characters to be rendered in the whitespace. func WithWhitespaceChars(s string) WhitespaceOption { return func(w *whitespace) { w.chars = s } } func ToTermenvColor(re *lipgloss.Renderer, c lipgloss.TerminalColor) termenv.Color { color := c.(lipgloss.Color) return re.ColorProfile().Color(string(color)) }