Skip to content

Commit 7943952

Browse files
committed
added Clamp for Loc and streamlined code
1 parent 5704643 commit 7943952

2 files changed

Lines changed: 48 additions & 57 deletions

File tree

internal/buffer/loc.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ func (l Loc) LessEqual(b Loc) bool {
4747
return l == b
4848
}
4949

50+
// Clamp clamps a loc between start and end
51+
func (l Loc) Clamp(start, end Loc) Loc {
52+
if l.GreaterThan(end) {
53+
return end
54+
} else if l.LessThan(start) {
55+
return start
56+
}
57+
return l
58+
}
59+
5060
// The following functions require a buffer to know where newlines are
5161

5262
// Diff returns the distance between two locations
@@ -139,10 +149,5 @@ func ByteOffset(pos Loc, buf *Buffer) int {
139149

140150
// clamps a loc within a buffer
141151
func clamp(pos Loc, la *LineArray) Loc {
142-
if pos.GreaterEqual(la.End()) {
143-
return la.End()
144-
} else if pos.LessThan(la.Start()) {
145-
return la.Start()
146-
}
147-
return pos
152+
return pos.Clamp(la.Start(), la.End())
148153
}

internal/buffer/search.go

Lines changed: 37 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -194,64 +194,50 @@ func (b *Buffer) ReplaceRegex(start, end Loc, search *regexp.Regexp, replace []b
194194

195195
charsEnd := util.CharacterCount(b.LineBytes(end.Y))
196196
found := 0
197+
var charCount int
197198
var deltas []Delta
198199

199-
// This replacement function works in general, but it creates a separate
200-
// modification for each match. We only use it for the first and last lines,
201-
// which may use padded regexps
202-
replaceFirstLast := func(start, end Loc) []Delta {
203-
matches := b.findAll(search, start, end)
204-
for j := len(matches) - 1; j >= 0; j-- {
205-
// if we counted upwards, the different deltas would interfere
206-
match := matches[j]
207-
var newText []byte
208-
if captureGroups {
209-
newText = search.ReplaceAll(b.Substr(match[0], match[1]), replace)
210-
} else {
211-
newText = replace
200+
for i := start.Y; i <= end.Y; i++ {
201+
l := b.LineBytes(i)
202+
charCount = util.CharacterCount(l)
203+
if i == start.Y || i == end.Y {
204+
// This replacement code works in general, but it creates a separate
205+
// modification for each match. We only use it for the first and last
206+
// lines, which may use padded regexps
207+
208+
from := Loc{0, i}.Clamp(start, end)
209+
to := Loc{charCount, i}.Clamp(start, end)
210+
matches := b.findAll(search, from, to)
211+
found += len(matches)
212+
213+
for j := len(matches) - 1; j >= 0; j-- {
214+
// if we counted upwards, the different deltas would interfere
215+
match := matches[j]
216+
var newText []byte
217+
if captureGroups {
218+
newText = search.ReplaceAll(b.Substr(match[0], match[1]), replace)
219+
} else {
220+
newText = replace
221+
}
222+
deltas = append(deltas, Delta{newText, match[0], match[1]})
212223
}
213-
deltas = append(deltas, Delta{newText, match[0], match[1]})
214-
}
215-
found += len(matches)
216-
return deltas
217-
}
218-
219-
replaceMiddle := func(in []byte) []byte {
220-
found++
221-
var result []byte
222-
if captureGroups {
223-
match := search.FindSubmatchIndex(in)
224-
result = search.Expand(result, replace, in, match)
225224
} else {
226-
result = replace
225+
newLine := search.ReplaceAllFunc(l, func(in []byte) []byte {
226+
found++
227+
var result []byte
228+
if captureGroups {
229+
match := search.FindSubmatchIndex(in)
230+
result = search.Expand(result, replace, in, match)
231+
} else {
232+
result = replace
233+
}
234+
return result
235+
})
236+
deltas = append(deltas, Delta{newLine, Loc{0, i}, Loc{charCount, i}})
227237
}
228-
return result
229-
}
230-
231-
// first line (if different from last line)
232-
if start.Y < end.Y {
233-
n := util.CharacterCount(b.LineBytes(start.Y))
234-
startEnd := Loc{n, start.Y}
235-
deltas = replaceFirstLast(start, startEnd)
236-
}
237-
238-
// middle lines
239-
for i := start.Y + 1; i < end.Y; i++ {
240-
l := b.LineBytes(i)
241-
n := util.CharacterCount(l)
242-
newLine := search.ReplaceAllFunc(l, replaceMiddle)
243-
deltas = append(deltas, Delta{newLine, Loc{0, i}, Loc{n, i}})
244-
}
245-
246-
// last line
247-
endStart := Loc{0, end.Y}
248-
if start.Y == end.Y {
249-
endStart = start
250238
}
251-
deltas = replaceFirstLast(endStart, end)
252239

253240
b.MultipleReplace(deltas)
254241

255-
deltaEndX := util.CharacterCount(b.LineBytes(end.Y)) - charsEnd
256-
return found, deltaEndX
242+
return found, charCount - charsEnd
257243
}

0 commit comments

Comments
 (0)