diff options
| author | David Kastrup | 2004-06-17 14:44:02 +0000 |
|---|---|---|
| committer | David Kastrup | 2004-06-17 14:44:02 +0000 |
| commit | 2f57bf8593e0852e5bb8fc95f9341f5857efc504 (patch) | |
| tree | a21662fd1fb6070d3f9dbdecf726511d9e102d8e /lisp/replace.el | |
| parent | a6cb6b787e03344d28e93bef1cce5a7930854158 (diff) | |
| download | emacs-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.el | 104 |
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 | ||
| 162 | In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, | 163 | In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, |
| 163 | and `\\=\\N' (where N is a digit) stands for | 164 | and `\\=\\N' (where N is a digit) stands for |
| 164 | whatever what matched the Nth `\\(...\\)' in REGEXP." | 165 | whatever what matched the Nth `\\(...\\)' in REGEXP. |
| 166 | |||
| 167 | When this function is called interactively, the replacement text | ||
| 168 | can also contain `\\,' followed by a Lisp expression. The escaped | ||
| 169 | shorthands for `query-replace-regexp-eval' are also valid | ||
| 170 | here: within the Lisp expression, you can use `\\&' for the whole | ||
| 171 | match string, `\\N' for partial matches, `\\#&' and `\\#N' for | ||
| 172 | the respective numeric values, and `\\#' for `replace-count'. | ||
| 173 | |||
| 174 | If your Lisp expression is an identifier and the next | ||
| 175 | letter in the replacement string would be interpreted as part of it, | ||
| 176 | you can wrap it with an expression like `\\,(or \\#)'. Incidentally, | ||
| 177 | for this particular case you may also enter `\\#' in the replacement | ||
| 178 | text directly. | ||
| 179 | |||
| 180 | When you use `\\,' or `\\#' in the replacement, TO-STRING actually | ||
| 181 | becomes a list with expanded shorthands. | ||
| 182 | Use \\[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 |
| 192 | N is a digit) to stand for whatever matched the Nth `\\(...\\)' in REGEXP. | 235 | N is a digit) to stand for whatever matched the Nth `\\(...\\)' in REGEXP. |
| 193 | Use `\\#&' or `\\#N' if you want a number instead of a string. | 236 | Use `\\#&' or `\\#N' if you want a number instead of a string. |
| 237 | In interactive use, `\\#' in itself stands for `replace-count'. | ||
| 194 | 238 | ||
| 195 | In Transient Mark mode, if the mark is active, operate on the contents | 239 | In Transient Mark mode, if the mark is active, operate on the contents |
| 196 | of the region. Otherwise, operate from point to the end of the buffer. | 240 | of 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 | ||
| 1016 | Note that these symbols must be preceeded by a backslash in order to | 1061 | Note that these symbols must be preceeded by a backslash in order to |
| 1017 | type them." | 1062 | type 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. | ||
| 1092 | This just doubles all backslashes in REPLACEMENT and | ||
| 1093 | returns the resulting string. If REPLACEMENT is not | ||
| 1094 | a string, it is first passed through `prin1-to-string' | ||
| 1095 | with 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 |