xah-replace-pairs.el is a emacs lisp package for doing multi-pair find replace.
(the package was named “xfrp_find_replace_pairs.el”)
Here's a sample use:
(require 'xah-replace-pairs) (xah-replace-pairs-in-string "abcdef" [["a" "1"] ["b" "2"] ["c" "3"]]) ;; returns "123def"
It's also on MELPA [see Emacs: How to Install Packages Using ELPA, MELPA]
Why Multi-Pair Find Replace?
You have a given region in a buffer. You want to do more than one pair of find replace strings. For example:
The normal way to do find replace in a region is like this:
(defun replace-html-chars-region (begin end) "Replace “<” to “<” etc in region." (interactive "r") (save-restriction (narrow-to-region begin end) (goto-char (point-min)) (while (search-forward "&" nil t) (replace-match "&" nil t)) (goto-char (point-min)) (while (search-forward "<" nil t) (replace-match "<" nil t)) (goto-char (point-min)) (while (search-forward ">" nil t) (replace-match ">" nil t))))
now you can write it like this:
(require 'xah-replace-pairs) (defun replace-html-chars-region (begin end) (interactive "r") (xah-replace-pairs-region begin end '( ["&" "&"] ["<" "<"] [">" ">"] )))
Here's sample use.
(defun replace-greek-to-unicode (@begin @end) "Replace alpha to α, beta to β etc in current line or selection." (interactive (if (use-region-p) (list (region-beginning) (region-end)) (list (line-beginning-position) (line-end-position)))) (let ((case-fold-search nil)) (xah-replace-pairs-region @begin @end '( ["alpha" "α"] ["beta" "β"] ["gamma" "γ"] ["pi" "π"] ) 'REPORT 'HILIGHT )))
Full code at Emacs: Replace Greek Letter Names to Unicode
It implements these functions:
For each function, there's a plain text version and a regex version. They are separate functions so it's simpler for user.
Each function also has a string and region version. The string version works on a given string, the region version works on a region in buffer.
Find Replace Feedback Loop Problem
If find replace pairs is done one after one, then you may end up with a substring that's not in the original input string nor in any of the find replace pairs. For example.
- Expected result
- Sequential find replace result
xah-replace-pairs-region will not have the feedback loop problem. It guarantees that a replacement is done IF AND ONLY IF the original input string contains a substring in one of your find string.
Real World Implication
Suppose you are working on a HTML tutorial that discusses HTML entities. Suppose the file contains this string:
use “&copy;” for ©
The intended display is
use “©” for ©.
and you want the HTML source code to be:
use “&copy;” for ©
However, if you are sequentially replacing each entities, the
& part will become
© becomes just
©, so you got
use “©” for © WRONG!
For many examples of using multi-pair find/replace, See: Emacs Lisp Find Replace String-Pairs Commands.