[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master caf64ae 2/3: Add new, simple `replace-in-string' function
From: |
Lars Ingebrigtsen |
Subject: |
master caf64ae 2/3: Add new, simple `replace-in-string' function |
Date: |
Tue, 15 Sep 2020 11:16:25 -0400 (EDT) |
branch: master
commit caf64ae08bff5c89a8eb0433891cc81f789b3efc
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>
Add new, simple `replace-in-string' function
* lisp/subr.el (replace-in-string): New, side-effect-free function.
* doc/lispref/searching.texi (Search and Replace): Document it.
---
doc/lispref/searching.texi | 7 ++++++-
etc/NEWS | 6 ++++++
lisp/subr.el | 30 ++++++++++++++++++++++++++++++
test/lisp/subr-tests.el | 12 ++++++++++++
4 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index b6242c5..a217c6e 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -2542,7 +2542,7 @@ and replace them, the best way is to write an explicit
loop using
description of @code{replace-match}.
However, replacing matches in a string is more complex, especially
-if you want to do it efficiently. So Emacs provides a function to do
+if you want to do it efficiently. So Emacs provides two functions to do
this.
@defun replace-regexp-in-string regexp rep string &optional fixedcase literal
subexp start
@@ -2566,6 +2566,11 @@ replacement string. The match data at this point are
the result
of matching @var{regexp} against a substring of @var{string}.
@end defun
+@defun replace-in-string fromstring tostring instring
+This function copies @var{instring} and replaces any occurrences of
+@var{fromstring} with @var{tostring}.
+@end defun
+
If you want to write a command along the lines of @code{query-replace},
you can use @code{perform-replace} to do the work.
diff --git a/etc/NEWS b/etc/NEWS
index 2928fd9..c9221a2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1317,6 +1317,12 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
* Lisp Changes in Emacs 28.1
++++
+*** New function 'replace-in-string'.
+This function works along the line of 'replace-regexp-in-string', but
+matching on strings instead of regexps, and does not change the global
+match state.
+
---
*** 'ascii' is now a coding system alias for 'us-ascii'.
diff --git a/lisp/subr.el b/lisp/subr.el
index b1537fd..b833176 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4411,6 +4411,36 @@ Unless optional argument INPLACE is non-nil, return a
new string."
(aset newstr i tochar)))
newstr))
+(defun replace-in-string (fromstring tostring instring)
+ "Replace FROMSTRING with TOSTRING in INSTRING each time it occurs.
+This function returns a freshly created string."
+ (declare (side-effect-free t))
+ (let ((i 0)
+ (start 0)
+ (result nil))
+ (while (< i (length instring))
+ (if (eq (aref instring i)
+ (aref fromstring 0))
+ ;; See if we're in a match.
+ (let ((ii i)
+ (if 0))
+ (while (and (< ii (length instring))
+ (< if (length fromstring))
+ (eq (aref instring ii)
+ (aref fromstring if)))
+ (setq ii (1+ ii)
+ if (1+ if)))
+ (when (= if (length fromstring))
+ (when (not (= start i))
+ (push (substring instring start i) result))
+ (push tostring result)
+ (setq i ii
+ start ii)))
+ (setq i (1+ i))))
+ (when (not (= start i))
+ (push (substring instring start i) result))
+ (apply #'concat (nreverse result))))
+
(defun replace-regexp-in-string (regexp rep string &optional
fixedcase literal subexp start)
"Replace all matches for REGEXP with REP in STRING.
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 2df5537..8bec097 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -440,5 +440,17 @@ See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19350.";
(should-error (ignore-error foo
(read ""))))
+(ert-deftest replace-in-string ()
+ (should (equal (replace-in-string "foo" "bar" "zot")
+ "zot"))
+ (should (equal (replace-in-string "foo" "bar" "foozot")
+ "barzot"))
+ (should (equal (replace-in-string "foo" "bar" "barfoozot")
+ "barbarzot"))
+ (should (equal (replace-in-string "zot" "bar" "barfoozot")
+ "barfoobar"))
+ (should (equal (replace-in-string "z" "bar" "barfoozot")
+ "barfoobarot")))
+
(provide 'subr-tests)
;;; subr-tests.el ends here