command: Fix replace to be able to insert '$' (#2954)

* 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>
This commit is contained in:
Jöran Karl 2024-03-17 21:37:16 +01:00 committed by GitHub
parent 5ae2799b70
commit c64add289b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 16 additions and 6 deletions

View File

@ -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)
@ -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)

View File

@ -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
}
@ -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 {

View File

@ -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.