mirror of
https://github.com/peco/peco.git
synced 2026-09-10 07:16:29 -04:00
70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
package filter
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"github.com/peco/peco/internal/util"
|
|
"github.com/peco/peco/line"
|
|
"github.com/peco/peco/pipeline"
|
|
)
|
|
|
|
// NewFuzzy builds a fuzzy-finder type of filter.
|
|
// In effect, this uses a smart case filter, and for q query
|
|
// like "ABC" it matches the equivalent of "A(.*)B(.*)C(.*)"
|
|
func NewFuzzy() *Fuzzy {
|
|
return &Fuzzy{}
|
|
}
|
|
|
|
func (ff Fuzzy) BufSize() int {
|
|
return 0
|
|
}
|
|
|
|
func (ff *Fuzzy) NewContext(ctx context.Context, query string) context.Context {
|
|
return newContext(ctx, query)
|
|
}
|
|
|
|
func (ff Fuzzy) String() string {
|
|
return "Fuzzy"
|
|
}
|
|
|
|
func (ff *Fuzzy) Apply(ctx context.Context, lines []line.Line, out pipeline.ChanOutput) error {
|
|
originalQuery := ctx.Value(queryKey).(string)
|
|
hasUpper := util.ContainsUpper(originalQuery)
|
|
|
|
OUTER:
|
|
for _, l := range lines {
|
|
base := 0
|
|
matches := [][]int{}
|
|
txt := l.DisplayString()
|
|
query := originalQuery
|
|
for len(query) > 0 {
|
|
r, n := utf8.DecodeRuneInString(query)
|
|
query = query[n:]
|
|
if r == utf8.RuneError {
|
|
// "Silently" ignore
|
|
continue OUTER
|
|
}
|
|
|
|
var i int
|
|
if hasUpper { // explicit match
|
|
i = strings.IndexRune(txt, r)
|
|
} else {
|
|
i = strings.IndexFunc(txt, util.CaseInsensitiveIndexFunc(r))
|
|
}
|
|
if i == -1 {
|
|
continue OUTER
|
|
}
|
|
|
|
// otherwise we have a match, but the next match must match against
|
|
// something AFTER the current match
|
|
txt = txt[i+n:]
|
|
matches = append(matches, []int{base + i, base + i + n})
|
|
base = base + i + n
|
|
}
|
|
out.Send(line.NewMatched(l, matches))
|
|
}
|
|
return nil
|
|
}
|