diff options
| author | Richard M. Stallman | 2001-11-11 20:05:39 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 2001-11-11 20:05:39 +0000 |
| commit | 1c4fe319c900665cf0cee0817f627175fc723490 (patch) | |
| tree | 21117326c616952c284b75fb4a9fdb67c1e5ca12 | |
| parent | 0542e206fe2aa03b5491271286ba430773af2b11 (diff) | |
| download | emacs-1c4fe319c900665cf0cee0817f627175fc723490.tar.gz emacs-1c4fe319c900665cf0cee0817f627175fc723490.zip | |
(query-replace-skip-read-only): New variable.
(perform-replace): If that variable is non-nil, ignore matches
that have a read-only property.
| -rw-r--r-- | lisp/replace.el | 311 |
1 files changed, 161 insertions, 150 deletions
diff --git a/lisp/replace.el b/lisp/replace.el index aabe37f011d..1082caadc7b 100644 --- a/lisp/replace.el +++ b/lisp/replace.el | |||
| @@ -56,6 +56,12 @@ strings or patterns." | |||
| 56 | :type 'symbol | 56 | :type 'symbol |
| 57 | :version "20.3") | 57 | :version "20.3") |
| 58 | 58 | ||
| 59 | (defcustom query-replace-skip-read-only nil | ||
| 60 | "*Non-nil means `query-replace' and friends ignore read-only matches." | ||
| 61 | :type 'boolean | ||
| 62 | :group 'matching | ||
| 63 | :version "21.3") | ||
| 64 | |||
| 59 | (defun query-replace-read-args (string regexp-flag) | 65 | (defun query-replace-read-args (string regexp-flag) |
| 60 | (let (from to) | 66 | (let (from to) |
| 61 | (if query-replace-interactive | 67 | (if query-replace-interactive |
| @@ -967,158 +973,163 @@ see the documentation of `replace-match' to find out how to simulate | |||
| 967 | ;; For speed, use only integers and | 973 | ;; For speed, use only integers and |
| 968 | ;; reuse the list used last time. | 974 | ;; reuse the list used last time. |
| 969 | (match-data t real-match-data))))) | 975 | (match-data t real-match-data))))) |
| 970 | 976 | ;; Optionally ignore matches that have a read-only property. | |
| 971 | ;; Record whether the match is nonempty, to avoid an infinite loop | 977 | (unless (and query-replace-skip-read-only |
| 972 | ;; repeatedly matching the same empty string. | 978 | (text-property-not-all |
| 973 | (setq nonempty-match | 979 | (match-beginning 0) (match-end 0) |
| 974 | (/= (nth 0 real-match-data) (nth 1 real-match-data))) | 980 | 'read-only nil)) |
| 975 | 981 | ||
| 976 | ;; If the match is empty, record that the next one can't be | 982 | ;; Record whether the match is nonempty, to avoid an infinite loop |
| 977 | ;; adjacent. | 983 | ;; repeatedly matching the same empty string. |
| 978 | 984 | (setq nonempty-match | |
| 979 | ;; Otherwise, if matching a regular expression, do the next | 985 | (/= (nth 0 real-match-data) (nth 1 real-match-data))) |
| 980 | ;; match now, since the replacement for this match may | 986 | |
| 981 | ;; affect whether the next match is adjacent to this one. | 987 | ;; If the match is empty, record that the next one can't be |
| 982 | ;; If that match is empty, don't use it. | 988 | ;; adjacent. |
| 983 | (setq match-again | 989 | |
| 984 | (and nonempty-match | 990 | ;; Otherwise, if matching a regular expression, do the next |
| 985 | (or (not regexp-flag) | 991 | ;; match now, since the replacement for this match may |
| 986 | (and (looking-at search-string) | 992 | ;; affect whether the next match is adjacent to this one. |
| 987 | (let ((match (match-data))) | 993 | ;; If that match is empty, don't use it. |
| 988 | (and (/= (nth 0 match) (nth 1 match)) | 994 | (setq match-again |
| 989 | match)))))) | 995 | (and nonempty-match |
| 990 | 996 | (or (not regexp-flag) | |
| 991 | ;; Calculate the replacement string, if necessary. | 997 | (and (looking-at search-string) |
| 992 | (when replacements | 998 | (let ((match (match-data))) |
| 993 | (set-match-data real-match-data) | 999 | (and (/= (nth 0 match) (nth 1 match)) |
| 994 | (setq next-replacement | 1000 | match)))))) |
| 995 | (funcall (car replacements) (cdr replacements) | 1001 | |
| 996 | replace-count))) | 1002 | ;; Calculate the replacement string, if necessary. |
| 997 | (if (not query-flag) | 1003 | (when replacements |
| 998 | (progn | 1004 | (set-match-data real-match-data) |
| 999 | (set-match-data real-match-data) | 1005 | (setq next-replacement |
| 1000 | (replace-match next-replacement nocasify literal) | 1006 | (funcall (car replacements) (cdr replacements) |
| 1001 | (setq replace-count (1+ replace-count))) | 1007 | replace-count))) |
| 1002 | (undo-boundary) | 1008 | (if (not query-flag) |
| 1003 | (let (done replaced key def) | 1009 | (let ((inhibit-read-only query-replace-skip-read-only)) |
| 1004 | ;; Loop reading commands until one of them sets done, | 1010 | (set-match-data real-match-data) |
| 1005 | ;; which means it has finished handling this occurrence. | 1011 | (replace-match next-replacement nocasify literal) |
| 1006 | (while (not done) | 1012 | (setq replace-count (1+ replace-count))) |
| 1007 | (set-match-data real-match-data) | 1013 | (undo-boundary) |
| 1008 | (replace-highlight (match-beginning 0) (match-end 0)) | 1014 | (let (done replaced key def) |
| 1009 | ;; Bind message-log-max so we don't fill up the message log | 1015 | ;; Loop reading commands until one of them sets done, |
| 1010 | ;; with a bunch of identical messages. | 1016 | ;; which means it has finished handling this occurrence. |
| 1011 | (let ((message-log-max nil)) | 1017 | (while (not done) |
| 1012 | (message message from-string next-replacement)) | 1018 | (set-match-data real-match-data) |
| 1013 | (setq key (read-event)) | 1019 | (replace-highlight (match-beginning 0) (match-end 0)) |
| 1014 | ;; Necessary in case something happens during read-event | 1020 | ;; Bind message-log-max so we don't fill up the message log |
| 1015 | ;; that clobbers the match data. | 1021 | ;; with a bunch of identical messages. |
| 1016 | (set-match-data real-match-data) | 1022 | (let ((message-log-max nil)) |
| 1017 | (setq key (vector key)) | 1023 | (message message from-string next-replacement)) |
| 1018 | (setq def (lookup-key map key)) | 1024 | (setq key (read-event)) |
| 1019 | ;; Restore the match data while we process the command. | 1025 | ;; Necessary in case something happens during read-event |
| 1020 | (cond ((eq def 'help) | 1026 | ;; that clobbers the match data. |
| 1021 | (with-output-to-temp-buffer "*Help*" | 1027 | (set-match-data real-match-data) |
| 1022 | (princ | 1028 | (setq key (vector key)) |
| 1023 | (concat "Query replacing " | 1029 | (setq def (lookup-key map key)) |
| 1024 | (if regexp-flag "regexp " "") | 1030 | ;; Restore the match data while we process the command. |
| 1025 | from-string " with " | 1031 | (cond ((eq def 'help) |
| 1026 | next-replacement ".\n\n" | 1032 | (with-output-to-temp-buffer "*Help*" |
| 1027 | (substitute-command-keys | 1033 | (princ |
| 1028 | query-replace-help))) | 1034 | (concat "Query replacing " |
| 1029 | (with-current-buffer standard-output | 1035 | (if regexp-flag "regexp " "") |
| 1030 | (help-mode)))) | 1036 | from-string " with " |
| 1031 | ((eq def 'exit) | 1037 | next-replacement ".\n\n" |
| 1032 | (setq keep-going nil) | 1038 | (substitute-command-keys |
| 1033 | (setq done t)) | 1039 | query-replace-help))) |
| 1034 | ((eq def 'backup) | 1040 | (with-current-buffer standard-output |
| 1035 | (if stack | 1041 | (help-mode)))) |
| 1036 | (let ((elt (car stack))) | 1042 | ((eq def 'exit) |
| 1037 | (goto-char (car elt)) | 1043 | (setq keep-going nil) |
| 1038 | (setq replaced (eq t (cdr elt))) | 1044 | (setq done t)) |
| 1039 | (or replaced | 1045 | ((eq def 'backup) |
| 1040 | (set-match-data (cdr elt))) | 1046 | (if stack |
| 1041 | (setq stack (cdr stack))) | 1047 | (let ((elt (car stack))) |
| 1042 | (message "No previous match") | 1048 | (goto-char (car elt)) |
| 1043 | (ding 'no-terminate) | 1049 | (setq replaced (eq t (cdr elt))) |
| 1044 | (sit-for 1))) | 1050 | (or replaced |
| 1045 | ((eq def 'act) | 1051 | (set-match-data (cdr elt))) |
| 1046 | (or replaced | 1052 | (setq stack (cdr stack))) |
| 1047 | (progn | 1053 | (message "No previous match") |
| 1048 | (replace-match next-replacement nocasify literal) | 1054 | (ding 'no-terminate) |
| 1049 | (setq replace-count (1+ replace-count)))) | 1055 | (sit-for 1))) |
| 1050 | (setq done t replaced t)) | 1056 | ((eq def 'act) |
| 1051 | ((eq def 'act-and-exit) | 1057 | (or replaced |
| 1052 | (or replaced | 1058 | (progn |
| 1053 | (progn | 1059 | (replace-match next-replacement nocasify literal) |
| 1054 | (replace-match next-replacement nocasify literal) | 1060 | (setq replace-count (1+ replace-count)))) |
| 1055 | (setq replace-count (1+ replace-count)))) | 1061 | (setq done t replaced t)) |
| 1056 | (setq keep-going nil) | 1062 | ((eq def 'act-and-exit) |
| 1057 | (setq done t replaced t)) | 1063 | (or replaced |
| 1058 | ((eq def 'act-and-show) | 1064 | (progn |
| 1059 | (if (not replaced) | 1065 | (replace-match next-replacement nocasify literal) |
| 1060 | (progn | 1066 | (setq replace-count (1+ replace-count)))) |
| 1061 | (replace-match next-replacement nocasify literal) | 1067 | (setq keep-going nil) |
| 1062 | (setq replace-count (1+ replace-count)) | 1068 | (setq done t replaced t)) |
| 1063 | (setq replaced t)))) | 1069 | ((eq def 'act-and-show) |
| 1064 | ((eq def 'automatic) | 1070 | (if (not replaced) |
| 1065 | (or replaced | 1071 | (progn |
| 1066 | (progn | 1072 | (replace-match next-replacement nocasify literal) |
| 1067 | (replace-match next-replacement nocasify literal) | 1073 | (setq replace-count (1+ replace-count)) |
| 1068 | (setq replace-count (1+ replace-count)))) | 1074 | (setq replaced t)))) |
| 1069 | (setq done t query-flag nil replaced t)) | 1075 | ((eq def 'automatic) |
| 1070 | ((eq def 'skip) | 1076 | (or replaced |
| 1071 | (setq done t)) | 1077 | (progn |
| 1072 | ((eq def 'recenter) | 1078 | (replace-match next-replacement nocasify literal) |
| 1073 | (recenter nil)) | 1079 | (setq replace-count (1+ replace-count)))) |
| 1074 | ((eq def 'edit) | 1080 | (setq done t query-flag nil replaced t)) |
| 1075 | (let ((opos (point-marker))) | 1081 | ((eq def 'skip) |
| 1076 | (goto-char (match-beginning 0)) | 1082 | (setq done t)) |
| 1077 | (save-excursion | 1083 | ((eq def 'recenter) |
| 1078 | (funcall search-function search-string limit t) | 1084 | (recenter nil)) |
| 1079 | (setq real-match-data (match-data))) | 1085 | ((eq def 'edit) |
| 1080 | (save-excursion (recursive-edit)) | 1086 | (let ((opos (point-marker))) |
| 1081 | (goto-char opos)) | 1087 | (goto-char (match-beginning 0)) |
| 1082 | (set-match-data real-match-data) | 1088 | (save-excursion |
| 1083 | ;; Before we make the replacement, | 1089 | (funcall search-function search-string limit t) |
| 1084 | ;; decide whether the search string | 1090 | (setq real-match-data (match-data))) |
| 1085 | ;; can match again just after this match. | 1091 | (save-excursion (recursive-edit)) |
| 1086 | (if (and regexp-flag nonempty-match) | 1092 | (goto-char opos)) |
| 1087 | (setq match-again (and (looking-at search-string) | 1093 | (set-match-data real-match-data) |
| 1088 | (match-data))))) | 1094 | ;; Before we make the replacement, |
| 1095 | ;; decide whether the search string | ||
| 1096 | ;; can match again just after this match. | ||
| 1097 | (if (and regexp-flag nonempty-match) | ||
| 1098 | (setq match-again (and (looking-at search-string) | ||
| 1099 | (match-data))))) | ||
| 1089 | 1100 | ||
| 1090 | ;; Edit replacement. | 1101 | ;; Edit replacement. |
| 1091 | ((eq def 'edit-replacement) | 1102 | ((eq def 'edit-replacement) |
| 1092 | (setq next-replacement | 1103 | (setq next-replacement |
| 1093 | (read-input "Edit replacement string: " | 1104 | (read-input "Edit replacement string: " |
| 1094 | next-replacement)) | 1105 | next-replacement)) |
| 1095 | (or replaced | 1106 | (or replaced |
| 1096 | (replace-match next-replacement nocasify literal)) | 1107 | (replace-match next-replacement nocasify literal)) |
| 1097 | (setq done t)) | 1108 | (setq done t)) |
| 1098 | 1109 | ||
| 1099 | ((eq def 'delete-and-edit) | 1110 | ((eq def 'delete-and-edit) |
| 1100 | (delete-region (match-beginning 0) (match-end 0)) | 1111 | (delete-region (match-beginning 0) (match-end 0)) |
| 1101 | (set-match-data | 1112 | (set-match-data |
| 1102 | (prog1 (match-data) | 1113 | (prog1 (match-data) |
| 1103 | (save-excursion (recursive-edit)))) | 1114 | (save-excursion (recursive-edit)))) |
| 1104 | (setq replaced t)) | 1115 | (setq replaced t)) |
| 1105 | ;; Note: we do not need to treat `exit-prefix' | 1116 | ;; Note: we do not need to treat `exit-prefix' |
| 1106 | ;; specially here, since we reread | 1117 | ;; specially here, since we reread |
| 1107 | ;; any unrecognized character. | 1118 | ;; any unrecognized character. |
| 1108 | (t | 1119 | (t |
| 1109 | (setq this-command 'mode-exited) | 1120 | (setq this-command 'mode-exited) |
| 1110 | (setq keep-going nil) | 1121 | (setq keep-going nil) |
| 1111 | (setq unread-command-events | 1122 | (setq unread-command-events |
| 1112 | (append (listify-key-sequence key) | 1123 | (append (listify-key-sequence key) |
| 1113 | unread-command-events)) | 1124 | unread-command-events)) |
| 1114 | (setq done t)))) | 1125 | (setq done t)))) |
| 1115 | ;; Record previous position for ^ when we move on. | 1126 | ;; Record previous position for ^ when we move on. |
| 1116 | ;; Change markers to numbers in the match data | 1127 | ;; Change markers to numbers in the match data |
| 1117 | ;; since lots of markers slow down editing. | 1128 | ;; since lots of markers slow down editing. |
| 1118 | (setq stack | 1129 | (setq stack |
| 1119 | (cons (cons (point) | 1130 | (cons (cons (point) |
| 1120 | (or replaced (match-data t))) | 1131 | (or replaced (match-data t))) |
| 1121 | stack))))) | 1132 | stack)))))) |
| 1122 | 1133 | ||
| 1123 | ;; The code preventing adjacent regexp matches in the condition | 1134 | ;; The code preventing adjacent regexp matches in the condition |
| 1124 | ;; of the while-loop above will haven taken us one character | 1135 | ;; of the while-loop above will haven taken us one character |