gilo/editor/search.go
Timothy Warren ceed34c634
All checks were successful
timw4mail/gilo/pipeline/head This commit looks good
Refactor keyword highlighting to handle more edge cases
2023-10-06 11:30:21 -04:00

116 lines
2.4 KiB
Go

package editor
import (
"timshome.page/gilo/char"
"timshome.page/gilo/editor/highlight"
"timshome.page/gilo/internal/gilo"
)
type search struct {
cursor *gilo.Point
offset *gilo.Point
savedhlLine int
savedhl []int
direction int
lastMatch int
}
func newSearch() *search {
return &search{
cursor: gilo.DefaultPoint(),
offset: gilo.DefaultPoint(),
savedhlLine: -1,
savedhl: []int{},
lastMatch: -1,
direction: 1,
}
}
func (e *Editor) find() {
e.search.cursor.X = e.cursor.X
e.search.cursor.Y = e.cursor.Y
e.search.offset.X = e.offset.X
e.search.offset.Y = e.offset.Y
query := e.prompt("Search: %s (Use ESC/Arrows/Enter)", e.findCallback)
if query == "" {
e.cursor.X = e.search.cursor.X
e.cursor.Y = e.search.cursor.Y
e.offset.X = e.search.offset.X
e.offset.Y = e.search.offset.Y
return
}
}
func (e *Editor) findCallback(query string, ch string) {
// If we highlighted a previous match, restore the original highlighting
if e.search.savedhlLine != -1 && e.search.savedhl != nil {
staleRow := e.doc.GetRow(e.search.savedhlLine)
for i, val := range e.search.savedhl {
staleRow.Hl[i] = val
}
e.search.savedhl = nil
e.search.savedhlLine = -1
}
if ch == string(char.Enter) || ch == string(char.Esc) {
e.search.lastMatch = -1
e.search.direction = 1
return
} else if ch == keyRight || ch == keyDown {
e.search.direction = 1
} else if ch == keyLeft || ch == keyUp {
e.search.direction = -1
} else {
e.search.lastMatch = -1
e.search.direction = 1
}
if e.search.lastMatch == -1 {
e.search.direction = 1
}
if len(query) == 0 {
return
}
current := e.search.lastMatch
for i := 0; i < e.doc.RowCount(); i++ {
current += e.search.direction
if current == -1 {
current = e.doc.RowCount() - 1
} else if current == e.doc.RowCount() {
current = 0
}
row := e.doc.GetRow(current)
matchIndex := row.Search(query)
if matchIndex == -1 {
continue
}
e.search.lastMatch = current
e.cursor.Y = current
e.cursor.X = row.RenderXtoCursorX(matchIndex)
e.offset.Y = e.doc.RowCount()
// Save the current highlighting of where the search result is
e.search.savedhlLine = current
e.search.savedhl = make([]int, row.RenderSize())
for i, val := range row.Hl {
e.search.savedhl[i] = val
}
// Update highlighting of search result
for x := matchIndex; x < matchIndex+len(query); x++ {
row.Hl[x] = highlight.Match
}
break
}
}