Consolidate Result and rank structs
By not storing item index twice, we can cut down the size of Result struct and now it makes more sense to store and pass Results by values. Benchmarks show no degradation of performance by additional pointer indirection for looking up index.
This commit is contained in:
parent
5e72709613
commit
bbe10f4f77
@ -3,7 +3,7 @@ package fzf
|
|||||||
import "sync"
|
import "sync"
|
||||||
|
|
||||||
// queryCache associates strings to lists of items
|
// queryCache associates strings to lists of items
|
||||||
type queryCache map[string][]*Result
|
type queryCache map[string][]Result
|
||||||
|
|
||||||
// ChunkCache associates Chunk and query string to lists of items
|
// ChunkCache associates Chunk and query string to lists of items
|
||||||
type ChunkCache struct {
|
type ChunkCache struct {
|
||||||
@ -17,7 +17,7 @@ func NewChunkCache() ChunkCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add adds the list to the cache
|
// Add adds the list to the cache
|
||||||
func (cc *ChunkCache) Add(chunk *Chunk, key string, list []*Result) {
|
func (cc *ChunkCache) Add(chunk *Chunk, key string, list []Result) {
|
||||||
if len(key) == 0 || !chunk.IsFull() || len(list) > queryCacheMax {
|
if len(key) == 0 || !chunk.IsFull() || len(list) > queryCacheMax {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ func (cc *ChunkCache) Add(chunk *Chunk, key string, list []*Result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Lookup is called to lookup ChunkCache
|
// Lookup is called to lookup ChunkCache
|
||||||
func (cc *ChunkCache) Lookup(chunk *Chunk, key string) []*Result {
|
func (cc *ChunkCache) Lookup(chunk *Chunk, key string) []Result {
|
||||||
if len(key) == 0 || !chunk.IsFull() {
|
if len(key) == 0 || !chunk.IsFull() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ func (cc *ChunkCache) Lookup(chunk *Chunk, key string) []*Result {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ChunkCache) Search(chunk *Chunk, key string) []*Result {
|
func (cc *ChunkCache) Search(chunk *Chunk, key string) []Result {
|
||||||
if len(key) == 0 || !chunk.IsFull() {
|
if len(key) == 0 || !chunk.IsFull() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,8 @@ func TestChunkCache(t *testing.T) {
|
|||||||
chunk2 := make(Chunk, chunkSize)
|
chunk2 := make(Chunk, chunkSize)
|
||||||
chunk1p := &Chunk{}
|
chunk1p := &Chunk{}
|
||||||
chunk2p := &chunk2
|
chunk2p := &chunk2
|
||||||
items1 := []*Result{&Result{}}
|
items1 := []Result{Result{}}
|
||||||
items2 := []*Result{&Result{}, &Result{}}
|
items2 := []Result{Result{}, Result{}}
|
||||||
cache.Add(chunk1p, "foo", items1)
|
cache.Add(chunk1p, "foo", items1)
|
||||||
cache.Add(chunk2p, "foo", items1)
|
cache.Add(chunk2p, "foo", items1)
|
||||||
cache.Add(chunk2p, "bar", items2)
|
cache.Add(chunk2p, "bar", items2)
|
||||||
|
@ -131,7 +131,7 @@ func (m *Matcher) sliceChunks(chunks []*Chunk) [][]*Chunk {
|
|||||||
|
|
||||||
type partialResult struct {
|
type partialResult struct {
|
||||||
index int
|
index int
|
||||||
matches []*Result
|
matches []Result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
|
func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
|
||||||
@ -162,7 +162,7 @@ func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
|
|||||||
go func(idx int, slab *util.Slab, chunks []*Chunk) {
|
go func(idx int, slab *util.Slab, chunks []*Chunk) {
|
||||||
defer func() { waitGroup.Done() }()
|
defer func() { waitGroup.Done() }()
|
||||||
count := 0
|
count := 0
|
||||||
allMatches := make([][]*Result, len(chunks))
|
allMatches := make([][]Result, len(chunks))
|
||||||
for idx, chunk := range chunks {
|
for idx, chunk := range chunks {
|
||||||
matches := request.pattern.Match(chunk, slab)
|
matches := request.pattern.Match(chunk, slab)
|
||||||
allMatches[idx] = matches
|
allMatches[idx] = matches
|
||||||
@ -172,7 +172,7 @@ func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
|
|||||||
}
|
}
|
||||||
countChan <- len(matches)
|
countChan <- len(matches)
|
||||||
}
|
}
|
||||||
sliceMatches := make([]*Result, 0, count)
|
sliceMatches := make([]Result, 0, count)
|
||||||
for _, matches := range allMatches {
|
for _, matches := range allMatches {
|
||||||
sliceMatches = append(sliceMatches, matches...)
|
sliceMatches = append(sliceMatches, matches...)
|
||||||
}
|
}
|
||||||
@ -212,7 +212,7 @@ func (m *Matcher) scan(request MatchRequest) (*Merger, bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
partialResults := make([][]*Result, numSlices)
|
partialResults := make([][]Result, numSlices)
|
||||||
for _ = range slices {
|
for _ = range slices {
|
||||||
partialResult := <-resultChan
|
partialResult := <-resultChan
|
||||||
partialResults[partialResult.index] = partialResult.matches
|
partialResults[partialResult.index] = partialResult.matches
|
||||||
|
@ -3,14 +3,14 @@ package fzf
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// EmptyMerger is a Merger with no data
|
// EmptyMerger is a Merger with no data
|
||||||
var EmptyMerger = NewMerger(nil, [][]*Result{}, false, false)
|
var EmptyMerger = NewMerger(nil, [][]Result{}, false, false)
|
||||||
|
|
||||||
// Merger holds a set of locally sorted lists of items and provides the view of
|
// Merger holds a set of locally sorted lists of items and provides the view of
|
||||||
// a single, globally-sorted list
|
// a single, globally-sorted list
|
||||||
type Merger struct {
|
type Merger struct {
|
||||||
pattern *Pattern
|
pattern *Pattern
|
||||||
lists [][]*Result
|
lists [][]Result
|
||||||
merged []*Result
|
merged []Result
|
||||||
chunks *[]*Chunk
|
chunks *[]*Chunk
|
||||||
cursors []int
|
cursors []int
|
||||||
sorted bool
|
sorted bool
|
||||||
@ -35,11 +35,11 @@ func PassMerger(chunks *[]*Chunk, tac bool) *Merger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewMerger returns a new Merger
|
// NewMerger returns a new Merger
|
||||||
func NewMerger(pattern *Pattern, lists [][]*Result, sorted bool, tac bool) *Merger {
|
func NewMerger(pattern *Pattern, lists [][]Result, sorted bool, tac bool) *Merger {
|
||||||
mg := Merger{
|
mg := Merger{
|
||||||
pattern: pattern,
|
pattern: pattern,
|
||||||
lists: lists,
|
lists: lists,
|
||||||
merged: []*Result{},
|
merged: []Result{},
|
||||||
chunks: nil,
|
chunks: nil,
|
||||||
cursors: make([]int, len(lists)),
|
cursors: make([]int, len(lists)),
|
||||||
sorted: sorted,
|
sorted: sorted,
|
||||||
@ -59,13 +59,13 @@ func (mg *Merger) Length() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get returns the pointer to the Result object indexed by the given integer
|
// Get returns the pointer to the Result object indexed by the given integer
|
||||||
func (mg *Merger) Get(idx int) *Result {
|
func (mg *Merger) Get(idx int) Result {
|
||||||
if mg.chunks != nil {
|
if mg.chunks != nil {
|
||||||
if mg.tac {
|
if mg.tac {
|
||||||
idx = mg.count - idx - 1
|
idx = mg.count - idx - 1
|
||||||
}
|
}
|
||||||
chunk := (*mg.chunks)[idx/chunkSize]
|
chunk := (*mg.chunks)[idx/chunkSize]
|
||||||
return &Result{item: &(*chunk)[idx%chunkSize]}
|
return Result{item: &(*chunk)[idx%chunkSize]}
|
||||||
}
|
}
|
||||||
|
|
||||||
if mg.sorted {
|
if mg.sorted {
|
||||||
@ -89,7 +89,7 @@ func (mg *Merger) cacheable() bool {
|
|||||||
return mg.count < mergerCacheMax
|
return mg.count < mergerCacheMax
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mg *Merger) mergedGet(idx int) *Result {
|
func (mg *Merger) mergedGet(idx int) Result {
|
||||||
for i := len(mg.merged); i <= idx; i++ {
|
for i := len(mg.merged); i <= idx; i++ {
|
||||||
minRank := minRank()
|
minRank := minRank()
|
||||||
minIdx := -1
|
minIdx := -1
|
||||||
@ -100,7 +100,7 @@ func (mg *Merger) mergedGet(idx int) *Result {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if cursor >= 0 {
|
if cursor >= 0 {
|
||||||
rank := list[cursor].rank
|
rank := list[cursor]
|
||||||
if minIdx < 0 || compareRanks(rank, minRank, mg.tac) {
|
if minIdx < 0 || compareRanks(rank, minRank, mg.tac) {
|
||||||
minRank = rank
|
minRank = rank
|
||||||
minIdx = listIdx
|
minIdx = listIdx
|
||||||
|
@ -15,11 +15,11 @@ func assert(t *testing.T, cond bool, msg ...string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func randResult() *Result {
|
func randResult() Result {
|
||||||
str := fmt.Sprintf("%d", rand.Uint32())
|
str := fmt.Sprintf("%d", rand.Uint32())
|
||||||
return &Result{
|
chars := util.RunesToChars([]rune(str))
|
||||||
item: &Item{text: util.RunesToChars([]rune(str))},
|
chars.Index = rand.Int31()
|
||||||
rank: rank{index: rand.Int31()}}
|
return Result{item: &Item{text: chars}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmptyMerger(t *testing.T) {
|
func TestEmptyMerger(t *testing.T) {
|
||||||
@ -29,14 +29,14 @@ func TestEmptyMerger(t *testing.T) {
|
|||||||
assert(t, len(EmptyMerger.merged) == 0, "Invalid merged list")
|
assert(t, len(EmptyMerger.merged) == 0, "Invalid merged list")
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildLists(partiallySorted bool) ([][]*Result, []*Result) {
|
func buildLists(partiallySorted bool) ([][]Result, []Result) {
|
||||||
numLists := 4
|
numLists := 4
|
||||||
lists := make([][]*Result, numLists)
|
lists := make([][]Result, numLists)
|
||||||
cnt := 0
|
cnt := 0
|
||||||
for i := 0; i < numLists; i++ {
|
for i := 0; i < numLists; i++ {
|
||||||
numResults := rand.Int() % 20
|
numResults := rand.Int() % 20
|
||||||
cnt += numResults
|
cnt += numResults
|
||||||
lists[i] = make([]*Result, numResults)
|
lists[i] = make([]Result, numResults)
|
||||||
for j := 0; j < numResults; j++ {
|
for j := 0; j < numResults; j++ {
|
||||||
item := randResult()
|
item := randResult()
|
||||||
lists[i][j] = item
|
lists[i][j] = item
|
||||||
@ -45,7 +45,7 @@ func buildLists(partiallySorted bool) ([][]*Result, []*Result) {
|
|||||||
sort.Sort(ByRelevance(lists[i]))
|
sort.Sort(ByRelevance(lists[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
items := []*Result{}
|
items := []Result{}
|
||||||
for _, list := range lists {
|
for _, list := range lists {
|
||||||
items = append(items, list...)
|
items = append(items, list...)
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ func (p *Pattern) CacheKey() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Match returns the list of matches Items in the given Chunk
|
// Match returns the list of matches Items in the given Chunk
|
||||||
func (p *Pattern) Match(chunk *Chunk, slab *util.Slab) []*Result {
|
func (p *Pattern) Match(chunk *Chunk, slab *util.Slab) []Result {
|
||||||
// ChunkCache: Exact match
|
// ChunkCache: Exact match
|
||||||
cacheKey := p.CacheKey()
|
cacheKey := p.CacheKey()
|
||||||
if p.cacheable {
|
if p.cacheable {
|
||||||
@ -263,19 +263,19 @@ func (p *Pattern) Match(chunk *Chunk, slab *util.Slab) []*Result {
|
|||||||
return matches
|
return matches
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pattern) matchChunk(chunk *Chunk, space []*Result, slab *util.Slab) []*Result {
|
func (p *Pattern) matchChunk(chunk *Chunk, space []Result, slab *util.Slab) []Result {
|
||||||
matches := []*Result{}
|
matches := []Result{}
|
||||||
|
|
||||||
if space == nil {
|
if space == nil {
|
||||||
for idx := range *chunk {
|
for idx := range *chunk {
|
||||||
if match, _, _ := p.MatchItem(&(*chunk)[idx], false, slab); match != nil {
|
if match, _, _ := p.MatchItem(&(*chunk)[idx], false, slab); match != nil {
|
||||||
matches = append(matches, match)
|
matches = append(matches, *match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, result := range space {
|
for _, result := range space {
|
||||||
if match, _, _ := p.MatchItem(result.item, false, slab); match != nil {
|
if match, _, _ := p.MatchItem(result.item, false, slab); match != nil {
|
||||||
matches = append(matches, match)
|
matches = append(matches, *match)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,14 +286,16 @@ func (p *Pattern) matchChunk(chunk *Chunk, space []*Result, slab *util.Slab) []*
|
|||||||
func (p *Pattern) MatchItem(item *Item, withPos bool, slab *util.Slab) (*Result, []Offset, *[]int) {
|
func (p *Pattern) MatchItem(item *Item, withPos bool, slab *util.Slab) (*Result, []Offset, *[]int) {
|
||||||
if p.extended {
|
if p.extended {
|
||||||
if offsets, bonus, pos := p.extendedMatch(item, withPos, slab); len(offsets) == len(p.termSets) {
|
if offsets, bonus, pos := p.extendedMatch(item, withPos, slab); len(offsets) == len(p.termSets) {
|
||||||
return buildResult(item, offsets, bonus), offsets, pos
|
result := buildResult(item, offsets, bonus)
|
||||||
|
return &result, offsets, pos
|
||||||
}
|
}
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
offset, bonus, pos := p.basicMatch(item, withPos, slab)
|
offset, bonus, pos := p.basicMatch(item, withPos, slab)
|
||||||
if sidx := offset[0]; sidx >= 0 {
|
if sidx := offset[0]; sidx >= 0 {
|
||||||
offsets := []Offset{offset}
|
offsets := []Offset{offset}
|
||||||
return buildResult(item, offsets, bonus), offsets, pos
|
result := buildResult(item, offsets, bonus)
|
||||||
|
return &result, offsets, pos
|
||||||
}
|
}
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,17 @@ type colorOffset struct {
|
|||||||
index int32
|
index int32
|
||||||
}
|
}
|
||||||
|
|
||||||
type rank struct {
|
|
||||||
points [4]uint16
|
|
||||||
index int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
item *Item
|
item *Item
|
||||||
rank rank
|
points [4]uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildResult(item *Item, offsets []Offset, score int) *Result {
|
func buildResult(item *Item, offsets []Offset, score int) Result {
|
||||||
if len(offsets) > 1 {
|
if len(offsets) > 1 {
|
||||||
sort.Sort(ByOrder(offsets))
|
sort.Sort(ByOrder(offsets))
|
||||||
}
|
}
|
||||||
|
|
||||||
result := Result{item: item, rank: rank{index: item.Index()}}
|
result := Result{item: item}
|
||||||
numChars := item.text.Length()
|
numChars := item.text.Length()
|
||||||
minBegin := math.MaxUint16
|
minBegin := math.MaxUint16
|
||||||
minEnd := math.MaxUint16
|
minEnd := math.MaxUint16
|
||||||
@ -75,10 +70,10 @@ func buildResult(item *Item, offsets []Offset, score int) *Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.rank.points[idx] = val
|
result.points[idx] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort criteria to use. Never changes once fzf is started.
|
// Sort criteria to use. Never changes once fzf is started.
|
||||||
@ -89,8 +84,8 @@ func (result *Result) Index() int32 {
|
|||||||
return result.item.Index()
|
return result.item.Index()
|
||||||
}
|
}
|
||||||
|
|
||||||
func minRank() rank {
|
func minRank() Result {
|
||||||
return rank{index: 0, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
|
return Result{item: &nilItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme, color tui.ColorPair, attr tui.Attr, current bool) []colorOffset {
|
func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme, color tui.ColorPair, attr tui.Attr, current bool) []colorOffset {
|
||||||
@ -201,7 +196,7 @@ func (a ByOrder) Less(i, j int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ByRelevance is for sorting Items
|
// ByRelevance is for sorting Items
|
||||||
type ByRelevance []*Result
|
type ByRelevance []Result
|
||||||
|
|
||||||
func (a ByRelevance) Len() int {
|
func (a ByRelevance) Len() int {
|
||||||
return len(a)
|
return len(a)
|
||||||
@ -212,11 +207,11 @@ func (a ByRelevance) Swap(i, j int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a ByRelevance) Less(i, j int) bool {
|
func (a ByRelevance) Less(i, j int) bool {
|
||||||
return compareRanks((*a[i]).rank, (*a[j]).rank, false)
|
return compareRanks(a[i], a[j], false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ByRelevanceTac is for sorting Items
|
// ByRelevanceTac is for sorting Items
|
||||||
type ByRelevanceTac []*Result
|
type ByRelevanceTac []Result
|
||||||
|
|
||||||
func (a ByRelevanceTac) Len() int {
|
func (a ByRelevanceTac) Len() int {
|
||||||
return len(a)
|
return len(a)
|
||||||
@ -227,10 +222,10 @@ func (a ByRelevanceTac) Swap(i, j int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a ByRelevanceTac) Less(i, j int) bool {
|
func (a ByRelevanceTac) Less(i, j int) bool {
|
||||||
return compareRanks((*a[i]).rank, (*a[j]).rank, true)
|
return compareRanks(a[i], a[j], true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareRanks(irank rank, jrank rank, tac bool) bool {
|
func compareRanks(irank Result, jrank Result, tac bool) bool {
|
||||||
for idx := 0; idx < 4; idx++ {
|
for idx := 0; idx < 4; idx++ {
|
||||||
left := irank.points[idx]
|
left := irank.points[idx]
|
||||||
right := jrank.points[idx]
|
right := jrank.points[idx]
|
||||||
@ -240,5 +235,5 @@ func compareRanks(irank rank, jrank rank, tac bool) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (irank.index <= jrank.index) != tac
|
return (irank.item.Index() <= jrank.item.Index()) != tac
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,10 @@ func TestOffsetSort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRankComparison(t *testing.T) {
|
func TestRankComparison(t *testing.T) {
|
||||||
rank := func(vals ...uint16) rank {
|
rank := func(vals ...uint16) Result {
|
||||||
return rank{
|
return Result{
|
||||||
points: [4]uint16{vals[0], vals[1], vals[2], vals[3]},
|
points: [4]uint16{vals[0], vals[1], vals[2], vals[3]},
|
||||||
index: int32(vals[4])}
|
item: &Item{text: util.Chars{Index: int32(vals[4])}}}
|
||||||
}
|
}
|
||||||
if compareRanks(rank(3, 0, 0, 0, 5), rank(2, 0, 0, 0, 7), false) ||
|
if compareRanks(rank(3, 0, 0, 0, 5), rank(2, 0, 0, 0, 7), false) ||
|
||||||
!compareRanks(rank(3, 0, 0, 0, 5), rank(3, 0, 0, 0, 6), false) ||
|
!compareRanks(rank(3, 0, 0, 0, 5), rank(3, 0, 0, 0, 6), false) ||
|
||||||
@ -59,23 +59,23 @@ func TestResultRank(t *testing.T) {
|
|||||||
strs := [][]rune{[]rune("foo"), []rune("foobar"), []rune("bar"), []rune("baz")}
|
strs := [][]rune{[]rune("foo"), []rune("foobar"), []rune("bar"), []rune("baz")}
|
||||||
item1 := buildResult(
|
item1 := buildResult(
|
||||||
withIndex(&Item{text: util.RunesToChars(strs[0])}, 1), []Offset{}, 2)
|
withIndex(&Item{text: util.RunesToChars(strs[0])}, 1), []Offset{}, 2)
|
||||||
if item1.rank.points[0] != math.MaxUint16-2 || // Bonus
|
if item1.points[0] != math.MaxUint16-2 || // Bonus
|
||||||
item1.rank.points[1] != 3 || // Length
|
item1.points[1] != 3 || // Length
|
||||||
item1.rank.points[2] != 0 || // Unused
|
item1.points[2] != 0 || // Unused
|
||||||
item1.rank.points[3] != 0 || // Unused
|
item1.points[3] != 0 || // Unused
|
||||||
item1.item.Index() != 1 {
|
item1.item.Index() != 1 {
|
||||||
t.Error(item1.rank)
|
t.Error(item1)
|
||||||
}
|
}
|
||||||
// Only differ in index
|
// Only differ in index
|
||||||
item2 := buildResult(&Item{text: util.RunesToChars(strs[0])}, []Offset{}, 2)
|
item2 := buildResult(&Item{text: util.RunesToChars(strs[0])}, []Offset{}, 2)
|
||||||
|
|
||||||
items := []*Result{item1, item2}
|
items := []Result{item1, item2}
|
||||||
sort.Sort(ByRelevance(items))
|
sort.Sort(ByRelevance(items))
|
||||||
if items[0] != item2 || items[1] != item1 {
|
if items[0] != item2 || items[1] != item1 {
|
||||||
t.Error(items)
|
t.Error(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
items = []*Result{item2, item1, item1, item2}
|
items = []Result{item2, item1, item1, item2}
|
||||||
sort.Sort(ByRelevance(items))
|
sort.Sort(ByRelevance(items))
|
||||||
if items[0] != item2 || items[1] != item2 ||
|
if items[0] != item2 || items[1] != item2 ||
|
||||||
items[2] != item1 || items[3] != item1 {
|
items[2] != item1 || items[3] != item1 {
|
||||||
@ -91,7 +91,7 @@ func TestResultRank(t *testing.T) {
|
|||||||
withIndex(&Item{}, 2), []Offset{Offset{1, 3}, Offset{5, 7}}, 5)
|
withIndex(&Item{}, 2), []Offset{Offset{1, 3}, Offset{5, 7}}, 5)
|
||||||
item6 := buildResult(
|
item6 := buildResult(
|
||||||
withIndex(&Item{}, 2), []Offset{Offset{1, 2}, Offset{6, 7}}, 6)
|
withIndex(&Item{}, 2), []Offset{Offset{1, 2}, Offset{6, 7}}, 6)
|
||||||
items = []*Result{item1, item2, item3, item4, item5, item6}
|
items = []Result{item1, item2, item3, item4, item5, item6}
|
||||||
sort.Sort(ByRelevance(items))
|
sort.Sort(ByRelevance(items))
|
||||||
if !(items[0] == item6 && items[1] == item5 &&
|
if !(items[0] == item6 && items[1] == item5 &&
|
||||||
items[2] == item4 && items[3] == item3 &&
|
items[2] == item4 && items[3] == item3 &&
|
||||||
|
@ -714,7 +714,7 @@ func (t *Terminal) printHeader() {
|
|||||||
colors: colors}
|
colors: colors}
|
||||||
|
|
||||||
t.move(line, 2, true)
|
t.move(line, 2, true)
|
||||||
t.printHighlighted(&Result{item: item},
|
t.printHighlighted(Result{item: item},
|
||||||
tui.AttrRegular, tui.ColHeader, tui.ColDefault, false, false)
|
tui.AttrRegular, tui.ColHeader, tui.ColDefault, false, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,7 +742,7 @@ func (t *Terminal) printList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) printItem(result *Result, line int, i int, current bool) {
|
func (t *Terminal) printItem(result Result, line int, i int, current bool) {
|
||||||
item := result.item
|
item := result.item
|
||||||
_, selected := t.selected[item.Index()]
|
_, selected := t.selected[item.Index()]
|
||||||
label := " "
|
label := " "
|
||||||
@ -758,7 +758,7 @@ func (t *Terminal) printItem(result *Result, line int, i int, current bool) {
|
|||||||
|
|
||||||
// Avoid unnecessary redraw
|
// Avoid unnecessary redraw
|
||||||
newLine := itemLine{current: current, selected: selected, label: label,
|
newLine := itemLine{current: current, selected: selected, label: label,
|
||||||
result: *result, queryLen: len(t.input), width: 0}
|
result: result, queryLen: len(t.input), width: 0}
|
||||||
prevLine := t.prevLines[i]
|
prevLine := t.prevLines[i]
|
||||||
if prevLine.current == newLine.current &&
|
if prevLine.current == newLine.current &&
|
||||||
prevLine.selected == newLine.selected &&
|
prevLine.selected == newLine.selected &&
|
||||||
@ -840,7 +840,7 @@ func (t *Terminal) overflow(runes []rune, max int) bool {
|
|||||||
return t.displayWidthWithLimit(runes, 0, max) > max
|
return t.displayWidthWithLimit(runes, 0, max) > max
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) printHighlighted(result *Result, attr tui.Attr, col1 tui.ColorPair, col2 tui.ColorPair, current bool, match bool) int {
|
func (t *Terminal) printHighlighted(result Result, attr tui.Attr, col1 tui.ColorPair, col2 tui.ColorPair, current bool, match bool) int {
|
||||||
item := result.item
|
item := result.item
|
||||||
|
|
||||||
// Overflow
|
// Overflow
|
||||||
|
Loading…
x
Reference in New Issue
Block a user