Cleanup highlighting of positions in text and add some tests

This commit is contained in:
Kovid Goyal
2025-12-05 09:40:36 +05:30
parent 71a7dda522
commit 7075f71da4
2 changed files with 88 additions and 31 deletions

View File

@@ -62,6 +62,45 @@ const matching_position_style = "fg=green"
const selected_style = "fg=magenta"
const current_style = "fg=intense-white bold"
type text_chunk struct {
text string
emphasize bool
}
func split_up_text(text string, add_ellipsis bool, positions []int) func(func(x text_chunk) bool) {
return func(yield func(x text_chunk) bool) {
if len(positions) == 0 {
if !yield(text_chunk{text, false}) {
return
}
} else {
at := 0
runes := []rune(text)
limit := len(runes)
for _, p := range positions {
if max(p, at) >= limit || p < at {
break
}
if at < p && !yield(text_chunk{string(runes[at:p]), false}) {
return
}
if !yield(text_chunk{string(runes[p]), true}) {
return
}
at = p + 1
}
if at < len(runes) {
if !yield(text_chunk{string(runes[at:]), false}) {
return
}
}
}
if add_ellipsis {
yield(text_chunk{"…", false})
}
}
}
func (h *Handler) render_match_with_positions(text string, add_ellipsis bool, positions []int, is_current bool) {
prefix, suffix, _ := strings.Cut(h.lp.SprintStyled(matching_position_style, " "), " ")
if is_current {
@@ -70,39 +109,16 @@ func (h *Handler) render_match_with_positions(text string, add_ellipsis bool, po
defer h.lp.QueueWriteString(s)
suffix += p
}
write_chunk := func(text string, emphasize bool) {
if text == "" {
return
}
if emphasize {
h.lp.QueueWriteString(prefix)
defer func() {
h.lp.QueueWriteString(suffix)
}()
}
h.lp.QueueWriteString(text)
}
if len(positions) == 0 {
write_chunk(text, false)
} else {
at := 0
runes := []rune(text)
limit := len(runes)
for _, p := range positions {
if p >= limit || at >= limit || p <= at {
break
for chunk := range split_up_text(text, add_ellipsis, positions) {
if chunk.text != "" {
if chunk.emphasize {
h.lp.QueueWriteString(prefix)
defer func() {
h.lp.QueueWriteString(suffix)
}()
}
before := runes[at:p]
write_chunk(string(before), false)
write_chunk(string(runes[p]), true)
at = p + 1
h.lp.QueueWriteString(chunk.text)
}
if at < len(runes) {
write_chunk(string(runes[at:]), false)
}
}
if add_ellipsis {
write_chunk("…", false)
}
}

View File

@@ -0,0 +1,41 @@
package choose_files
import (
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
)
var _ = fmt.Print
func TestSplitWithPositions(t *testing.T) {
for _, c := range []struct {
src string
positions []int
expected []string
}{
{"abc", nil, []string{"abc"}},
{"abc", []int{0}, []string{"a", "bc"}},
{"abc", []int{1}, []string{"a", "b", "c"}},
{"abc", []int{2}, []string{"ab", "c"}},
{"abc", []int{0, 1}, []string{"a", "b", "c"}},
{"abc", []int{0, 1, 2}, []string{"a", "b", "c"}},
{"abc", []int{0, 2}, []string{"a", "b", "c"}},
// invalid positions
{"abc", []int{-1}, []string{"abc"}},
{"abc", []int{3}, []string{"abc"}},
{"abc", []int{0, 3}, []string{"a", "bc"}},
{"abc", []int{2, 0}, []string{"ab", "c"}},
{"abc", []int{2, 1}, []string{"ab", "c"}},
{"abc", []int{1, 0}, []string{"a", "b", "c"}},
} {
actual := make([]string, 0, len(c.expected))
for ch := range split_up_text(c.src, false, c.positions) {
actual = append(actual, ch.text)
}
if diff := cmp.Diff(c.expected, actual); diff != "" {
t.Fatalf("Failed for src: %#v positions: %v\n%s", c.src, c.positions, diff)
}
}
}