fix: multiple matches in a single line. (#1876)
parent
e5da1a9559
commit
a5be038c99
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue