1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
package textstyles
import (
"unicode"
"github.com/walles/moor/v2/twin"
)
// Like twin.StyledRune, but with additional metadata
type CellWithMetadata struct {
Rune rune
Style twin.Style
cachedWidth *int
StartsSearchHit bool // True if this cell is the start of a search hit
IsSearchHit bool // True if this cell is part of a search hit
}
// Required for some tests to pass
func (r CellWithMetadata) Equal(b CellWithMetadata) bool {
if r.Rune != b.Rune {
return false
}
if !r.Style.Equal(b.Style) {
return false
}
if r.IsSearchHit != b.IsSearchHit {
return false
}
if r.StartsSearchHit != b.StartsSearchHit {
return false
}
return true
}
func (r CellWithMetadata) ToStyledRune() twin.StyledRune {
return twin.NewStyledRune(r.Rune, r.Style)
}
func (r *CellWithMetadata) Width() int {
if r.cachedWidth != nil {
return *r.cachedWidth
}
// Cache it
w := r.ToStyledRune().Width()
r.cachedWidth = &w
return w
}
type CellWithMetadataSlice []CellWithMetadata
func (runes CellWithMetadataSlice) Equal(other CellWithMetadataSlice) bool {
if len(runes) != len(other) {
return false
}
for i := range runes {
if !runes[i].Equal(other[i]) {
return false
}
}
return true
}
// Returns a copy of the slice with leading whitespace removed
func (runes CellWithMetadataSlice) WithoutSpaceLeft() CellWithMetadataSlice {
for i := range runes {
cell := runes[i]
if !unicode.IsSpace(cell.Rune) {
return runes[i:]
}
// That was a space, keep looking
}
// All whitespace, return empty
return CellWithMetadataSlice{}
}
// Returns a copy of the slice with trailing whitespace removed
func (runes CellWithMetadataSlice) WithoutSpaceRight() CellWithMetadataSlice {
for i := len(runes) - 1; i >= 0; i-- {
cell := runes[i]
if !unicode.IsSpace(cell.Rune) {
return runes[0 : i+1]
}
// That was a space, keep looking
}
// All whitespace, return empty
return CellWithMetadataSlice{}
}
func (runes CellWithMetadataSlice) ContainsSearchHit() bool {
for _, cell := range runes {
if cell.IsSearchHit {
return true
}
}
return false
}
|