mirror of
https://github.com/charmbracelet/gum
synced 2024-06-01 21:32:15 +02:00
simplified matchers and fixed duplicate highlights
This commit is contained in:
parent
86c66fd6cb
commit
c576e347a0
|
@ -11,11 +11,12 @@ import (
|
|||
)
|
||||
|
||||
type search struct {
|
||||
active bool
|
||||
input textinput.Model
|
||||
query *regexp.Regexp
|
||||
lastMatchLoc int
|
||||
prevMatch string
|
||||
active bool
|
||||
input textinput.Model
|
||||
query *regexp.Regexp
|
||||
matchIndex int
|
||||
matchLipglossStr string
|
||||
matchString string
|
||||
}
|
||||
|
||||
func (s *search) new() {
|
||||
|
@ -46,8 +47,9 @@ func (s *search) Execute(m *model) {
|
|||
|
||||
func (s *search) Done() {
|
||||
s.active = false
|
||||
s.lastMatchLoc = 0
|
||||
s.prevMatch = ""
|
||||
|
||||
// To account for the first match is always executed.
|
||||
s.matchIndex = -1
|
||||
}
|
||||
|
||||
func (s *search) NextMatch(m *model) {
|
||||
|
@ -56,32 +58,16 @@ func (s *search) NextMatch(m *model) {
|
|||
return
|
||||
}
|
||||
|
||||
// Removed last highlight.
|
||||
if s.prevMatch != "" {
|
||||
leftPadding, rightPadding := utils.LipglossLengthPadding(s.prevMatch, m.matchHighlightStyle)
|
||||
metastring := regexp.QuoteMeta(m.matchHighlightStyle.Render(s.query.String()))
|
||||
query := regexp.MustCompile("(" + metastring[:leftPadding+1] + ")(" + s.query.String() + ")(" + metastring[len(metastring)-rightPadding-1:] + ")")
|
||||
m.content = query.ReplaceAllString(m.content, "$2")
|
||||
}
|
||||
// Find the string to highlight.
|
||||
nextMatch := s.query.FindString(m.content[s.lastMatchLoc:])
|
||||
s.prevMatch = nextMatch
|
||||
m.content = strings.Replace(m.content, s.matchLipglossStr, s.matchString, 1)
|
||||
|
||||
leftPadding, _ := utils.LipglossLengthPadding(s.prevMatch, m.matchHighlightStyle)
|
||||
allMatches := s.query.FindAllSubmatchIndex([]byte(m.content), -1)
|
||||
for i, subm := range allMatches {
|
||||
if subm[1]+leftPadding == s.lastMatchLoc {
|
||||
// Highliht the current match.
|
||||
m.content = m.content[:allMatches[i+1][0]] + strings.Replace(m.content[allMatches[i+1][0]:], m.content[allMatches[i+1][0]:allMatches[i+1][1]], m.matchHighlightStyle.Render(m.content[allMatches[i+1][0]:allMatches[i+1][1]]), 1)
|
||||
s.lastMatchLoc = allMatches[i+1][1] + leftPadding
|
||||
break
|
||||
}
|
||||
if i == len(allMatches)-1 {
|
||||
m.content = m.content[:allMatches[0][0]] + strings.Replace(m.content[allMatches[0][0]:], m.content[allMatches[0][0]:allMatches[0][1]], m.matchHighlightStyle.Render(m.content[allMatches[0][0]:allMatches[0][1]]), 1)
|
||||
s.lastMatchLoc = allMatches[0][1] + leftPadding
|
||||
break
|
||||
}
|
||||
}
|
||||
allMatches := s.query.FindAllStringSubmatchIndex(m.content, -1)
|
||||
s.matchIndex = (s.matchIndex + 1) % len(allMatches)
|
||||
match := allMatches[s.matchIndex]
|
||||
lhs := m.content[:match[0]]
|
||||
rhs := m.content[match[0]:]
|
||||
s.matchString = m.content[match[0]:match[1]]
|
||||
s.matchLipglossStr = m.matchHighlightStyle.Render(s.matchString)
|
||||
m.content = lhs + strings.Replace(rhs, m.content[match[0]:match[1]], s.matchLipglossStr, 1)
|
||||
|
||||
// Update the viewport position.
|
||||
line := 0
|
||||
|
@ -89,13 +75,13 @@ func (s *search) NextMatch(m *model) {
|
|||
if c == '\n' {
|
||||
line++
|
||||
}
|
||||
if i == s.lastMatchLoc {
|
||||
if i == match[0]+len(s.matchLipglossStr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Only update if the match is not within the viewport.
|
||||
if line > m.viewport.YOffset+m.viewport.VisibleLineCount()-1 || line < m.viewport.YOffset {
|
||||
if line > m.viewport.YOffset-1+m.viewport.VisibleLineCount()-1 || line < m.viewport.YOffset {
|
||||
m.viewport.SetYOffset(line)
|
||||
}
|
||||
}
|
||||
|
@ -106,32 +92,20 @@ func (s *search) PrevMatch(m *model) {
|
|||
return
|
||||
}
|
||||
|
||||
// Removed last highlight.
|
||||
if s.prevMatch != "" {
|
||||
leftPadding, rightPadding := utils.LipglossLengthPadding(s.prevMatch, m.matchHighlightStyle)
|
||||
metastring := regexp.QuoteMeta(m.matchHighlightStyle.Render(s.query.String()))
|
||||
query := regexp.MustCompile("(" + metastring[:leftPadding+1] + ")(" + s.query.String() + ")(" + metastring[len(metastring)-rightPadding-1:] + ")")
|
||||
m.content = query.ReplaceAllString(m.content, "$2")
|
||||
m.content = strings.Replace(m.content, s.matchLipglossStr, s.matchString, 1)
|
||||
|
||||
allMatches := s.query.FindAllStringSubmatchIndex(m.content, -1)
|
||||
s.matchIndex = (s.matchIndex - 1) % len(allMatches)
|
||||
if s.matchIndex < 0 {
|
||||
s.matchIndex = 0
|
||||
}
|
||||
|
||||
var prev []int
|
||||
leftPadding, _ := utils.LipglossLengthPadding(s.prevMatch, m.matchHighlightStyle)
|
||||
allMatches := s.query.FindAllSubmatchIndex([]byte(m.content), -1)
|
||||
for i, subm := range allMatches {
|
||||
if prev != nil && subm[1]+leftPadding == s.lastMatchLoc {
|
||||
// Highliht the current match.
|
||||
m.content = m.content[:prev[0]] + strings.Replace(m.content[prev[0]:], m.content[prev[0]:prev[1]], m.matchHighlightStyle.Render(m.content[prev[0]:prev[1]]), 1)
|
||||
s.lastMatchLoc = prev[1] + leftPadding
|
||||
break
|
||||
}
|
||||
|
||||
// If reaching this at the end of the loop we have looked through all matches.
|
||||
if i == len(allMatches)-1 {
|
||||
m.content = m.content[:subm[0]] + strings.Replace(m.content[subm[0]:], m.content[subm[0]:subm[1]], m.matchHighlightStyle.Render(m.content[subm[0]:subm[1]]), 1)
|
||||
s.lastMatchLoc = subm[1] + leftPadding
|
||||
}
|
||||
prev = subm
|
||||
}
|
||||
match := allMatches[s.matchIndex]
|
||||
lhs := m.content[:match[0]]
|
||||
rhs := m.content[match[0]:]
|
||||
s.matchString = m.content[match[0]:match[1]]
|
||||
s.matchLipglossStr = m.matchHighlightStyle.Render(s.matchString)
|
||||
m.content = lhs + strings.Replace(rhs, m.content[match[0]:match[1]], s.matchLipglossStr, 1)
|
||||
|
||||
// Update the viewport position.
|
||||
line := 0
|
||||
|
@ -139,13 +113,13 @@ func (s *search) PrevMatch(m *model) {
|
|||
if c == '\n' {
|
||||
line++
|
||||
}
|
||||
if i == s.lastMatchLoc {
|
||||
if i == match[0]+len(s.matchLipglossStr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Only update if the match is not within the viewport.
|
||||
if line > m.viewport.YOffset+m.viewport.VisibleLineCount()-1 || line < m.viewport.YOffset {
|
||||
if line > m.viewport.YOffset-1+m.viewport.VisibleLineCount()-1 || line < m.viewport.YOffset {
|
||||
m.viewport.SetYOffset(line)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue