2021-04-07 16:26:05 -04:00
|
|
|
package editor
|
|
|
|
|
|
|
|
import (
|
2023-10-06 11:30:21 -04:00
|
|
|
"timshome.page/gilo/char"
|
2021-04-07 16:26:05 -04:00
|
|
|
"timshome.page/gilo/editor/highlight"
|
2021-04-13 14:54:44 -04:00
|
|
|
"timshome.page/gilo/internal/gilo"
|
2021-04-07 16:26:05 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
type search struct {
|
2023-10-03 17:02:22 -04:00
|
|
|
cursor *gilo.Point
|
|
|
|
offset *gilo.Point
|
|
|
|
savedhlLine int
|
|
|
|
savedhl []int
|
|
|
|
direction int
|
|
|
|
lastMatch int
|
2021-04-07 16:26:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func newSearch() *search {
|
|
|
|
return &search{
|
2023-10-03 17:02:22 -04:00
|
|
|
cursor: gilo.DefaultPoint(),
|
|
|
|
offset: gilo.DefaultPoint(),
|
|
|
|
savedhlLine: -1,
|
|
|
|
savedhl: []int{},
|
|
|
|
lastMatch: -1,
|
|
|
|
direction: 1,
|
2021-04-07 16:26:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 17:02:22 -04:00
|
|
|
func (e *Editor) find() {
|
2021-04-07 16:26:05 -04:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-03 17:02:22 -04:00
|
|
|
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 {
|
2021-04-07 16:26:05 -04:00
|
|
|
staleRow.Hl[i] = val
|
|
|
|
}
|
2023-10-03 17:02:22 -04:00
|
|
|
e.search.savedhl = nil
|
|
|
|
e.search.savedhlLine = -1
|
2021-04-07 16:26:05 -04:00
|
|
|
}
|
|
|
|
|
2023-10-06 11:30:21 -04:00
|
|
|
if ch == string(char.Enter) || ch == string(char.Esc) {
|
2021-04-07 16:26:05 -04:00
|
|
|
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
|
|
|
|
|
2021-04-07 16:33:00 -04:00
|
|
|
for i := 0; i < e.doc.RowCount(); i++ {
|
2021-04-07 16:26:05 -04:00
|
|
|
current += e.search.direction
|
|
|
|
|
|
|
|
if current == -1 {
|
2021-04-07 16:33:00 -04:00
|
|
|
current = e.doc.RowCount() - 1
|
|
|
|
} else if current == e.doc.RowCount() {
|
2021-04-07 16:26:05 -04:00
|
|
|
current = 0
|
|
|
|
}
|
|
|
|
|
2021-04-07 16:33:00 -04:00
|
|
|
row := e.doc.GetRow(current)
|
2021-04-07 16:26:05 -04:00
|
|
|
matchIndex := row.Search(query)
|
|
|
|
if matchIndex == -1 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
e.search.lastMatch = current
|
|
|
|
e.cursor.Y = current
|
|
|
|
e.cursor.X = row.RenderXtoCursorX(matchIndex)
|
2021-04-07 16:33:00 -04:00
|
|
|
e.offset.Y = e.doc.RowCount()
|
2021-04-07 16:26:05 -04:00
|
|
|
|
2023-10-03 17:02:22 -04:00
|
|
|
// Save the current highlighting of where the search result is
|
|
|
|
e.search.savedhlLine = current
|
|
|
|
e.search.savedhl = make([]int, row.RenderSize())
|
2021-04-07 16:26:05 -04:00
|
|
|
for i, val := range row.Hl {
|
2023-10-03 17:02:22 -04:00
|
|
|
e.search.savedhl[i] = val
|
2021-04-07 16:26:05 -04:00
|
|
|
}
|
2023-10-03 17:02:22 -04:00
|
|
|
|
|
|
|
// Update highlighting of search result
|
2021-04-07 16:26:05 -04:00
|
|
|
for x := matchIndex; x < matchIndex+len(query); x++ {
|
|
|
|
row.Hl[x] = highlight.Match
|
|
|
|
}
|
|
|
|
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|