Skip to content

Commit

Permalink
command: Fix replace to be able to insert '$' (#2954)
Browse files Browse the repository at this point in the history
* command: Fix replace to be able to insert '$'

* help: commands: Precise the documentation of `replace`

* help: commands: Further improvement suggested within the review

Co-authored-by: Beni Cherniavsky-Paskin <cben@redhat.com>

* Fix replace with '$' in a more kosher way

On top of JoeKar's fix.

---------

Co-authored-by: Beni Cherniavsky-Paskin <cben@redhat.com>
Co-authored-by: Dmytro Maluka <dmitrymaluka@gmail.com>
  • Loading branch information
3 people committed Mar 17, 2024
1 parent 5ae2799 commit c64add2
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 6 deletions.
4 changes: 2 additions & 2 deletions internal/action/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ func (h *BufPane) ReplaceCmd(args []string) {
end = h.Cursor.CurSelection[1]
}
if all {
nreplaced, _ = h.Buf.ReplaceRegex(start, end, regex, replace)
nreplaced, _ = h.Buf.ReplaceRegex(start, end, regex, replace, !noRegex)
} else {
inRange := func(l buffer.Loc) bool {
return l.GreaterEqual(start) && l.LessEqual(end)
Expand Down Expand Up @@ -850,7 +850,7 @@ func (h *BufPane) ReplaceCmd(args []string) {

InfoBar.YNPrompt("Perform replacement (y,n,esc)", func(yes, canceled bool) {
if !canceled && yes {
_, nrunes := h.Buf.ReplaceRegex(locs[0], locs[1], regex, replace)
_, nrunes := h.Buf.ReplaceRegex(locs[0], locs[1], regex, replace, !noRegex)

searchLoc = locs[0]
searchLoc.X += nrunes + locs[0].Diff(locs[1], h.Buf)
Expand Down
12 changes: 8 additions & 4 deletions internal/buffer/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func (b *Buffer) FindNext(s string, start, end, from Loc, down bool, useRegex bo
// ReplaceRegex replaces all occurrences of 'search' with 'replace' in the given area
// and returns the number of replacements made and the number of runes
// added or removed on the last line of the range
func (b *Buffer) ReplaceRegex(start, end Loc, search *regexp.Regexp, replace []byte) (int, int) {
func (b *Buffer) ReplaceRegex(start, end Loc, search *regexp.Regexp, replace []byte, captureGroups bool) (int, int) {
if start.GreaterThan(end) {
start, end = end, start
}
Expand All @@ -172,9 +172,13 @@ func (b *Buffer) ReplaceRegex(start, end Loc, search *regexp.Regexp, replace []b
l = util.SliceStart(l, end.X)
}
newText := search.ReplaceAllFunc(l, func(in []byte) []byte {
result := []byte{}
for _, submatches := range search.FindAllSubmatchIndex(in, -1) {
result = search.Expand(result, replace, in, submatches)
var result []byte
if captureGroups {
for _, submatches := range search.FindAllSubmatchIndex(in, -1) {
result = search.Expand(result, replace, in, submatches)
}
} else {
result = replace
}
found++
if i == end.Y {
Expand Down
6 changes: 6 additions & 0 deletions runtime/help/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ quotes here but these are not necessary when entering the command in micro.
Note that `search` must be a valid regex (unless `-l` is passed). If one
of the arguments does not have any spaces in it, you may omit the quotes.

In case the search is done non-literal (without `-l`), the 'value'
is interpreted as a template:
* `$3` or `${3}` substitutes the submatch of the 3rd (capturing group)
* `$foo` or `${foo}` substitutes the submatch of the (?P<foo>named group)
* You have to write `$$` to substitute a literal dollar.

* `replaceall 'search' 'value'`: this will replace all occurrences of `search`
with `value` without user confirmation.

Expand Down

0 comments on commit c64add2

Please sign in to comment.