]> git.lizzy.rs Git - micro.git/blob - cmd/micro/search.go
Add ignorecase option
[micro.git] / cmd / micro / search.go
1 package main
2
3 import (
4         "regexp"
5
6         "github.com/zyedidia/tcell"
7 )
8
9 var (
10         // What was the last search
11         lastSearch string
12
13         // Where should we start the search down from (or up from)
14         searchStart int
15
16         // Is there currently a search in progress
17         searching bool
18 )
19
20 // BeginSearch starts a search
21 func BeginSearch() {
22         searching = true
23         messenger.hasPrompt = true
24         messenger.Message("Find: ")
25 }
26
27 // EndSearch stops the current search
28 func EndSearch() {
29         searching = false
30         messenger.hasPrompt = false
31         messenger.Clear()
32         messenger.Reset()
33         if lastSearch != "" {
34                 messenger.Message("^P Previous ^N Next")
35         }
36 }
37
38 // HandleSearchEvent takes an event and a view and will do a real time match from the messenger's output
39 // to the current buffer. It searches down the buffer.
40 func HandleSearchEvent(event tcell.Event, v *View) {
41         switch e := event.(type) {
42         case *tcell.EventKey:
43                 switch e.Key() {
44                 case tcell.KeyCtrlQ, tcell.KeyCtrlC, tcell.KeyEscape, tcell.KeyEnter:
45                         // Done
46                         EndSearch()
47                         return
48                 }
49         }
50
51         messenger.HandleEvent(event)
52
53         if messenger.cursorx < 0 {
54                 // Done
55                 EndSearch()
56                 return
57         }
58
59         if messenger.response == "" {
60                 v.Cursor.ResetSelection()
61                 // We don't end the search though
62                 return
63         }
64
65         Search(messenger.response, v, true)
66
67         return
68 }
69
70 // Search searches in the view for the given regex. The down bool
71 // specifies whether it should search down from the searchStart position
72 // or up from there
73 func Search(searchStr string, v *View, down bool) {
74         if searchStr == "" {
75                 return
76         }
77         var str string
78         var charPos int
79         text := v.Buf.String()
80         if down {
81                 str = text[searchStart:]
82                 charPos = searchStart
83         } else {
84                 str = text[:searchStart]
85         }
86         r, err := regexp.Compile(searchStr)
87         if settings["ignorecase"].(bool) {
88                 r, err = regexp.Compile("(?i)" + searchStr)
89         }
90         if err != nil {
91                 return
92         }
93         matches := r.FindAllStringIndex(str, -1)
94         var match []int
95         if matches == nil {
96                 // Search the entire buffer now
97                 matches = r.FindAllStringIndex(text, -1)
98                 charPos = 0
99                 if matches == nil {
100                         v.Cursor.ResetSelection()
101                         return
102                 }
103
104                 if !down {
105                         match = matches[len(matches)-1]
106                 } else {
107                         match = matches[0]
108                 }
109         }
110
111         if !down {
112                 match = matches[len(matches)-1]
113         } else {
114                 match = matches[0]
115         }
116
117         if match[0] == match[1] {
118                 return
119         }
120
121         v.Cursor.curSelection[0] = charPos + match[0]
122         v.Cursor.curSelection[1] = charPos + match[1]
123         v.Cursor.x, v.Cursor.y = FromCharPos(charPos+match[1]-1, v.Buf)
124         if v.Relocate() {
125                 v.matches = Match(v)
126         }
127         lastSearch = searchStr
128 }