package ui
import (
"git.sr.ht/~rockorager/vaxis"
)
func StyledString(s string) *vaxis.StyledString {
return state.vx.NewStyledString(s, vaxis.Style{})
}
// Applies a style to a string. Any currently applied styles will not be overwritten
func ApplyStyle(style vaxis.Style, str string) string {
ss := StyledString(str)
d := vaxis.Style{}
for i, sr := range ss.Cells {
if sr.Style == d {
sr.Style = style
ss.Cells[i] = sr
}
}
return ss.Encode()
}
// PadLeft inserts blank spaces at the beginning of the StyledString to produce
// a string of the provided width
func PadLeft(ss *vaxis.StyledString, width int) {
w := ss.Len()
if w >= width {
return
}
cell := vaxis.Cell{
Character: vaxis.Character{
Grapheme: " ",
Width: 1,
},
}
w = width - w
cells := make([]vaxis.Cell, 0, len(ss.Cells)+w)
for w > 0 {
cells = append(cells, cell)
w -= 1
}
cells = append(cells, ss.Cells...)
ss.Cells = cells
}
// PadLeft inserts blank spaces at the end of the StyledString to produce
// a string of the provided width
func PadRight(ss *vaxis.StyledString, width int) {
w := ss.Len()
if w >= width {
return
}
cell := vaxis.Cell{
Character: vaxis.Character{
Grapheme: " ",
Width: 1,
},
}
w = width - w
for w > 0 {
w -= 1
ss.Cells = append(ss.Cells, cell)
}
}
// ApplyAttrs applies the style, and if another style is present ORs the
// attributes
func ApplyAttrs(ss *vaxis.StyledString, style vaxis.Style) {
for i, cell := range ss.Cells {
if style.Foreground != 0 {
cell.Style.Foreground = style.Foreground
}
if style.Background != 0 {
cell.Style.Background = style.Background
}
cell.Style.Attribute |= style.Attribute
if style.UnderlineColor != 0 {
cell.Style.UnderlineColor = style.UnderlineColor
}
if style.UnderlineStyle != vaxis.UnderlineOff {
cell.Style.UnderlineStyle = style.UnderlineStyle
}
ss.Cells[i] = cell
}
}
// Truncates the styled string on the right and inserts a '…' as the last
// character
func Truncate(ss *vaxis.StyledString, width int) {
if ss.Len() <= width {
return
}
cells := make([]vaxis.Cell, 0, len(ss.Cells))
total := 0
for _, cell := range ss.Cells {
if total+cell.Width >= width {
// we can't fit this cell so put in our truncator
cells = append(cells, vaxis.Cell{
Character: vaxis.Character{
Grapheme: "…",
Width: 1,
},
Style: cell.Style,
})
break
}
total += cell.Width
cells = append(cells, cell)
}
ss.Cells = cells
}
// TruncateHead truncates the left side of the string and inserts '…' as the
// first character
func TruncateHead(ss *vaxis.StyledString, width int) {
l := ss.Len()
if l <= width {
return
}
offset := l - width
cells := make([]vaxis.Cell, 0, len(ss.Cells))
cells = append(cells, vaxis.Cell{
Character: vaxis.Character{
Grapheme: "…",
Width: 1,
},
})
total := 0
for _, cell := range ss.Cells {
total += cell.Width
if total < offset {
// we always have at least one for our truncator. We
// copy this cells style to it so that it retains the
// style information from the first printed cell
cells[0].Style = cell.Style
continue
}
cells = append(cells, cell)
}
ss.Cells = cells
}