Skip to content

Commit 8683a1a

Browse files
committed
made search and replace functions accept RegexpGroup argument
1 parent 82e77d0 commit 8683a1a

2 files changed

Lines changed: 87 additions & 71 deletions

File tree

internal/action/command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ func (h *BufPane) ReplaceCmd(args []string) {
974974
lastMatchEnd := buffer.LocVoid()
975975
var doReplacement func()
976976
doReplacement = func() {
977-
locs := h.Buf.FindDown(rgrp, searchLoc, end)
977+
locs, _ := h.Buf.FindDown(rgrp, searchLoc, end)
978978
if locs == nil || !inRange(locs[0]) || !inRange(locs[1]) {
979979
h.Cursor.ResetSelection()
980980
h.Buf.RelocateCursors()

internal/buffer/search.go

Lines changed: 86 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package buffer
22

33
import (
4+
"fmt"
45
"regexp"
56
"unicode/utf8"
67

@@ -32,9 +33,25 @@ func NewRegexpGroup(s string) (RegexpGroup, error) {
3233
return rgrp, err
3334
}
3435

36+
func regexpGroup(re any) (RegexpGroup, error) {
37+
switch re := re.(type) {
38+
case RegexpGroup:
39+
return re, nil
40+
case string:
41+
return NewRegexpGroup(re)
42+
default:
43+
return RegexpGroup{}, fmt.Errorf(`cannot convert "%v" (of type %[1]T) to type RegexpGroup`, re)
44+
}
45+
}
46+
3547
type bytesFind func(*regexp.Regexp, []byte) []int
3648

37-
func (b *Buffer) findDownFunc(rgrp RegexpGroup, start, end Loc, find bytesFind) []Loc {
49+
func (b *Buffer) findDownFunc(re any, start, end Loc, find bytesFind) ([]Loc, error) {
50+
rgrp, err := regexpGroup(re)
51+
if err != nil {
52+
return nil, err
53+
}
54+
3855
lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
3956
if start.Y > b.LinesNum()-1 {
4057
start.X = lastcn - 1
@@ -95,30 +112,35 @@ func (b *Buffer) findDownFunc(rgrp RegexpGroup, start, end Loc, find bytesFind)
95112
} else { // start or end of unused submatch
96113
return LocVoid()
97114
}
98-
})
115+
}), nil
99116
}
100117
}
101-
return nil
118+
return nil, nil
102119
}
103120

104-
type bufferFind func(*Buffer, RegexpGroup, Loc, Loc) []Loc
121+
type bufferFind func(*Buffer, any, Loc, Loc) ([]Loc, error)
105122

