fix: multiple matches in a single line. (#1876)

mine
Mohamed Messaad 2023-03-17 16:26:10 +01:00 committed by GitHub
parent e5da1a9559
commit a5be038c99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 149 additions and 14 deletions

View File

@ -84,11 +84,11 @@ func (*YAML) rxFilter(q string, lines []string) fuzzy.Matches {
}
matches := make(fuzzy.Matches, 0, len(lines))
for i, l := range lines {
if loc := rx.FindStringIndex(l); len(loc) == 2 {
locs := rx.FindAllStringIndex(l, -1)
for _, loc := range locs {
matches = append(matches, fuzzy.Match{Str: q, Index: i, MatchedIndexes: loc})
}
}
return matches
}

View File

@ -0,0 +1,65 @@
package model
import (
"testing"
"github.com/sahilm/fuzzy"
"github.com/stretchr/testify/assert"
)
func TestYAML_rxFilter(t *testing.T) {
uu := map[string]struct {
q string
lines []string
e fuzzy.Matches
}{
"empty-lines": {
q: "foo",
e: fuzzy.Matches{},
},
"no-match": {
q: "foo",
lines: []string{"bar"},
e: fuzzy.Matches{},
},
"single-match": {
q: "foo",
lines: []string{"foo", "bar", "baz"},
e: fuzzy.Matches{
{
Str: "foo",
Index: 0,
MatchedIndexes: []int{0, 3},
},
},
},
"multiple-matches": {
q: "foo",
lines: []string{"foo", "bar", "foo bar foo", "baz"},
e: fuzzy.Matches{
{
Str: "foo",
Index: 0,
MatchedIndexes: []int{0, 3},
},
{
Str: "foo",
Index: 2,
MatchedIndexes: []int{0, 3},
},
{
Str: "foo",
Index: 2,
MatchedIndexes: []int{8, 11},
},
},
},
}
var y YAML
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
assert.Equal(t, u.e, y.rxFilter(u.q, u.lines))
})
}
}

View File

@ -92,6 +92,21 @@ func (v *LiveView) ResourceFailed(err error) {
v.text.SetText(cowTalk(err.Error(), x+w))
}
func (*LiveView) linesWithRegions(lines []string, matches fuzzy.Matches) []string {
ll := make([]string, len(lines))
copy(ll, lines)
offsetForLine := make(map[int]int)
for i, m := range matches {
loc, line := m.MatchedIndexes, ll[m.Index]
offset := offsetForLine[m.Index]
loc[0], loc[1] = loc[0]+offset, loc[1]+offset
regionStr := `<<<"search_` + strconv.Itoa(i) + `">>>` + line[loc[0]:loc[1]] + `<<<"">>>`
ll[m.Index] = line[:loc[0]] + regionStr + line[loc[1]:]
offsetForLine[m.Index] += len(regionStr) - (loc[1] - loc[0])
}
return ll
}
// ResourceChanged notifies when the filter changes.
func (v *LiveView) ResourceChanged(lines []string, matches fuzzy.Matches) {
v.app.QueueUpdateDraw(func() {
@ -101,23 +116,14 @@ func (v *LiveView) ResourceChanged(lines []string, matches fuzzy.Matches) {
v.text.SetTextAlign(tview.AlignLeft)
v.maxRegions = len(matches)
var ll []string
if len(matches) == 0 {
ll = lines
} else {
ll = make([]string, len(lines))
copy(ll, lines)
for i, m := range matches {
loc, line := m.MatchedIndexes, ll[m.Index]
ll[m.Index] = line[:loc[0]] + `<<<"search_` + strconv.Itoa(i) + `">>>` + line[loc[0]:loc[1]] + `<<<"">>>` + line[loc[1]:]
}
}
if v.text.GetText(true) == "" {
v.text.ScrollToBeginning()
}
v.text.SetText(colorizeYAML(v.app.Styles.Views().Yaml, strings.Join(ll, "\n")))
lines = v.linesWithRegions(lines, matches)
v.text.SetText(colorizeYAML(v.app.Styles.Views().Yaml, strings.Join(lines, "\n")))
v.text.Highlight()
if v.currentRegion < v.maxRegions {
v.text.Highlight("search_" + strconv.Itoa(v.currentRegion))

View File

@ -0,0 +1,64 @@
package view
import (
"strconv"
"testing"
"github.com/sahilm/fuzzy"
"github.com/stretchr/testify/assert"
)
func matchTag(i int, s string) string {
return `<<<"search_` + strconv.Itoa(i) + `">>>` + s + `<<<"">>>`
}
func TestLiveView_linesWithRegions(t *testing.T) {
uu := map[string]struct {
lines []string
matches fuzzy.Matches
e []string
}{
"empty-lines": {
e: []string{},
},
"no-match": {
lines: []string{"bar"},
e: []string{"bar"},
},
"single-match": {
lines: []string{"foo", "bar", "baz"},
matches: fuzzy.Matches{
{Index: 1, MatchedIndexes: []int{0, 3}},
},
e: []string{"foo", matchTag(0, "bar"), "baz"},
},
"multiple-matches": {
lines: []string{"foo", "bar", "baz"},
matches: fuzzy.Matches{
{Index: 1, MatchedIndexes: []int{0, 3}},
{Index: 2, MatchedIndexes: []int{0, 3}},
},
e: []string{"foo", matchTag(0, "bar"), matchTag(1, "baz")},
},
"multiple-matches-same-line": {
lines: []string{"foosfoo baz", "dfbarfoos bar"},
matches: fuzzy.Matches{
{Index: 0, MatchedIndexes: []int{0, 3}},
{Index: 0, MatchedIndexes: []int{4, 7}},
{Index: 1, MatchedIndexes: []int{5, 8}},
},
e: []string{
matchTag(0, "foo") + "s" + matchTag(1, "foo") + " baz",
"dfbar" + matchTag(2, "foo") + "s bar",
},
},
}
var v LiveView
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
t.Parallel()
assert.Equal(t, u.e, v.linesWithRegions(u.lines, u.matches))
})
}
}