1
1
mirror of https://github.com/walles/moar.git synced 2024-11-27 01:05:23 +03:00

Don't search the whole file more than once

Should improve the performance situation reported here:
https://github.com/walles/moar/issues/209
This commit is contained in:
Johan Walles 2024-05-13 07:59:40 +02:00
parent e6c69c2d97
commit edb3e51680
2 changed files with 15 additions and 10 deletions

View File

@ -298,7 +298,7 @@ func TestFindFirstHitSimple(t *testing.T) {
pager.searchPattern = toPattern("AB") pager.searchPattern = toPattern("AB")
hit := pager.findFirstHit(linenumbers.LineNumber{}, false) hit := pager.findFirstHit(linenumbers.LineNumber{}, nil, false)
assert.Assert(t, hit.internalDontTouch.lineNumber.IsZero()) assert.Assert(t, hit.internalDontTouch.lineNumber.IsZero())
assert.Equal(t, hit.internalDontTouch.deltaScreenLines, 0) assert.Equal(t, hit.internalDontTouch.deltaScreenLines, 0)
} }
@ -312,7 +312,7 @@ func TestFindFirstHitAnsi(t *testing.T) {
pager.searchPattern = toPattern("AB") pager.searchPattern = toPattern("AB")
hit := pager.findFirstHit(linenumbers.LineNumber{}, false) hit := pager.findFirstHit(linenumbers.LineNumber{}, nil, false)
assert.Assert(t, hit.internalDontTouch.lineNumber.IsZero()) assert.Assert(t, hit.internalDontTouch.lineNumber.IsZero())
assert.Equal(t, hit.internalDontTouch.deltaScreenLines, 0) assert.Equal(t, hit.internalDontTouch.deltaScreenLines, 0)
} }
@ -326,7 +326,7 @@ func TestFindFirstHitNoMatch(t *testing.T) {
pager.searchPattern = toPattern("this pattern should not be found") pager.searchPattern = toPattern("this pattern should not be found")
hit := pager.findFirstHit(linenumbers.LineNumber{}, false) hit := pager.findFirstHit(linenumbers.LineNumber{}, nil, false)
assert.Assert(t, hit == nil) assert.Assert(t, hit == nil)
} }
@ -340,7 +340,7 @@ func TestFindFirstHitNoMatchBackwards(t *testing.T) {
pager.searchPattern = toPattern("this pattern should not be found") pager.searchPattern = toPattern("this pattern should not be found")
theEnd := *linenumbers.LineNumberFromLength(reader.GetLineCount()) theEnd := *linenumbers.LineNumberFromLength(reader.GetLineCount())
hit := pager.findFirstHit(theEnd, true) hit := pager.findFirstHit(theEnd, nil, true)
assert.Assert(t, hit == nil) assert.Assert(t, hit == nil)
} }
@ -682,7 +682,7 @@ func benchmarkSearch(b *testing.B, highlighted bool) {
b.ResetTimer() b.ResetTimer()
// This test will search through all the N copies we made of our file // This test will search through all the N copies we made of our file
hit := pager.findFirstHit(linenumbers.LineNumber{}, false) hit := pager.findFirstHit(linenumbers.LineNumber{}, nil, false)
if hit != nil { if hit != nil {
panic(fmt.Errorf("This test is meant to scan the whole file without finding anything")) panic(fmt.Errorf("This test is meant to scan the whole file without finding anything"))

View File

@ -12,10 +12,10 @@ func (p *Pager) scrollToSearchHits() {
return return
} }
firstHitPosition := p.findFirstHit(*p.scrollPosition.lineNumber(p), false) firstHitPosition := p.findFirstHit(*p.scrollPosition.lineNumber(p), nil, false)
if firstHitPosition == nil { if firstHitPosition == nil {
// Try again from the top // Try again from the top
firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, false) firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, p.scrollPosition.lineNumber(p), false)
} }
if firstHitPosition == nil { if firstHitPosition == nil {
// No match, give up // No match, give up
@ -35,7 +35,7 @@ func (p *Pager) scrollToSearchHits() {
// scrollPosition for searching. // scrollPosition for searching.
// //
// FIXME: We should take startPosition.deltaScreenLines into account as well! // FIXME: We should take startPosition.deltaScreenLines into account as well!
func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, backwards bool) *scrollPosition { func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, beforePosition *linenumbers.LineNumber, backwards bool) *scrollPosition {
searchPosition := startPosition searchPosition := startPosition
for { for {
line := p.reader.GetLine(searchPosition) line := p.reader.GetLine(searchPosition)
@ -58,6 +58,11 @@ func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, backwards boo
searchPosition = searchPosition.NonWrappingAdd(-1) searchPosition = searchPosition.NonWrappingAdd(-1)
} else { } else {
searchPosition = searchPosition.NonWrappingAdd(1) searchPosition = searchPosition.NonWrappingAdd(1)
if beforePosition != nil && searchPosition == *beforePosition {
// No match, give up
return nil
}
} }
} }
} }
@ -105,7 +110,7 @@ func (p *Pager) scrollToNextSearchHit() {
panic(fmt.Sprint("Unknown search mode when finding next: ", p.mode)) panic(fmt.Sprint("Unknown search mode when finding next: ", p.mode))
} }
firstHitPosition := p.findFirstHit(firstSearchPosition, false) firstHitPosition := p.findFirstHit(firstSearchPosition, nil, false)
if firstHitPosition == nil { if firstHitPosition == nil {
p.mode = PagerModeNotFound{pager: p} p.mode = PagerModeNotFound{pager: p}
return return
@ -144,7 +149,7 @@ func (p *Pager) scrollToPreviousSearchHit() {
panic(fmt.Sprint("Unknown search mode when finding previous: ", p.mode)) panic(fmt.Sprint("Unknown search mode when finding previous: ", p.mode))
} }
firstHitPosition := p.findFirstHit(firstSearchPosition, true) firstHitPosition := p.findFirstHit(firstSearchPosition, nil, true)
if firstHitPosition == nil { if firstHitPosition == nil {
p.mode = PagerModeNotFound{pager: p} p.mode = PagerModeNotFound{pager: p}
return return