mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-17 15:53:39 -05:00
Rewrite fzf in Go
This commit is contained in:
135
src/item.go
Normal file
135
src/item.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package fzf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Offset [2]int
|
||||
|
||||
type Item struct {
|
||||
text *string
|
||||
origText *string
|
||||
offsets []Offset
|
||||
index int
|
||||
rank Rank
|
||||
transformed *Transformed
|
||||
}
|
||||
|
||||
type Rank [3]int
|
||||
|
||||
var NilRank = Rank{-1, 0, 0}
|
||||
|
||||
func (i *Item) Rank() Rank {
|
||||
if i.rank[0] > 0 {
|
||||
return i.rank
|
||||
}
|
||||
sort.Sort(ByOrder(i.offsets))
|
||||
matchlen := 0
|
||||
prevEnd := 0
|
||||
for _, offset := range i.offsets {
|
||||
begin := offset[0]
|
||||
end := offset[1]
|
||||
if prevEnd > begin {
|
||||
begin = prevEnd
|
||||
}
|
||||
if end > prevEnd {
|
||||
prevEnd = end
|
||||
}
|
||||
if end > begin {
|
||||
matchlen += end - begin
|
||||
}
|
||||
}
|
||||
i.rank = Rank{matchlen, len(*i.text), i.index}
|
||||
return i.rank
|
||||
}
|
||||
|
||||
func (i *Item) Print() {
|
||||
if i.origText != nil {
|
||||
fmt.Println(*i.origText)
|
||||
} else {
|
||||
fmt.Println(*i.text)
|
||||
}
|
||||
}
|
||||
|
||||
type ByOrder []Offset
|
||||
|
||||
func (a ByOrder) Len() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
func (a ByOrder) Swap(i, j int) {
|
||||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
|
||||
func (a ByOrder) Less(i, j int) bool {
|
||||
ioff := a[i]
|
||||
joff := a[j]
|
||||
return (ioff[0] < joff[0]) || (ioff[0] == joff[0]) && (ioff[1] <= joff[1])
|
||||
}
|
||||
|
||||
type ByRelevance []*Item
|
||||
|
||||
func (a ByRelevance) Len() int {
|
||||
return len(a)
|
||||
}
|
||||
|
||||
func (a ByRelevance) Swap(i, j int) {
|
||||
a[i], a[j] = a[j], a[i]
|
||||
}
|
||||
|
||||
func (a ByRelevance) Less(i, j int) bool {
|
||||
irank := a[i].Rank()
|
||||
jrank := a[j].Rank()
|
||||
|
||||
return compareRanks(irank, jrank)
|
||||
}
|
||||
|
||||
func compareRanks(irank Rank, jrank Rank) bool {
|
||||
for idx := range irank {
|
||||
if irank[idx] < jrank[idx] {
|
||||
return true
|
||||
} else if irank[idx] > jrank[idx] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func SortMerge(partialResults [][]*Item) []*Item {
|
||||
if len(partialResults) == 1 {
|
||||
return partialResults[0]
|
||||
}
|
||||
|
||||
merged := []*Item{}
|
||||
|
||||
for len(partialResults) > 0 {
|
||||
minRank := Rank{0, 0, 0}
|
||||
minIdx := -1
|
||||
|
||||
for idx, partialResult := range partialResults {
|
||||
if len(partialResult) > 0 {
|
||||
rank := partialResult[0].Rank()
|
||||
if minIdx < 0 || compareRanks(rank, minRank) {
|
||||
minRank = rank
|
||||
minIdx = idx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if minIdx >= 0 {
|
||||
merged = append(merged, partialResults[minIdx][0])
|
||||
partialResults[minIdx] = partialResults[minIdx][1:]
|
||||
}
|
||||
|
||||
nonEmptyPartialResults := make([][]*Item, 0, len(partialResults))
|
||||
for _, partialResult := range partialResults {
|
||||
if len(partialResult) > 0 {
|
||||
nonEmptyPartialResults = append(nonEmptyPartialResults, partialResult)
|
||||
}
|
||||
}
|
||||
partialResults = nonEmptyPartialResults
|
||||
}
|
||||
|
||||
return merged
|
||||
}
|
||||
Reference in New Issue
Block a user