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 := 0.0 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 } } } if score > 0 { score += 1.0/float64(strings.Count(a, "/")+1) } 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 getPathsFromFile(path string) []string { paths := []string{} file, err := os.Open(path) 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 getPathsFromStdin() []string { paths := []string{} scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { line := scanner.Text() // Get the current line paths = append(paths, line) } // Check for errors during scanning if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "Error reading from stdin:", err) } return paths } func getListItems() []list.Item { items := []list.Item{} // paths := getPathsFromFile("/home/user/.cache/fzy_paths_d") paths := getPathsFromStdin() for _, path := range paths { if len(path) == 0 { continue } items = append(items, item{path}) } return items }