branch: elpa/iedit commit 6392399b08cff63f2b07208b2d2c78bae40f335f Author: Victor <victor...@gmail.com> Commit: Victor Ren <victor...@gmail.com>
Allow special '\' in replacement of `iedit-replace-occurrences' With a prefix arguement, replacement string of `iedit-replace-occurrences' needs not to be constant. The things like `\\,' `\\&' and `\\#' can be used in TO-STRING and treated specially, the same way as `replace-regexp'. --- iedit-lib.el | 86 +++++++++++++++++++++++++++++++++++----------------------- iedit-tests.el | 15 +++++++--- 2 files changed, 63 insertions(+), 38 deletions(-) diff --git a/iedit-lib.el b/iedit-lib.el index 6fa586b0095..8bd30d3124b 100644 --- a/iedit-lib.el +++ b/iedit-lib.el @@ -1,7 +1,7 @@ ;;; iedit-lib.el --- APIs for editing multiple regions in the same way ;;; simultaneously. -;; Copyright (C) 2010 - 2019, 2020, 2021 Victor Ren +;; Copyright (C) 2010 - 2022 Victor Ren ;; Time-stamp: <2022-01-14 12:33:36 Victor Ren> ;; Author: Victor Ren <victor...@gmail.com> @@ -854,6 +854,24 @@ value of `iedit-occurrence-context-lines' is used for this time." (dolist (occurrence iedit-occurrences-overlays) (apply function (overlay-start occurrence) (overlay-end occurrence) args))))) +(defun iedit-apply-on-occurrences-in-seq (function &rest args) + "Call function for each occurrence in sequence." + (let ((iedit-updating t)) + (save-excursion + (goto-char (iedit-first-occurrence)) + (cl-loop for counter from 0 + for ov = (iedit-find-current-occurrence-overlay) + while (/= (point) (point-max)) + do (progn + (apply function ov counter args) + (iedit-move-conjoined-overlays ov) + ;; goto the beginning of the next occurrence overlay + (if (iedit-find-overlay-at-point (overlay-end ov) 'iedit-occurrence-overlay-name) + (goto-char (overlay-end ov)) ; conjoined overlay + (when (< (point) (overlay-end ov)) + (goto-char (next-single-char-property-change (point) 'iedit-occurrence-overlay-name))) + (goto-char (next-single-char-property-change (point) 'iedit-occurrence-overlay-name)))))))) + (defun iedit-upcase-occurrences () "Convert occurrences to upper case." (interactive "*") @@ -883,47 +901,47 @@ FORMAT." nil nil iedit-increment-format-string))) (list 1 iedit-increment-format-string))) (iedit-barf-if-buffering) - (let ((number start-at) - (iedit-updating t)) - (save-excursion - (goto-char (iedit-first-occurrence)) - (cl-loop for counter from number - for ov = (iedit-find-current-occurrence-overlay) - while (/= (point) (point-max)) - do (progn - (if (re-search-forward "\\\\#" (overlay-end ov) t) - (replace-match (format format-string counter) t) - (insert (format format-string counter))) - (iedit-move-conjoined-overlays ov) - ;; goto the beginning of the next occurrence overlay - (if (iedit-find-overlay-at-point (overlay-end ov) 'iedit-occurrence-overlay-name) - (goto-char (overlay-end ov)) ; conjoined overlay - (when (< (point) (overlay-end ov)) - (goto-char (next-single-char-property-change (point) 'iedit-occurrence-overlay-name))) - (goto-char (next-single-char-property-change (point) 'iedit-occurrence-overlay-name)))))))) + (iedit-apply-on-occurrences-in-seq + (lambda (ov count start-at) + (let ((counter (+ count start-at))) + (goto-char (overlay-start ov)) + (if (re-search-forward "\\\\#" (overlay-end ov) t) + (replace-match (format format-string counter) t) + (insert (format format-string counter))))) + start-at)) ;;; Don't downcase from-string to allow case freedom! (defun iedit-replace-occurrences(&optional to-string) - "Replace occurrences with STRING." + "Replace occurrences with TO-STRING. + +With a prefix arguement, TO-STRING needs not to be constant. The +things like `\\,' `\\&' `\\#' can be used in TO-STRING, the same +way as `replace-regexp'. Refer to the document of +`replace-string' and `replace-regexp' for the details about +TO-STRING." (interactive "*") (iedit-barf-if-buffering) (let* ((ov (iedit-find-current-occurrence-overlay)) (offset (- (point) (overlay-start ov))) - (from-string (buffer-substring-no-properties - (overlay-start ov) - (overlay-end ov))) + (literal (not current-prefix-arg)) (to-string (if (not to-string) - (read-string "Replace with: " - nil nil - from-string - nil) - to-string))) - (iedit-apply-on-occurrences - (lambda (beg end from-string to-string) - (goto-char beg) - (search-forward from-string end) - (replace-match to-string (not (and (not iedit-case-sensitive) case-replace)))) - from-string to-string) + (query-replace-read-to "occurrences" + "Replace" + (not literal)) + to-string))) + (iedit-apply-on-occurrences-in-seq + (lambda (ov count to-string literal) + (goto-char (overlay-start ov)) + (search-forward (buffer-substring-no-properties + (overlay-start ov) + (overlay-end ov)) + (overlay-end ov)) + (replace-match (if literal + to-string + (funcall (car to-string) (cdr to-string) count)) + (not (and (not iedit-case-sensitive) case-replace)) + literal)) + to-string literal) (goto-char (+ (overlay-start ov) offset)))) (defun iedit-blank-occurrences() diff --git a/iedit-tests.el b/iedit-tests.el index 9fcf927d912..f18666127ac 100644 --- a/iedit-tests.el +++ b/iedit-tests.el @@ -1,6 +1,6 @@ ;;; iedit-tests.el --- iedit's automatic-tests -;; Copyright (C) 2010 - 2019, 2020, 2022 Victor Ren +;; Copyright (C) 2010 - 2022 Victor Ren ;; Time-stamp: <2025-09-29 19:47:28 Victor Ren> ;; Author: Victor Ren <victor...@gmail.com> @@ -530,12 +530,19 @@ foo bar barfoo bar")) + (let ((current-prefix-arg 4)) + (iedit-replace-occurrences (query-replace-compile-replacement "\\,(format \"%s %d\" \\& \\#)" t ))) + (should (string= (buffer-string) +"bar 0 + bar 1 + barfoo + bar 2")) (iedit-number-occurrences 1 "%d ") (should (string= (buffer-string) -"1 bar - 2 bar +"1 bar 0 + 2 bar 1 barfoo - 3 bar"))))) + 3 bar 2"))))) (ert-deftest iedit-blank-occurrences-test () "Test functions deal with the whole occurrences"