6 "github.com/zyedidia/micro/v2/internal/util"
9 func (b *Buffer) findDown(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
10 lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
11 if start.Y > b.LinesNum()-1 {
14 if end.Y > b.LinesNum()-1 {
17 start.Y = util.Clamp(start.Y, 0, b.LinesNum()-1)
18 end.Y = util.Clamp(end.Y, 0, b.LinesNum()-1)
20 if start.GreaterThan(end) {
21 start, end = end, start
24 for i := start.Y; i <= end.Y; i++ {
28 if i == start.Y && start.Y == end.Y {
29 nchars := util.CharacterCount(l)
30 start.X = util.Clamp(start.X, 0, nchars)
31 end.X = util.Clamp(end.X, 0, nchars)
32 l = util.SliceStart(l, end.X)
33 l = util.SliceEnd(l, start.X)
35 } else if i == start.Y {
36 nchars := util.CharacterCount(l)
37 start.X = util.Clamp(start.X, 0, nchars)
38 l = util.SliceEnd(l, start.X)
40 } else if i == end.Y {
41 nchars := util.CharacterCount(l)
42 end.X = util.Clamp(end.X, 0, nchars)
43 l = util.SliceStart(l, end.X)
46 match := r.FindIndex(l)
49 start := Loc{charpos + util.RunePos(l, match[0]), i}
50 end := Loc{charpos + util.RunePos(l, match[1]), i}
51 return [2]Loc{start, end}, true
54 return [2]Loc{}, false
57 func (b *Buffer) findUp(r *regexp.Regexp, start, end Loc) ([2]Loc, bool) {
58 lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
59 if start.Y > b.LinesNum()-1 {
62 if end.Y > b.LinesNum()-1 {
65 start.Y = util.Clamp(start.Y, 0, b.LinesNum()-1)
66 end.Y = util.Clamp(end.Y, 0, b.LinesNum()-1)
68 if start.GreaterThan(end) {
69 start, end = end, start
72 for i := end.Y; i >= start.Y; i-- {
76 if i == start.Y && start.Y == end.Y {
77 nchars := util.CharacterCount(l)
78 start.X = util.Clamp(start.X, 0, nchars)
79 end.X = util.Clamp(end.X, 0, nchars)
80 l = util.SliceStart(l, end.X)
81 l = util.SliceEnd(l, start.X)
83 } else if i == start.Y {
84 nchars := util.CharacterCount(l)
85 start.X = util.Clamp(start.X, 0, nchars)
86 l = util.SliceEnd(l, start.X)
88 } else if i == end.Y {
89 nchars := util.CharacterCount(l)
90 end.X = util.Clamp(end.X, 0, nchars)
91 l = util.SliceStart(l, end.X)
94 allMatches := r.FindAllIndex(l, -1)
96 if allMatches != nil {
97 match := allMatches[len(allMatches)-1]
98 start := Loc{charpos + util.RunePos(l, match[0]), i}
99 end := Loc{charpos + util.RunePos(l, match[1]), i}
100 return [2]Loc{start, end}, true
103 return [2]Loc{}, false
106 // FindNext finds the next occurrence of a given string in the buffer
107 // It returns the start and end location of the match (if found) and
108 // a boolean indicating if it was found
109 // May also return an error if the search regex is invalid
110 func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bool) ([2]Loc, bool, error) {
112 return [2]Loc{}, false, nil
119 s = regexp.QuoteMeta(s)
122 if b.Settings["ignorecase"].(bool) {
123 r, err = regexp.Compile("(?i)" + s)
125 r, err = regexp.Compile(s)
129 return [2]Loc{}, false, err
135 l, found = b.findDown(r, from, end)
137 l, found = b.findDown(r, start, end)
140 l, found = b.findUp(r, from, start)
142 l, found = b.findUp(r, end, start)
148 // ReplaceRegex replaces all occurrences of 'search' with 'replace' in the given area
149 // and returns the number of replacements made and the number of runes
150 // added or removed on the last line of the range
151 func (b *Buffer) ReplaceRegex(start, end Loc, search *regexp.Regexp, replace []byte) (int, int) {
152 if start.GreaterThan(end) {
153 start, end = end, start
160 for i := start.Y; i <= end.Y; i++ {
164 if start.Y == end.Y && i == start.Y {
165 l = util.SliceStart(l, end.X)
166 l = util.SliceEnd(l, start.X)
168 } else if i == start.Y {
169 l = util.SliceEnd(l, start.X)
171 } else if i == end.Y {
172 l = util.SliceStart(l, end.X)
174 newText := search.ReplaceAllFunc(l, func(in []byte) []byte {
176 for _, submatches := range search.FindAllSubmatchIndex(in, -1) {
177 result = search.Expand(result, replace, in, submatches)
181 netrunes += util.CharacterCount(result) - util.CharacterCount(in)
186 from := Loc{charpos, i}
187 to := Loc{charpos + util.CharacterCount(l), i}
189 deltas = append(deltas, Delta{newText, from, to})
191 b.MultipleReplace(deltas)
193 return found, netrunes