-
Notifications
You must be signed in to change notification settings - Fork 3
/
search.go
133 lines (114 loc) · 3.04 KB
/
search.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"regexp"
"strings"
)
var (
last_search_buffer *Buffer = nil
last_search = ""
last_search_index = 0
last_search_highlight = false
last_search_results = []*Location{}
)
func init_search() {
bind("normal", k("/"), handle_search_start)
bind("normal", k("N"), handle_search_prev)
bind("normal", k("n"), handle_search_next)
bind("normal", k("*"), handle_search_search_work_under_cursor)
bind("normal", k("SPC n"), func(vt *ViewTree, b *Buffer, kl *KeyList) {
search_clear()
})
addCommand("clearsearch", func(args []string) {
search_clear()
})
addAlias("cs", "clearsearch")
hook_buffer("modified", func(b *Buffer) {
// Update search result indexes on buffer changes
if last_search != "" && b == last_search_buffer {
search_find_matches(b, last_search)
last_search_index = len(last_search_results) - 1
}
})
}
func search_clear() {
last_search_highlight = false
highlight_buffer(currentViewTree.Leaf.Buf)
}
func search_find_matches(b *Buffer, search string) {
last_search = search
re := regexp.MustCompile(regexp.QuoteMeta(search))
last_search_buffer = b
last_search_results = []*Location{}
for i, line := range b.Data {
idxs := re.FindAllStringIndex(string(line), -1)
for _, idx := range idxs {
last_search_results = append(last_search_results, NewLocation(i, idx[0]))
}
}
}
func search_start(b *Buffer, search string) {
if len(search) > 0 {
search_find_matches(b, search)
// TODO start index at first match after cursor
last_search_index = len(last_search_results) - 1
search_next(b)
}
}
func handle_search_start(vt *ViewTree, b *Buffer, kl *KeyList) {
prompt("/", noopComplete, func(args []string) {
search_start(b, strings.Join(args, " "))
})
}
func search_prev(b *Buffer) {
if len(last_search_results) == 0 {
message("No search result.")
return
}
if last_search_index == 0 {
last_search_index = len(last_search_results) - 1
} else {
last_search_index--
}
last_search_highlight = true
highlight_buffer(currentViewTree.Leaf.Buf)
loc := last_search_results[last_search_index]
b.MoveTo(loc.Char, loc.Line)
}
func handle_search_prev(vt *ViewTree, b *Buffer, kl *KeyList) {
search_prev(b)
}
func search_next(b *Buffer) {
if len(last_search_results) == 0 {
message("No search result.")
return
}
if last_search_index+1 == len(last_search_results) {
last_search_index = 0
} else {
last_search_index++
}
last_search_highlight = true
highlight_buffer(currentViewTree.Leaf.Buf)
loc := last_search_results[last_search_index]
b.MoveTo(loc.Char, loc.Line)
}
func handle_search_next(vt *ViewTree, b *Buffer, kl *KeyList) {
search_next(b)
}
func search_highlight(b *Buffer, l, c int) int {
if !last_search_highlight {
return 0
}
if last_search_buffer != b {
return 0
}
for _, loc := range last_search_results {
if l == loc.Line && c == loc.Char {
return len(last_search)
}
}
return 0
}
func handle_search_search_work_under_cursor(vt *ViewTree, b *Buffer, kl *KeyList) {
search_start(b, string(b.WordUnderCursor()))
}