fzgo/data.go

144 lines
3.1 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
"sync"
"github.com/charmbracelet/bubbles/list"
)
type Ranking struct {
items []string
indexes []int
scores []float64
}
func (r Ranking) Len() int { return len(r.items) }
func (r Ranking) Swap(i, j int) {
r.indexes[i], r.indexes[j] = r.indexes[j], r.indexes[i]
}
func (r Ranking) Less(i, j int) bool {
return r.scores[r.indexes[i]] > r.scores[r.indexes[j]]
}
// Function to compute the score for a given string
func computeScore(term string, s string) float64 {
term = strings.ToLower(term)
a := strings.ToLower(s)
splits := strings.Split(a, "/")
term_splits := strings.Split(term, "/")
score := 1.0 / float64(len(splits))
used := make([]bool, len(term_splits))
for i, term := range term_splits {
if used[i] {
continue
}
for j, c := range splits {
if len(term) == 0 {
continue
}
if strings.Contains(c, term) {
used[i] = true
score += 1.0/float64(j)
splits = splits[j+1:]
break
}
}
}
return score
}
func rank(term string, targets []string) []int {
scores := make([]float64, len(targets))
var wg sync.WaitGroup
scoreChan := make(chan struct {
index int
score float64
}, len(targets))
// Start a goroutine for each string to compute its score
for i, s := range targets {
wg.Add(1)
go func(i int, s string) {
defer wg.Done()
score := computeScore(term, s)
scoreChan <- struct {
index int
score float64
}{index: i, score: score}
}(i, s)
}
// Close the channel once all goroutines are done
go func() {
wg.Wait()
close(scoreChan)
}()
// Collect scores from the channel
for result := range scoreChan {
scores[result.index] = result.score
}
indexes := make([]int, len(targets))
for i := range targets {
indexes[i] = i
}
sort.Stable(Ranking{targets, indexes, scores})
return indexes
}
func Filter(term string, targets []string) []list.Rank {
indexes := rank(term, targets)
result := make([]list.Rank, len(targets))
for i := range targets {
result[i] = list.Rank{
Index: indexes[i],
MatchedIndexes: []int{},
}
}
return result
}
func getPaths() []string {
paths := []string{}
file, err := os.Open("/home/user/.cache/fzy_paths_d")
if err != nil {
fmt.Fprintln(os.Stderr, "Error opening file:", err)
return paths
}
defer file.Close() // Ensure the file is closed when we're done
// Create a scanner to read the file line by line
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if len(line) == 0 {
continue
}
paths = append(paths, line)
}
// Check for errors during scanning
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "Error reading file:", err)
}
return paths
}
func getListItems() []list.Item {
items := []list.Item{}
paths := getPaths()
for _, path := range paths {
items = append(items, item{path})
}
return items
}