mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-28 03:01:57 +02:00
Cleanup highlighting of positions in text and add some tests
This commit is contained in:
@@ -62,6 +62,45 @@ const matching_position_style = "fg=green"
|
|||||||
const selected_style = "fg=magenta"
|
const selected_style = "fg=magenta"
|
||||||
const current_style = "fg=intense-white bold"
|
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) {
|
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, " "), " ")
|
prefix, suffix, _ := strings.Cut(h.lp.SprintStyled(matching_position_style, " "), " ")
|
||||||
if is_current {
|
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)
|
defer h.lp.QueueWriteString(s)
|
||||||
suffix += p
|
suffix += p
|
||||||
}
|
}
|
||||||
write_chunk := func(text string, emphasize bool) {
|
for chunk := range split_up_text(text, add_ellipsis, positions) {
|
||||||
if text == "" {
|
if chunk.text != "" {
|
||||||
return
|
if chunk.emphasize {
|
||||||
}
|
h.lp.QueueWriteString(prefix)
|
||||||
if emphasize {
|
defer func() {
|
||||||
h.lp.QueueWriteString(prefix)
|
h.lp.QueueWriteString(suffix)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
before := runes[at:p]
|
h.lp.QueueWriteString(chunk.text)
|
||||||
write_chunk(string(before), false)
|
|
||||||
write_chunk(string(runes[p]), true)
|
|
||||||
at = p + 1
|
|
||||||
}
|
}
|
||||||
if at < len(runes) {
|
|
||||||
write_chunk(string(runes[at:]), false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if add_ellipsis {
|
|
||||||
write_chunk("…", false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
kittens/choose_files/results_test.go
Normal file
41
kittens/choose_files/results_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user