This repository has been archived on 2026-02-10. You can view files and clone it, but cannot push or open issues or pull requests.
Files
horsebot/autocomplete/autocomplete.go

57 lines
1.3 KiB
Go

package autocomplete
import (
"bytes"
"cmp"
"slices"
"sync"
"github.com/junegunn/fzf/src/algo"
"github.com/junegunn/fzf/src/util"
)
// Set is an autocomplete set.
type Set[V any] struct {
keys []util.Chars
vals []V
}
// Add associates a value with a key in the autocomplete set.
// The behavior is undefined if the key already has a value.
func (s *Set[V]) Add(key string, val V) {
k := util.ToChars([]byte(key))
i, _ := slices.BinarySearchFunc(s.keys, k, func(a, b util.Chars) int {
return bytes.Compare(a.Bytes(), b.Bytes())
})
s.keys = slices.Insert(s.keys, i, k)
s.vals = slices.Insert(s.vals, i, val)
}
// Find appends to r all values in the set with keys that key matches.
func (s *Set[V]) Find(r []V, key string) []V {
initFzf()
var (
p = []rune(key)
got []V
t []algo.Result
slab util.Slab
)
for i := range s.keys {
res, _ := algo.FuzzyMatchV2(false, true, true, &s.keys[i], p, false, &slab)
if res.Score <= 0 {
continue
}
j, _ := slices.BinarySearchFunc(t, res, func(a, b algo.Result) int { return -cmp.Compare(a.Score, b.Score) })
// Insert after all other matches with the same score for stability.
for j < len(t) && t[j].Score == res.Score {
j++
}
t = slices.Insert(t, j, res)
got = slices.Insert(got, j, s.vals[i])
}
return append(r, got...)
}
var initFzf = sync.OnceFunc(func() { algo.Init("default") })