add my own session manager
This commit is contained in:
+102
@@ -0,0 +1,102 @@
|
||||
// Package matching provides matching features that find appropriate strings
|
||||
// by using a passed input string.
|
||||
package matching
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/ktr0731/go-fuzzyfinder/scoring"
|
||||
)
|
||||
|
||||
// Matched represents a result of FindAll.
|
||||
type Matched struct {
|
||||
// Idx is the index of an item of the original slice which was used to
|
||||
// search matched strings.
|
||||
Idx int
|
||||
// Pos is the range of matched position.
|
||||
// [2]int represents an open interval of a position.
|
||||
Pos [2]int
|
||||
// score is the value that indicates how it similar to the input string.
|
||||
// The bigger score, the more similar it is.
|
||||
score int
|
||||
}
|
||||
|
||||
// Option represents available matching options.
|
||||
type Option func(*opt)
|
||||
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
ModeSmart Mode = iota
|
||||
ModeCaseSensitive
|
||||
ModeCaseInsensitive
|
||||
)
|
||||
|
||||
// opt represents available options and its default values.
|
||||
type opt struct {
|
||||
mode Mode
|
||||
}
|
||||
|
||||
// WithMode specifies a matching mode. The default mode is ModeSmart.
|
||||
func WithMode(m Mode) Option {
|
||||
return func(o *opt) {
|
||||
o.mode = m
|
||||
}
|
||||
}
|
||||
|
||||
// FindAll tries to find out sub-strings from slice that match the passed argument in.
|
||||
// The returned slice is sorted by similarity scores in descending order.
|
||||
func FindAll(in string, slice []string, opts ...Option) []Matched {
|
||||
var opt opt
|
||||
for _, o := range opts {
|
||||
o(&opt)
|
||||
}
|
||||
m := match(in, slice, opt)
|
||||
sort.Slice(m, func(i, j int) bool {
|
||||
if m[i].score == m[j].score {
|
||||
return m[i].Idx > m[j].Idx
|
||||
}
|
||||
return m[i].score > m[j].score
|
||||
})
|
||||
return m
|
||||
}
|
||||
|
||||
// match iterates each string of slice for check whether it is matched to the input string.
|
||||
func match(input string, slice []string, opt opt) (res []Matched) {
|
||||
if opt.mode == ModeSmart {
|
||||
// Find an upper-case rune
|
||||
n := strings.IndexFunc(input, unicode.IsUpper)
|
||||
if n == -1 {
|
||||
opt.mode = ModeCaseInsensitive
|
||||
input = strings.ToLower(input)
|
||||
} else {
|
||||
opt.mode = ModeCaseSensitive
|
||||
}
|
||||
}
|
||||
|
||||
in := []rune(input)
|
||||
for idxOfSlice, s := range slice {
|
||||
var idx int
|
||||
if opt.mode == ModeCaseInsensitive {
|
||||
s = strings.ToLower(s)
|
||||
}
|
||||
LINE_MATCHING:
|
||||
for _, r := range s {
|
||||
if r == in[idx] {
|
||||
idx++
|
||||
if idx == len(in) {
|
||||
score, pos := scoring.Calculate(s, input)
|
||||
res = append(res, Matched{
|
||||
Idx: idxOfSlice,
|
||||
Pos: pos,
|
||||
score: score,
|
||||
})
|
||||
break LINE_MATCHING
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
Reference in New Issue
Block a user