mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2024-11-30 00:33:56 +00:00
Simplify Item structure
This commit compensates for the performance overhead from the extended tiebreak option.
This commit is contained in:
parent
1d2d32c847
commit
8d3a302a17
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
func TestChunkList(t *testing.T) {
|
func TestChunkList(t *testing.T) {
|
||||||
// FIXME global
|
// FIXME global
|
||||||
sortCriteria = []criterion{byMatchLen, byLength, byIndex}
|
sortCriteria = []criterion{byMatchLen, byLength}
|
||||||
|
|
||||||
cl := NewChunkList(func(s []byte, i int) *Item {
|
cl := NewChunkList(func(s []byte, i int) *Item {
|
||||||
return &Item{text: []rune(string(s)), rank: buildEmptyRank(int32(i * 2))}
|
return &Item{text: []rune(string(s)), rank: buildEmptyRank(int32(i * 2))}
|
||||||
@ -39,7 +39,7 @@ func TestChunkList(t *testing.T) {
|
|||||||
if len(*chunk1) != 2 {
|
if len(*chunk1) != 2 {
|
||||||
t.Error("Snapshot should contain only two items")
|
t.Error("Snapshot should contain only two items")
|
||||||
}
|
}
|
||||||
last := func(arr []int32) int32 {
|
last := func(arr [5]int32) int32 {
|
||||||
return arr[len(arr)-1]
|
return arr[len(arr)-1]
|
||||||
}
|
}
|
||||||
if string((*chunk1)[0].text) != "hello" || last((*chunk1)[0].rank) != 0 ||
|
if string((*chunk1)[0].text) != "hello" || last((*chunk1)[0].rank) != 0 ||
|
||||||
|
@ -103,7 +103,6 @@ func Run(opts *Options) {
|
|||||||
runes, colors := ansiProcessor(data)
|
runes, colors := ansiProcessor(data)
|
||||||
return &Item{
|
return &Item{
|
||||||
text: runes,
|
text: runes,
|
||||||
index: int32(index),
|
|
||||||
colors: colors,
|
colors: colors,
|
||||||
rank: buildEmptyRank(int32(index))}
|
rank: buildEmptyRank(int32(index))}
|
||||||
})
|
})
|
||||||
@ -120,7 +119,6 @@ func Run(opts *Options) {
|
|||||||
item := Item{
|
item := Item{
|
||||||
text: joinTokens(trans),
|
text: joinTokens(trans),
|
||||||
origText: &runes,
|
origText: &runes,
|
||||||
index: int32(index),
|
|
||||||
colors: nil,
|
colors: nil,
|
||||||
rank: buildEmptyRank(int32(index))}
|
rank: buildEmptyRank(int32(index))}
|
||||||
|
|
||||||
|
40
src/item.go
40
src/item.go
@ -20,41 +20,41 @@ type Item struct {
|
|||||||
text []rune
|
text []rune
|
||||||
origText *[]rune
|
origText *[]rune
|
||||||
transformed []Token
|
transformed []Token
|
||||||
index int32
|
|
||||||
offsets []Offset
|
offsets []Offset
|
||||||
colors []ansiOffset
|
colors []ansiOffset
|
||||||
rank []int32
|
rank [5]int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort criteria to use. Never changes once fzf is started.
|
// Sort criteria to use. Never changes once fzf is started.
|
||||||
var sortCriteria []criterion
|
var sortCriteria []criterion
|
||||||
|
|
||||||
func isRankValid(rank []int32) bool {
|
func isRankValid(rank [5]int32) bool {
|
||||||
// Exclude ordinal index
|
// Exclude ordinal index
|
||||||
for i := 0; i < len(rank)-1; i++ {
|
for _, r := range rank[:4] {
|
||||||
if rank[i] > 0 {
|
if r > 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildEmptyRank(index int32) []int32 {
|
func buildEmptyRank(index int32) [5]int32 {
|
||||||
len := len(sortCriteria)
|
return [5]int32{0, 0, 0, 0, index}
|
||||||
arr := make([]int32, len)
|
}
|
||||||
arr[len-1] = index
|
|
||||||
return arr
|
func (item *Item) Index() int32 {
|
||||||
|
return item.rank[4]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rank calculates rank of the Item
|
// Rank calculates rank of the Item
|
||||||
func (item *Item) Rank(cache bool) []int32 {
|
func (item *Item) Rank(cache bool) [5]int32 {
|
||||||
if cache && isRankValid(item.rank) {
|
if cache && isRankValid(item.rank) {
|
||||||
return item.rank
|
return item.rank
|
||||||
}
|
}
|
||||||
matchlen := 0
|
matchlen := 0
|
||||||
prevEnd := 0
|
prevEnd := 0
|
||||||
lenSum := 0
|
lenSum := 0
|
||||||
minBegin := math.MaxUint16
|
minBegin := math.MaxInt32
|
||||||
for _, offset := range item.offsets {
|
for _, offset := range item.offsets {
|
||||||
begin := int(offset[0])
|
begin := int(offset[0])
|
||||||
end := int(offset[1])
|
end := int(offset[1])
|
||||||
@ -76,7 +76,7 @@ func (item *Item) Rank(cache bool) []int32 {
|
|||||||
if matchlen == 0 {
|
if matchlen == 0 {
|
||||||
matchlen = math.MaxInt32
|
matchlen = math.MaxInt32
|
||||||
}
|
}
|
||||||
rank := make([]int32, len(sortCriteria))
|
rank := buildEmptyRank(item.Index())
|
||||||
for idx, criterion := range sortCriteria {
|
for idx, criterion := range sortCriteria {
|
||||||
var val int32
|
var val int32
|
||||||
switch criterion {
|
switch criterion {
|
||||||
@ -100,8 +100,6 @@ func (item *Item) Rank(cache bool) []int32 {
|
|||||||
// Empty offsets due to inverse terms.
|
// Empty offsets due to inverse terms.
|
||||||
val = 1
|
val = 1
|
||||||
}
|
}
|
||||||
case byIndex:
|
|
||||||
val = item.index
|
|
||||||
}
|
}
|
||||||
rank[idx] = val
|
rank[idx] = val
|
||||||
}
|
}
|
||||||
@ -269,19 +267,15 @@ func (a ByRelevanceTac) Less(i, j int) bool {
|
|||||||
return compareRanks(irank, jrank, true)
|
return compareRanks(irank, jrank, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareRanks(irank []int32, jrank []int32, tac bool) bool {
|
func compareRanks(irank [5]int32, jrank [5]int32, tac bool) bool {
|
||||||
lastIdx := len(irank) - 1
|
for idx := 0; idx < 4; idx++ {
|
||||||
for idx, left := range irank {
|
left := irank[idx]
|
||||||
right := jrank[idx]
|
right := jrank[idx]
|
||||||
if tac && idx == lastIdx {
|
|
||||||
left = left * -1
|
|
||||||
right = right * -1
|
|
||||||
}
|
|
||||||
if left < right {
|
if left < right {
|
||||||
return true
|
return true
|
||||||
} else if left > right {
|
} else if left > right {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return (irank[4] <= jrank[4]) != tac
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,17 @@ func TestOffsetSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRankComparison(t *testing.T) {
|
func TestRankComparison(t *testing.T) {
|
||||||
if compareRanks([]int32{3, 0, 5}, []int32{2, 0, 7}, false) ||
|
if compareRanks([5]int32{3, 0, 0, 0, 5}, [5]int32{2, 0, 0, 0, 7}, false) ||
|
||||||
!compareRanks([]int32{3, 0, 5}, []int32{3, 0, 6}, false) ||
|
!compareRanks([5]int32{3, 0, 0, 0, 5}, [5]int32{3, 0, 0, 0, 6}, false) ||
|
||||||
!compareRanks([]int32{1, 2, 3}, []int32{1, 3, 2}, false) ||
|
!compareRanks([5]int32{1, 2, 0, 0, 3}, [5]int32{1, 3, 0, 0, 2}, false) ||
|
||||||
!compareRanks([]int32{0, 0, 0}, []int32{0, 0, 0}, false) {
|
!compareRanks([5]int32{0, 0, 0, 0, 0}, [5]int32{0, 0, 0, 0, 0}, false) {
|
||||||
t.Error("Invalid order")
|
t.Error("Invalid order")
|
||||||
}
|
}
|
||||||
|
|
||||||
if compareRanks([]int32{3, 0, 5}, []int32{2, 0, 7}, true) ||
|
if compareRanks([5]int32{3, 0, 0, 0, 5}, [5]int32{2, 0, 0, 0, 7}, true) ||
|
||||||
!compareRanks([]int32{3, 0, 5}, []int32{3, 0, 6}, false) ||
|
!compareRanks([5]int32{3, 0, 0, 0, 5}, [5]int32{3, 0, 0, 0, 6}, false) ||
|
||||||
!compareRanks([]int32{1, 2, 3}, []int32{1, 3, 2}, true) ||
|
!compareRanks([5]int32{1, 2, 0, 0, 3}, [5]int32{1, 3, 0, 0, 2}, true) ||
|
||||||
!compareRanks([]int32{0, 0, 0}, []int32{0, 0, 0}, false) {
|
!compareRanks([5]int32{0, 0, 0, 0, 0}, [5]int32{0, 0, 0, 0, 0}, false) {
|
||||||
t.Error("Invalid order (tac)")
|
t.Error("Invalid order (tac)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,16 +41,16 @@ func TestRankComparison(t *testing.T) {
|
|||||||
// Match length, string length, index
|
// Match length, string length, index
|
||||||
func TestItemRank(t *testing.T) {
|
func TestItemRank(t *testing.T) {
|
||||||
// FIXME global
|
// FIXME global
|
||||||
sortCriteria = []criterion{byMatchLen, byLength, byIndex}
|
sortCriteria = []criterion{byMatchLen, byLength}
|
||||||
|
|
||||||
strs := [][]rune{[]rune("foo"), []rune("foobar"), []rune("bar"), []rune("baz")}
|
strs := [][]rune{[]rune("foo"), []rune("foobar"), []rune("bar"), []rune("baz")}
|
||||||
item1 := Item{text: strs[0], index: 1, offsets: []Offset{}}
|
item1 := Item{text: strs[0], offsets: []Offset{}, rank: [5]int32{0, 0, 0, 0, 1}}
|
||||||
rank1 := item1.Rank(true)
|
rank1 := item1.Rank(true)
|
||||||
if rank1[0] != math.MaxInt32 || rank1[1] != 3 || rank1[2] != 1 {
|
if rank1[0] != math.MaxInt32 || rank1[1] != 3 || rank1[4] != 1 {
|
||||||
t.Error(item1.Rank(true))
|
t.Error(item1.Rank(true))
|
||||||
}
|
}
|
||||||
// Only differ in index
|
// Only differ in index
|
||||||
item2 := Item{text: strs[0], index: 0, offsets: []Offset{}}
|
item2 := Item{text: strs[0], offsets: []Offset{}}
|
||||||
|
|
||||||
items := []*Item{&item1, &item2}
|
items := []*Item{&item1, &item2}
|
||||||
sort.Sort(ByRelevance(items))
|
sort.Sort(ByRelevance(items))
|
||||||
@ -66,10 +66,10 @@ func TestItemRank(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort by relevance
|
// Sort by relevance
|
||||||
item3 := Item{text: strs[1], rank: []int32{0, 0, 2}, offsets: []Offset{Offset{1, 3}, Offset{5, 7}}}
|
item3 := Item{text: strs[1], rank: [5]int32{0, 0, 0, 0, 2}, offsets: []Offset{Offset{1, 3}, Offset{5, 7}}}
|
||||||
item4 := Item{text: strs[1], rank: []int32{0, 0, 2}, offsets: []Offset{Offset{1, 2}, Offset{6, 7}}}
|
item4 := Item{text: strs[1], rank: [5]int32{0, 0, 0, 0, 2}, offsets: []Offset{Offset{1, 2}, Offset{6, 7}}}
|
||||||
item5 := Item{text: strs[2], rank: []int32{0, 0, 2}, offsets: []Offset{Offset{1, 3}, Offset{5, 7}}}
|
item5 := Item{text: strs[2], rank: [5]int32{0, 0, 0, 0, 2}, offsets: []Offset{Offset{1, 3}, Offset{5, 7}}}
|
||||||
item6 := Item{text: strs[2], rank: []int32{0, 0, 2}, offsets: []Offset{Offset{1, 2}, Offset{6, 7}}}
|
item6 := Item{text: strs[2], rank: [5]int32{0, 0, 0, 0, 2}, offsets: []Offset{Offset{1, 2}, Offset{6, 7}}}
|
||||||
items = []*Item{&item1, &item2, &item3, &item4, &item5, &item6}
|
items = []*Item{&item1, &item2, &item3, &item4, &item5, &item6}
|
||||||
sort.Sort(ByRelevance(items))
|
sort.Sort(ByRelevance(items))
|
||||||
if items[0] != &item6 || items[1] != &item4 ||
|
if items[0] != &item6 || items[1] != &item4 ||
|
||||||
|
@ -23,7 +23,7 @@ func randItem() *Item {
|
|||||||
}
|
}
|
||||||
return &Item{
|
return &Item{
|
||||||
text: []rune(str),
|
text: []rune(str),
|
||||||
index: rand.Int31(),
|
rank: buildEmptyRank(rand.Int31()),
|
||||||
offsets: offsets}
|
offsets: offsets}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ const (
|
|||||||
byLength
|
byLength
|
||||||
byBegin
|
byBegin
|
||||||
byEnd
|
byEnd
|
||||||
byIndex
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func defaultMargin() [4]string {
|
func defaultMargin() [4]string {
|
||||||
@ -147,7 +146,7 @@ func defaultOptions() *Options {
|
|||||||
Delimiter: Delimiter{},
|
Delimiter: Delimiter{},
|
||||||
Sort: 1000,
|
Sort: 1000,
|
||||||
Tac: false,
|
Tac: false,
|
||||||
Criteria: []criterion{byMatchLen, byLength, byIndex},
|
Criteria: []criterion{byMatchLen, byLength},
|
||||||
Multi: false,
|
Multi: false,
|
||||||
Ansi: false,
|
Ansi: false,
|
||||||
Mouse: true,
|
Mouse: true,
|
||||||
@ -382,7 +381,6 @@ func parseTiebreak(str string) []criterion {
|
|||||||
switch str {
|
switch str {
|
||||||
case "index":
|
case "index":
|
||||||
check(&hasIndex, "index")
|
check(&hasIndex, "index")
|
||||||
criteria = append(criteria, byIndex)
|
|
||||||
case "length":
|
case "length":
|
||||||
check(&hasLength, "length")
|
check(&hasLength, "length")
|
||||||
criteria = append(criteria, byLength)
|
criteria = append(criteria, byLength)
|
||||||
@ -396,9 +394,6 @@ func parseTiebreak(str string) []criterion {
|
|||||||
errorExit("invalid sort criterion: " + str)
|
errorExit("invalid sort criterion: " + str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !hasIndex {
|
|
||||||
criteria = append(criteria, byIndex)
|
|
||||||
}
|
|
||||||
return criteria
|
return criteria
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,10 +306,9 @@ func dupItem(item *Item, offsets []Offset) *Item {
|
|||||||
text: item.text,
|
text: item.text,
|
||||||
origText: item.origText,
|
origText: item.origText,
|
||||||
transformed: item.transformed,
|
transformed: item.transformed,
|
||||||
index: item.index,
|
|
||||||
offsets: offsets,
|
offsets: offsets,
|
||||||
colors: item.colors,
|
colors: item.colors,
|
||||||
rank: buildEmptyRank(item.index)}
|
rank: buildEmptyRank(item.Index())}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pattern) basicMatch(item *Item) (int, int, int) {
|
func (p *Pattern) basicMatch(item *Item) (int, int, int) {
|
||||||
|
@ -464,7 +464,6 @@ func (t *Terminal) printHeader() {
|
|||||||
state = newState
|
state = newState
|
||||||
item := &Item{
|
item := &Item{
|
||||||
text: []rune(trimmed),
|
text: []rune(trimmed),
|
||||||
index: 0,
|
|
||||||
colors: colors,
|
colors: colors,
|
||||||
rank: buildEmptyRank(0)}
|
rank: buildEmptyRank(0)}
|
||||||
|
|
||||||
@ -491,7 +490,7 @@ func (t *Terminal) printList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) printItem(item *Item, current bool) {
|
func (t *Terminal) printItem(item *Item, current bool) {
|
||||||
_, selected := t.selected[item.index]
|
_, selected := t.selected[item.Index()]
|
||||||
if current {
|
if current {
|
||||||
C.CPrint(C.ColCursor, true, ">")
|
C.CPrint(C.ColCursor, true, ">")
|
||||||
if selected {
|
if selected {
|
||||||
@ -836,8 +835,8 @@ func (t *Terminal) Loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectItem := func(item *Item) bool {
|
selectItem := func(item *Item) bool {
|
||||||
if _, found := t.selected[item.index]; !found {
|
if _, found := t.selected[item.Index()]; !found {
|
||||||
t.selected[item.index] = selectedItem{time.Now(), item.StringPtr(t.ansi)}
|
t.selected[item.Index()] = selectedItem{time.Now(), item.StringPtr(t.ansi)}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -845,7 +844,7 @@ func (t *Terminal) Loop() {
|
|||||||
toggleY := func(y int) {
|
toggleY := func(y int) {
|
||||||
item := t.merger.Get(y)
|
item := t.merger.Get(y)
|
||||||
if !selectItem(item) {
|
if !selectItem(item) {
|
||||||
delete(t.selected, item.index)
|
delete(t.selected, item.Index())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toggle := func() {
|
toggle := func() {
|
||||||
@ -934,7 +933,7 @@ func (t *Terminal) Loop() {
|
|||||||
if t.multi {
|
if t.multi {
|
||||||
for i := 0; i < t.merger.Length(); i++ {
|
for i := 0; i < t.merger.Length(); i++ {
|
||||||
item := t.merger.Get(i)
|
item := t.merger.Get(i)
|
||||||
delete(t.selected, item.index)
|
delete(t.selected, item.Index())
|
||||||
}
|
}
|
||||||
req(reqList, reqInfo)
|
req(reqList, reqInfo)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user