106123
// FindDown returns a slice containing the start and end positions
107-
// of the first match of `rgrp` between `start` and `end`, or nil
124+
// of the first match of `re` between `start` and `end`, or nil
108125
// if no match exists.
109-
func (b *Buffer) FindDown(rgrp RegexpGroup, start, end Loc) []Loc {
110-
return b.findDownFunc(rgrp, start, end, (*regexp.Regexp).FindIndex)
126+
func (b *Buffer) FindDown(re any, start, end Loc) ([]Loc, error) {
127+
return b.findDownFunc(re, start, end, (*regexp.Regexp).FindIndex)
111128
}
112129

113130
// FindDownSubmatch returns a slice containing the start and end positions
114-
// of the first match of `rgrp` between `start` and `end` plus those
131+
// of the first match of `re` between `start` and `end` plus those
115132
// of all submatches (capturing groups), or nil if no match exists.
116133
// The start and end positions of an unused submatch are void.
117-
func (b *Buffer) FindDownSubmatch(rgrp RegexpGroup, start, end Loc) []Loc {
118-
return b.findDownFunc(rgrp, start, end, (*regexp.Regexp).FindSubmatchIndex)
134+
func (b *Buffer) FindDownSubmatch(re any, start, end Loc) ([]Loc, error) {
135+
return b.findDownFunc(re, start, end, (*regexp.Regexp).FindSubmatchIndex)
119136
}
120137

121-
func (b *Buffer) findUpFunc(rgrp RegexpGroup, start, end Loc, find bytesFind) []Loc {
138+
func (b *Buffer) findUpFunc(re any, start, end Loc, find bytesFind) ([]Loc, error) {
139+
rgrp, err := regexpGroup(re)
140+
if err != nil {
141+
return nil, err
142+
}
143+
122144
lastcn := util.CharacterCount(b.LineBytes(b.LinesNum() - 1))
123145
if start.Y > b.LinesNum()-1 {
124146
start.X = lastcn - 1
@@ -139,24 +161,24 @@ func (b *Buffer) findUpFunc(rgrp RegexpGroup, start, end Loc, find bytesFind) []
139161
from := Loc{0, i}.Clamp(start, end)
140162
to := Loc{charCount, i}.Clamp(start, end)
141163

142-
b.findAllFuncFunc(rgrp, from, to, func(b *Buffer, rgrp RegexpGroup, start, end Loc) []Loc {
164+
b.findAllFuncFunc(rgrp, from, to, func(b *Buffer, re any, start, end Loc) ([]Loc, error) {
143165
return b.findDownFunc(rgrp, start, end, find)
144166
}, func(match []Loc) {
145167
locs = match
146168
})
147169

148170
if locs != nil {
149-
return locs
171+
return locs, nil
150172
}
151173
}
152-
return nil
174+
return nil, nil
153175
}
154176

155177
// FindUp returns a slice containing the start and end positions
156-
// of the last match of `rgrp` between `start` and `end`, or nil
178+
// of the last match of `re` between `start` and `end`, or nil
157179
// if no match exists.
158-
func (b *Buffer) FindUp(rgrp RegexpGroup, start, end Loc) []Loc {
159-
return b.findUpFunc(rgrp, start, end, func(re *regexp.Regexp, l []byte) []int {
180+
func (b *Buffer) FindUp(re any, start, end Loc) ([]Loc, error) {
181+
return b.findUpFunc(re, start, end, func(re *regexp.Regexp, l []byte) []int {
160182
allMatches := re.FindAllIndex(l, -1)
161183
if allMatches != nil {
162184
return allMatches[len(allMatches)-1]
@@ -167,12 +189,12 @@ func (b *Buffer) FindUp(rgrp RegexpGroup, start, end Loc) []Loc {
167189
}
168190

169191
// FindUpSubmatch returns a slice containing the start and end positions
170-
// of the last match of `rgrp` between `start` and `end` plus those
192+
// of the last match of `re` between `start` and `end` plus those
171193
// of all submatches (capturing groups), or nil if no match exists.
172194
// The start and end positions of an unused submatch are void.
173-
func (b *Buffer) FindUpSubmatch(rgrp RegexpGroup, start, end Loc) []Loc {
174-
return b.findUpFunc(rgrp, start, end, func(re *regexp.Regexp, l []byte) []int {
175-
allMatches := re.FindAllSubmatchIndex(l, -1)
195+
func (b *Buffer) FindUpSubmatch(re any, start, end Loc) ([]Loc, error) {
196+
return b.findUpFunc(re, start, end, func(r *regexp.Regexp, l []byte) []int {
197+
allMatches := r.FindAllSubmatchIndex(l, -1)
176198
if allMatches != nil {
177199
return allMatches[len(allMatches)-1]
178200
} else {
@@ -181,11 +203,15 @@ func (b *Buffer) FindUpSubmatch(rgrp RegexpGroup, start, end Loc) []Loc {
181203
})
182204
}
183205

184-
func (b *Buffer) findAllFuncFunc(r RegexpGroup, start, end Loc, find bufferFind, f func([]Loc)) int {
206+
func (b *Buffer) findAllFuncFunc(re any, start, end Loc, find bufferFind, f func([]Loc)) (int, error) {
207+
rgrp, err := regexpGroup(re)
208+
if err != nil {
209+
return -1, err
210+
}
185211
n := 0
186212
loc := start
187213
for {
188-
match := find(b, r, loc, end)
214+
match, _ := find(b, rgrp, loc, end)
189215
if match == nil {
190216
break
191217
}
@@ -199,55 +225,45 @@ func (b *Buffer) findAllFuncFunc(r RegexpGroup, start, end Loc, find bufferFind,
199225
break
200226
}
201227
}
202-
return n
228+
return n, nil
203229
}
204230

205231
// FindAllFunc calls the function `f` once for each match between `start`
206-
// and `end` of the regexp given by `s`. The argument of `f` is the slice
232+
// and `end` of the regexp given by `re`. The argument of `f` is the slice
207233
// containing the start and end positions of the match. FindAllFunc returns
208234
// the number of matches plus any error that occured when compiling the regexp.
209-
func (b *Buffer) FindAllFunc(s string, start, end Loc, f func([]Loc)) (int, error) {
210-
rgrp, err := NewRegexpGroup(s)
211-
if err == nil {
212-
return b.findAllFuncFunc(rgrp, start, end, (*Buffer).FindDown, f), nil
213-
} else {
214-
return -1, err
215-
}
235+
func (b *Buffer) FindAllFunc(re any, start, end Loc, f func([]Loc)) (int, error) {
236+
return b.findAllFuncFunc(re, start, end, (*Buffer).FindDown, f)
216237
}
217238

218239
// FindAll returns a slice containing the start and end positions of all
219-
// matches between `start` and `end` of the regexp given by `s`, plus any
240+
// matches between `start` and `end` of the regexp given by `re`, plus any
220241
// error that occured when compiling the regexp. If no match is found, the
221242
// slice returned is nil.
222-
func (b *Buffer) FindAll(s string, start, end Loc) ([][]Loc, error) {
243+
func (b *Buffer) FindAll(re any, start, end Loc) ([][]Loc, error) {
223244
var matches [][]Loc
224-
_, err := b.FindAllFunc(s, start, end, func(match []Loc) {
245+
_, err := b.FindAllFunc(re, start, end, func(match []Loc) {
225246
matches = append(matches, match)
226247
})
227248
return matches, err
228249
}
229250

230251
// FindAllSubmatchFunc calls the function `f` once for each match between
231-
// `start` and `end` of the regexp given by `s`. The argument of `f` is the
252+
// `start` and `end` of the regexp given by `re`. The argument of `f` is the
232253
// slice containing the start and end positions of the match and all submatches
233254
// (capturing groups). FindAllSubmatch Func returns the number of matches plus
234255
// any error that occured when compiling the regexp.
235-
func (b *Buffer) FindAllSubmatchFunc(s string, start, end Loc, f func([]Loc)) (int, error) {
236-
rgrp, err := NewRegexpGroup(s)
237-
if err == nil {
238-
return b.findAllFuncFunc(rgrp, start, end, (*Buffer).FindDownSubmatch, f), nil
239-
} else {
240-
return -1, err
241-
}
256+
func (b *Buffer) FindAllSubmatchFunc(re any, start, end Loc, f func([]Loc)) (int, error) {
257+
return b.findAllFuncFunc(re, start, end, (*Buffer).FindDownSubmatch, f)
242258
}
243259

244260
// FindAllSubmatch returns a slice containing the start and end positions of
245261
// all matches and all submatches (capturing groups) between `start` and `end`
246-
// of the regexp given by `s`, plus any error that occured when compiling
262+
// of the regexp given by `re`, plus any error that occured when compiling
247263
// the regexp. If no match is found, the slice returned is nil.
248-
func (b *Buffer) FindAllSubmatch(s string, start, end Loc) ([][]Loc, error) {
264+
func (b *Buffer) FindAllSubmatch(re any, start, end Loc) ([][]Loc, error) {
249265
var matches [][]Loc
250-
_, err := b.FindAllSubmatchFunc(s, start, end, func(match []Loc) {
266+
_, err := b.FindAllSubmatchFunc(re, start, end, func(match []Loc) {
251267
matches = append(matches, match)
252268
})
253269
return matches, err
@@ -290,14 +306,14 @@ func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bo
290306

291307
var match []Loc
292308
if down {
293-
match = b.FindDown(rgrp, from, end)
309+
match, _ = b.FindDown(rgrp, from, end)
294310
if match == nil {
295-
match = b.FindDown(rgrp, start, end)
311+
match, _ = b.FindDown(rgrp, start, end)
296312
}
297313
} else {
298-
match = b.FindUp(rgrp, from, start)
314+
match, _ = b.FindUp(rgrp, from, start)
299315
if match == nil {
300-
match = b.FindUp(rgrp, end, start)
316+
match, _ = b.FindUp(rgrp, end, start)
301317
}
302318
}
303319
if match != nil {
@@ -307,33 +323,33 @@ func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bo
307323
}
308324
}
309325

310-
func (b *Buffer) replaceAllFuncFunc(s string, start, end Loc, find bufferFind, repl func(match []Loc) []byte) (int, Loc, error) {
311-
rgrp, err := NewRegexpGroup(s)
312-
if err != nil {
313-
return -1, LocVoid(), err
314-
}
315-
326+
func (b *Buffer) replaceAllFuncFunc(re any, start, end Loc, find bufferFind, repl func(match []Loc) []byte) (int, Loc, error) {
316327
charsEnd := util.CharacterCount(b.LineBytes(end.Y))
317328
var deltas []Delta
318329

319-
n := b.findAllFuncFunc(rgrp, start, end, find, func(match []Loc) {
330+
n, err := b.findAllFuncFunc(re, start, end, find, func(match []Loc) {
320331
deltas = append(deltas, Delta{repl(match), match[0], match[1]})
321332
})
333+
334+
if err != nil {
335+
return -1, LocVoid(), err
336+
}
337+
322338
b.MultipleReplace(deltas)
323339

324340
deltaX := util.CharacterCount(b.LineBytes(end.Y)) - charsEnd
325341
return n, Loc{end.X + deltaX, end.Y}, nil
326342
}
327343

328-
// ReplaceAll replaces all matches of the regexp `s` in the given area. The
344+
// ReplaceAll replaces all matches of the regexp `re` in the given area. The
329345
// new text is obtained from `template` by replacing each variable with the
330346
// corresponding submatch as in `Regexp.Expand`. The function returns the
331347
// number of replacements made, the new end position and any error that
332348
// occured during regexp compilation
333-
func (b *Buffer) ReplaceAll(s string, start, end Loc, template []byte) (int, Loc, error) {
349+
func (b *Buffer) ReplaceAll(re any, start, end Loc, template []byte) (int, Loc, error) {
334350
var replace []byte
335351

336-
find := func(b *Buffer, r RegexpGroup, start, end Loc) []Loc {
352+
find := func(b *Buffer, r any, start, end Loc) ([]Loc, error) {
337353
return b.findDownFunc(r, start, end, func(re *regexp.Regexp, l []byte) []int {
338354
match := re.FindSubmatchIndex(l)
339355
if match == nil {
@@ -344,34 +360,34 @@ func (b *Buffer) ReplaceAll(s string, start, end Loc, template []byte) (int, Loc
344360
})
345361
}
346362

347-
return b.replaceAllFuncFunc(s, start, end, find, func(match []Loc) []byte {
363+
return b.replaceAllFuncFunc(re, start, end, find, func(match []Loc) []byte {
348364
return replace
349365
})
350366
}
351367

352-
// ReplaceAllLiteral replaces all matches of the regexp `s` with `repl` in
368+
// ReplaceAllLiteral replaces all matches of the regexp `re` with `repl` in
353369
// the given area. The function returns the number of replacements made, the
354370
// new end position and any error that occured during regexp compilation
355-
func (b *Buffer) ReplaceAllLiteral(s string, start, end Loc, repl []byte) (int, Loc, error) {
356-
return b.ReplaceAllFunc(s, start, end, func([]Loc) []byte {
371+
func (b *Buffer) ReplaceAllLiteral(re any, start, end Loc, repl []byte) (int, Loc, error) {
372+
return b.ReplaceAllFunc(re, start, end, func([]Loc) []byte {
357373
return repl
358374
})
359375
}
360376

361-
// ReplaceAllFunc replaces all matches of the regexp `s` with `repl(match)`
377+
// ReplaceAllFunc replaces all matches of the regexp `re` with `repl(match)`
362378
// in the given area, where `match` is the slice containing start and end
363379
// positions of the match. The function returns the number of replacements
364380
// made, the new end position and any error that occured during regexp
365381
// compilation
366-
func (b *Buffer) ReplaceAllFunc(s string, start, end Loc, repl func(match []Loc) []byte) (int, Loc, error) {
367-
return b.replaceAllFuncFunc(s, start, end, (*Buffer).FindDown, repl)
382+
func (b *Buffer) ReplaceAllFunc(re any, start, end Loc, repl func(match []Loc) []byte) (int, Loc, error) {
383+
return b.replaceAllFuncFunc(re, start, end, (*Buffer).FindDown, repl)
368384
}
369385

370-
// ReplaceAllSubmatchFunc replaces all matches of the regexp `s` with
386+
// ReplaceAllSubmatchFunc replaces all matches of the regexp `re` with
371387
// `repl(match)` in the given area, where `match` is the slice containing
372388
// start and end positions of the match and all submatches. The function
373389
// returns the number of replacements made, the new end position and any
374390
// error that occured during regexp compilation
375-
func (b *Buffer) ReplaceAllSubmatchFunc(s string, start, end Loc, repl func(match []Loc) []byte) (int, Loc, error) {
376-
return b.replaceAllFuncFunc(s, start, end, (*Buffer).FindDownSubmatch, repl)
391+
func (b *Buffer) ReplaceAllSubmatchFunc(re any, start, end Loc, repl func(match []Loc) []byte) (int, Loc, error) {
392+
return b.replaceAllFuncFunc(re, start, end, (*Buffer).FindDownSubmatch, repl)
377393
}

0 commit comments

Comments
 (0)