aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/replace.el
diff options
context:
space:
mode:
authorDavid Kastrup2004-06-17 14:44:02 +0000
committerDavid Kastrup2004-06-17 14:44:02 +0000
commit2f57bf8593e0852e5bb8fc95f9341f5857efc504 (patch)
treea21662fd1fb6070d3f9dbdecf726511d9e102d8e /lisp/replace.el
parenta6cb6b787e03344d28e93bef1cce5a7930854158 (diff)
downloademacs-2f57bf8593e0852e5bb8fc95f9341f5857efc504.tar.gz
emacs-2f57bf8593e0852e5bb8fc95f9341f5857efc504.zip
(query-replace-read-args): Only warn about use of \n
and \t when we are doing a regexp replacement and the actual escaped character is n or t. (query-replace-regexp): Add \, and \# interpretation to interactive call and document it. (query-replace-regexp-eval, replace-match-string-symbols): add \# as shortkey for replace-count. (replace-quote): New function for doubling backslashes.
Diffstat (limited to 'lisp/replace.el')
-rw-r--r--lisp/replace.el104
1 files changed, 83 insertions, 21 deletions
diff --git a/lisp/replace.el b/lisp/replace.el
index 014762be53e..89f55c2829e 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1,7 +1,7 @@
1;;; replace.el --- replace commands for Emacs 1;;; replace.el --- replace commands for Emacs
2 2
3;; Copyright (C) 1985, 86, 87, 92, 94, 96, 1997, 2000, 2001, 2002 3;; Copyright (C) 1985, 86, 87, 92, 94, 96, 1997, 2000, 2001, 2002,
4;; Free Software Foundation, Inc. 4;; 2003, 2004 Free Software Foundation, Inc.
5 5
6;; Maintainer: FSF 6;; Maintainer: FSF
7 7
@@ -81,14 +81,15 @@ strings or patterns."
81 query-replace-from-history-variable 81 query-replace-from-history-variable
82 nil t))) 82 nil t)))
83 ;; Warn if user types \n or \t, but don't reject the input. 83 ;; Warn if user types \n or \t, but don't reject the input.
84 (if (string-match "\\\\[nt]" from) 84 (and regexp-flag
85 (let ((match (match-string 0 from))) 85 (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\[nt]\\)" from)
86 (cond 86 (let ((match (match-string 3 from)))
87 ((string= match "\\n") 87 (cond
88 (message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead")) 88 ((string= match "\\n")
89 ((string= match "\\t") 89 (message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
90 (message "Note: `\\t' here doesn't match a tab; to do that, just type TAB"))) 90 ((string= match "\\t")
91 (sit-for 2)))) 91 (message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
92 (sit-for 2))))
92 93
93 (save-excursion 94 (save-excursion
94 (setq to (read-from-minibuffer (format "%s %s with: " string from) 95 (setq to (read-from-minibuffer (format "%s %s with: " string from)
@@ -161,20 +162,62 @@ Fourth and fifth arg START and END specify the region to operate on.
161 162
162In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, 163In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP,
163and `\\=\\N' (where N is a digit) stands for 164and `\\=\\N' (where N is a digit) stands for
164 whatever what matched the Nth `\\(...\\)' in REGEXP." 165whatever what matched the Nth `\\(...\\)' in REGEXP.
166
167When this function is called interactively, the replacement text
168can also contain `\\,' followed by a Lisp expression. The escaped
169shorthands for `query-replace-regexp-eval' are also valid
170here: within the Lisp expression, you can use `\\&' for the whole
171match string, `\\N' for partial matches, `\\#&' and `\\#N' for
172the respective numeric values, and `\\#' for `replace-count'.
173
174If your Lisp expression is an identifier and the next
175letter in the replacement string would be interpreted as part of it,
176you can wrap it with an expression like `\\,(or \\#)'. Incidentally,
177for this particular case you may also enter `\\#' in the replacement
178text directly.
179
180When you use `\\,' or `\\#' in the replacement, TO-STRING actually
181becomes a list with expanded shorthands.
182Use \\[repeat-complex-command] after this command to see details."
165 (interactive 183 (interactive
166 (let ((common 184 (let ((common
167 (query-replace-read-args "Query replace regexp" t))) 185 (query-replace-read-args "Query replace regexp" t)))
168 (list (nth 0 common) (nth 1 common) (nth 2 common) 186 (list
169 ;; These are done separately here 187 (nth 0 common)
170 ;; so that command-history will record these expressions 188 (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
171 ;; rather than the values they had this time. 189 (nth 1 common))
172 (if (and transient-mark-mode mark-active) 190 (let ((to-string (nth 1 common)) pos to-expr char prompt)
173 (region-beginning)) 191 (while (string-match
174 (if (and transient-mark-mode mark-active) 192 "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
175 (region-end))))) 193 to-string)
176 194 (setq pos (match-end 0))
195 (push (substring to-string 0 (- pos 2)) to-expr)
196 (setq char (aref to-string (1- pos))
197 to-string (substring to-string pos))
198 (cond ((eq char ?\#)
199 (push '(number-to-string replace-count) to-expr))
200 ((eq char ?\,)
201 (setq pos (read-from-string to-string))
202 (push `(replace-quote ,(car pos)) to-expr)
203 (setq to-string (substring to-string (cdr pos))))))
204 (setq to-expr (nreverse (delete "" (cons to-string to-expr))))
205 (replace-match-string-symbols to-expr)
206 (cons 'replace-eval-replacement
207 (if (> (length to-expr) 1)
208 (cons 'concat to-expr)
209 (car to-expr))))
210 (nth 1 common))
211 (nth 2 common)
212 ;; These are done separately here
213 ;; so that command-history will record these expressions
214 ;; rather than the values they had this time.
215 (if (and transient-mark-mode mark-active)
216 (region-beginning))
217 (if (and transient-mark-mode mark-active)
218 (region-end)))))
177 (perform-replace regexp to-string t t delimited nil nil start end)) 219 (perform-replace regexp to-string t t delimited nil nil start end))
220
178(define-key esc-map [?\C-%] 'query-replace-regexp) 221(define-key esc-map [?\C-%] 'query-replace-regexp)
179 222
180(defun query-replace-regexp-eval (regexp to-expr &optional delimited start end) 223(defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
@@ -191,6 +234,7 @@ For convenience, when entering TO-EXPR interactively, you can use `\\&' or
191`\\0' to stand for whatever matched the whole of REGEXP, and `\\N' (where 234`\\0' to stand for whatever matched the whole of REGEXP, and `\\N' (where
192N is a digit) to stand for whatever matched the Nth `\\(...\\)' in REGEXP. 235N is a digit) to stand for whatever matched the Nth `\\(...\\)' in REGEXP.
193Use `\\#&' or `\\#N' if you want a number instead of a string. 236Use `\\#&' or `\\#N' if you want a number instead of a string.
237In interactive use, `\\#' in itself stands for `replace-count'.
194 238
195In Transient Mark mode, if the mark is active, operate on the contents 239In Transient Mark mode, if the mark is active, operate on the contents
196of the region. Otherwise, operate from point to the end of the buffer. 240of the region. Otherwise, operate from point to the end of the buffer.
@@ -1012,6 +1056,7 @@ N (match-string N) (where N is a string of digits)
1012#N (string-to-number (match-string N)) 1056#N (string-to-number (match-string N))
1013& (match-string 0) 1057& (match-string 0)
1014#& (string-to-number (match-string 0)) 1058#& (string-to-number (match-string 0))
1059# replace-count
1015 1060
1016Note that these symbols must be preceeded by a backslash in order to 1061Note that these symbols must be preceeded by a backslash in order to
1017type them." 1062type them."
@@ -1031,7 +1076,9 @@ type them."
1031 ((string= "&" name) 1076 ((string= "&" name)
1032 (setcar n '(match-string 0))) 1077 (setcar n '(match-string 0)))
1033 ((string= "#&" name) 1078 ((string= "#&" name)
1034 (setcar n '(string-to-number (match-string 0)))))))) 1079 (setcar n '(string-to-number (match-string 0))))
1080 ((string= "#" name)
1081 (setcar n 'replace-count))))))
1035 (setq n (cdr n)))) 1082 (setq n (cdr n))))
1036 1083
1037(defun replace-eval-replacement (expression replace-count) 1084(defun replace-eval-replacement (expression replace-count)
@@ -1040,6 +1087,21 @@ type them."
1040 replacement 1087 replacement
1041 (prin1-to-string replacement t)))) 1088 (prin1-to-string replacement t))))
1042 1089
1090(defun replace-quote (replacement)
1091 "Quote a replacement string.
1092This just doubles all backslashes in REPLACEMENT and
1093returns the resulting string. If REPLACEMENT is not
1094a string, it is first passed through `prin1-to-string'
1095with the `noescape' argument set.
1096
1097`match-data' is preserved across the call."
1098 (save-match-data
1099 (replace-regexp-in-string "\\\\" "\\\\"
1100 (if (stringp replacement)
1101 replacement
1102 (prin1-to-string replacement t))
1103 t t)))
1104
1043(defun replace-loop-through-replacements (data replace-count) 1105(defun replace-loop-through-replacements (data replace-count)
1044 ;; DATA is a vector contaning the following values: 1106 ;; DATA is a vector contaning the following values:
1045 ;; 0 next-rotate-count 1107 ;; 0 next-rotate-count