From c64add289b396b35f790c5b20b9db9c750fb1706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6ran=20Karl?= <3951388+JoeKar@users.noreply.github.com> Date: Sun, 17 Mar 2024 21:37:16 +0100 Subject: [PATCH] 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 * Fix replace with '$' in a more kosher way On top of JoeKar's fix. --------- Co-authored-by: Beni Cherniavsky-Paskin Co-authored-by: Dmytro Maluka --- internal/action/command.go | 4 ++-- internal/buffer/search.go | 12 ++++++++---- runtime/help/commands.md | 6 ++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/internal/action/command.go b/internal/action/command.go index e241d687..32ed686b 100644 --- a/internal/action/command.go +++ b/internal/action/command.go @@ -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) diff --git a/internal/buffer/search.go b/internal/buffer/search.go index 0ab6d0c8..14ae2517 100644 --- a/internal/buffer/search.go +++ b/internal/buffer/search.go @@ -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 { diff --git a/runtime/help/commands.md b/runtime/help/commands.md index 8bc4e8ab..8e191f9f 100644 --- a/runtime/help/commands.md +++ b/runtime/help/commands.md @@ -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 (?Pnamed 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.