Skip to content

Commit

Permalink
added Clamp for Loc and streamlined code
Browse files Browse the repository at this point in the history
  • Loading branch information
matthias314 committed Jan 22, 2025
1 parent 5704643 commit 7943952
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 57 deletions.
17 changes: 11 additions & 6 deletions internal/buffer/loc.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ func (l Loc) LessEqual(b Loc) bool {
return l == b
}

// Clamp clamps a loc between start and end
func (l Loc) Clamp(start, end Loc) Loc {
if l.GreaterThan(end) {
return end
} else if l.LessThan(start) {
return start
}
return l
}

// The following functions require a buffer to know where newlines are

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

// clamps a loc within a buffer
func clamp(pos Loc, la *LineArray) Loc {
if pos.GreaterEqual(la.End()) {
return la.End()
} else if pos.LessThan(la.Start()) {
return la.Start()
}
return pos
return pos.Clamp(la.Start(), la.End())
}
88 changes: 37 additions & 51 deletions internal/buffer/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,64 +194,50 @@ func (b *Buffer) ReplaceRegex(start, end Loc, search *regexp.Regexp, replace []b

charsEnd := util.CharacterCount(b.LineBytes(end.Y))
found := 0
var charCount int
var deltas []Delta

// This replacement function works in general, but it creates a separate
// modification for each match. We only use it for the first and last lines,
// which may use padded regexps
replaceFirstLast := func(start, end Loc) []Delta {
matches := b.findAll(search, start, end)
for j := len(matches) - 1; j >= 0; j-- {
// if we counted upwards, the different deltas would interfere
match := matches[j]
var newText []byte
if captureGroups {
newText = search.ReplaceAll(b.Substr(match[0], match[1]), replace)
} else {
newText = replace
for i := start.Y; i <= end.Y; i++ {
l := b.LineBytes(i)
charCount = util.CharacterCount(l)
if i == start.Y || i == end.Y {
// This replacement code works in general, but it creates a separate
// modification for each match. We only use it for the first and last
// lines, which may use padded regexps

from := Loc{0, i}.Clamp(start, end)
to := Loc{charCount, i}.Clamp(start, end)
matches := b.findAll(search, from, to)
found += len(matches)

for j := len(matches) - 1; j >= 0; j-- {
// if we counted upwards, the different deltas would interfere
match := matches[j]
var newText []byte
if captureGroups {
newText = search.ReplaceAll(b.Substr(match[0], match[1]), replace)
} else {
newText = replace
}
deltas = append(deltas, Delta{newText, match[0], match[1]})
}
deltas = append(deltas, Delta{newText, match[0], match[1]})
}
found += len(matches)
return deltas
}

replaceMiddle := func(in []byte) []byte {
found++
var result []byte
if captureGroups {
match := search.FindSubmatchIndex(in)
result = search.Expand(result, replace, in, match)
} else {
result = replace
newLine := search.ReplaceAllFunc(l, func(in []byte) []byte {
found++
var result []byte
if captureGroups {
match := search.FindSubmatchIndex(in)
result = search.Expand(result, replace, in, match)
} else {
result = replace
}
return result
})
deltas = append(deltas, Delta{newLine, Loc{0, i}, Loc{charCount, i}})
}
return result
}

// first line (if different from last line)
if start.Y < end.Y {
n := util.CharacterCount(b.LineBytes(start.Y))
startEnd := Loc{n, start.Y}
deltas = replaceFirstLast(start, startEnd)
}

// middle lines
for i := start.Y + 1; i < end.Y; i++ {
l := b.LineBytes(i)
n := util.CharacterCount(l)
newLine := search.ReplaceAllFunc(l, replaceMiddle)
deltas = append(deltas, Delta{newLine, Loc{0, i}, Loc{n, i}})
}

// last line
endStart := Loc{0, end.Y}
if start.Y == end.Y {
endStart = start
}
deltas = replaceFirstLast(endStart, end)

b.MultipleReplace(deltas)

deltaEndX := util.CharacterCount(b.LineBytes(end.Y)) - charsEnd
return found, deltaEndX
return found, charCount - charsEnd
}

0 comments on commit 7943952

Please sign in to comment.