Files
8bitMyGoUI/text/highlight.go
T

55 lines
1.2 KiB
Go

package text
import (
"unicode"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/8bitMyGoUI/pixel"
)
type HighlightOptions struct {
Slot pixel.Slot
// Mark is the marker slot; zero means Warn.
Mark pixel.Slot
}
// Highlight marks each match of query in s, ignoring case.
func Highlight(c *ui.Context, s, query string, o HighlightOptions) *ui.Element {
k := pixel.K(c)
mark := slotOr(o.Mark, pixel.Warn)
rs := []rune(s)
spans := matches(rs, []rune(query))
return block(c, k, s, pixel.Measure(s), pixel.LineHeight, func(g pixel.Canvas) {
for _, sp := range spans {
x0, x1 := pixel.Measure(string(rs[:sp[0]])), pixel.Measure(string(rs[:sp[1]]))
g.Veil(x0, 2, x1-x0, pixel.LineHeight-4, mark, 10)
}
g.Text(0, 0, s, o.Slot, 1)
})
}
// matches are the rune spans of q in s.
func matches(s, q []rune) [][2]int {
var out [][2]int
if len(q) == 0 {
return nil
}
for i := 0; i+len(q) <= len(s); {
same := true
for j := range q {
if unicode.ToLower(s[i+j]) != unicode.ToLower(q[j]) {
same = false
break
}
}
if same {
out = append(out, [2]int{i, i + len(q)})
i += len(q)
} else {
i++
}
}
return out
}