Mercurial > hg > xemacs-beta
annotate lisp/replace.el @ 5379:a32a108ae815
#'cl-non-fixnum-number-p: return t for integers > #x3fffffff and < -#x40000000
2011-03-21 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el (cl-non-fixnum-number-p):
This should return t under 64-bit builds for fixnums that would
be bignums on a 32-bit machine; make it so.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Mon, 21 Mar 2011 12:19:25 +0000 |
parents | f00192e1cd49 |
children | ac37a5f7e5be |
rev | line source |
---|---|
428 | 1 ;;; replace.el --- search and replace commands for XEmacs. |
2 | |
1476 | 3 ;; Copyright (C) 1985-7, 1992, 1994, 1997, 2003 Free Software Foundation, Inc. |
428 | 4 |
5 ;; Maintainer: XEmacs Development Team | |
6 ;; Keywords: dumped, matching | |
7 | |
8 ;; This file is part of XEmacs. | |
9 | |
10 ;; XEmacs is free software; you can redistribute it and/or modify it | |
11 ;; under the terms of the GNU General Public License as published by | |
12 ;; the Free Software Foundation; either version 2, or (at your option) | |
13 ;; any later version. | |
14 | |
15 ;; XEmacs is distributed in the hope that it will be useful, but | |
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 ;; General Public License for more details. | |
19 | |
20 ;; You should have received a copy of the GNU General Public License | |
21 ;; along with XEmacs; see the file COPYING. If not, write to the Free | |
3000 | 22 ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
23 ;; Boston, MA 02110-1301, USA. | |
428 | 24 |
25 ;;; Synched up with: FSF 19.34 [Partially]. | |
26 | |
27 ;;; Commentary: | |
28 | |
29 ;; This file is dumped with XEmacs. | |
30 | |
31 ;; This package supplies the string and regular-expression replace functions | |
32 ;; documented in the XEmacs Reference Manual. | |
33 | |
34 ;; All the gettext calls are for XEmacs I18N3 message catalog support. | |
35 ;; (This is hopelessly broken and we should remove it. -sb) | |
36 | |
37 ;;; Code: | |
38 | |
39 (defvar case-replace t "\ | |
40 *Non-nil means `query-replace' should preserve case in replacements. | |
41 What this means is that `query-replace' will change the case of the | |
42 replacement text so that it matches the text that was replaced. | |
43 If this variable is nil, the replacement text will be inserted | |
44 exactly as it was specified by the user, irrespective of the case | |
45 of the text that was replaced. | |
46 | |
47 Note that this flag has no effect if `case-fold-search' is nil, | |
48 or if the replacement text has any uppercase letters in it.") | |
49 | |
50 (defvar query-replace-history nil) | |
51 | |
52 (defvar query-replace-interactive nil | |
53 "Non-nil means `query-replace' uses the last search string. | |
54 That becomes the \"string to replace\".") | |
55 | |
56 (defvar replace-search-function | |
57 (lambda (str limit) | |
58 (search-forward str limit t)) | |
444 | 59 "Function used by perform-replace to search forward for a string. It will be |
428 | 60 called with two arguments: the string to search for and a limit bounding the |
61 search.") | |
62 | |
63 (defvar replace-re-search-function | |
64 (lambda (regexp limit) | |
65 (re-search-forward regexp limit t)) | |
66 "Function used by perform-replace to search forward for a regular | |
67 expression. It will be called with two arguments: the regexp to search for and | |
68 a limit bounding the search.") | |
69 | |
70 (defun query-replace-read-args (string regexp-flag) | |
71 (let (from to) | |
72 (if query-replace-interactive | |
73 (setq from (car (if regexp-flag regexp-search-ring search-ring))) | |
74 (setq from (read-from-minibuffer (format "%s: " (gettext string)) | |
75 nil nil nil | |
76 'query-replace-history))) | |
77 (setq to (read-from-minibuffer (format "%s %s with: " (gettext string) | |
78 from) | |
79 nil nil nil | |
80 'query-replace-history)) | |
81 (list from to current-prefix-arg))) | |
82 | |
83 ;; As per suggestion from Per Abrahamsen, limit replacement to the region | |
84 ;; if the region is active. | |
85 (defun query-replace (from-string to-string &optional delimited) | |
86 "Replace some occurrences of FROM-STRING with TO-STRING. | |
87 As each match is found, the user must type a character saying | |
88 what to do with it. For directions, type \\[help-command] at that time. | |
89 | |
90 If `query-replace-interactive' is non-nil, the last incremental search | |
91 string is used as FROM-STRING--you don't have to specify it with the | |
92 minibuffer. | |
93 | |
94 Preserves case in each replacement if `case-replace' and `case-fold-search' | |
95 are non-nil and FROM-STRING has no uppercase letters. | |
96 \(Preserving case means that if the string matched is all caps, or capitalized, | |
97 then its replacement is upcased or capitalized.) | |
98 | |
99 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
100 only matches surrounded by word boundaries. | |
101 | |
102 To customize possible responses, change the \"bindings\" in `query-replace-map'." | |
103 (interactive (query-replace-read-args "Query replace" nil)) | |
104 (perform-replace from-string to-string t nil delimited)) | |
105 | |
106 (defun query-replace-regexp (regexp to-string &optional delimited) | |
107 "Replace some things after point matching REGEXP with TO-STRING. | |
108 As each match is found, the user must type a character saying | |
109 what to do with it. For directions, type \\[help-command] at that time. | |
110 | |
111 If `query-replace-interactive' is non-nil, the last incremental search | |
112 regexp is used as REGEXP--you don't have to specify it with the | |
113 minibuffer. | |
114 | |
115 Preserves case in each replacement if `case-replace' and `case-fold-search' | |
116 are non-nil and REGEXP has no uppercase letters. | |
117 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
118 only matches surrounded by word boundaries. | |
119 In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, | |
120 and `\\=\\N' (where N is a digit) stands for | |
121 whatever what matched the Nth `\\(...\\)' in REGEXP." | |
122 (interactive (query-replace-read-args "Query replace regexp" t)) | |
123 (perform-replace regexp to-string t t delimited)) | |
124 | |
125 ;;#### Not patently useful | |
126 (defun map-query-replace-regexp (regexp to-strings &optional arg) | |
127 "Replace some matches for REGEXP with various strings, in rotation. | |
128 The second argument TO-STRINGS contains the replacement strings, separated | |
129 by spaces. This command works like `query-replace-regexp' except | |
130 that each successive replacement uses the next successive replacement string, | |
131 wrapping around from the last such string to the first. | |
132 | |
133 Non-interactively, TO-STRINGS may be a list of replacement strings. | |
134 | |
135 If `query-replace-interactive' is non-nil, the last incremental search | |
136 regexp is used as REGEXP--you don't have to specify it with the minibuffer. | |
137 | |
138 A prefix argument N says to use each replacement string N times | |
139 before rotating to the next." | |
140 (interactive | |
141 (let (from to) | |
142 (setq from (if query-replace-interactive | |
143 (car regexp-search-ring) | |
144 (read-from-minibuffer "Map query replace (regexp): " | |
145 nil nil nil | |
146 'query-replace-history))) | |
147 (setq to (read-from-minibuffer | |
148 (format "Query replace %s with (space-separated strings): " | |
149 from) | |
150 nil nil nil | |
151 'query-replace-history)) | |
152 (list from to current-prefix-arg))) | |
153 (let (replacements) | |
154 (if (listp to-strings) | |
155 (setq replacements to-strings) | |
5366
f00192e1cd49
Examining the result of #'length: `eql', not `=', it's better style & cheaper
Aidan Kehoe <kehoea@parhasard.net>
parents:
3000
diff
changeset
|
156 (while (not (eql (length to-strings) 0)) |
428 | 157 (if (string-match " " to-strings) |
158 (setq replacements | |
159 (append replacements | |
160 (list (substring to-strings 0 | |
161 (string-match " " to-strings)))) | |
162 to-strings (substring to-strings | |
163 (1+ (string-match " " to-strings)))) | |
164 (setq replacements (append replacements (list to-strings)) | |
165 to-strings "")))) | |
166 (perform-replace regexp replacements t t nil arg))) | |
167 | |
168 (defun replace-string (from-string to-string &optional delimited) | |
169 "Replace occurrences of FROM-STRING with TO-STRING. | |
170 Preserve case in each match if `case-replace' and `case-fold-search' | |
171 are non-nil and FROM-STRING has no uppercase letters. | |
172 \(Preserving case means that if the string matched is all caps, or capitalized, | |
173 then its replacement is upcased or capitalized.) | |
174 | |
175 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
176 only matches surrounded by word boundaries. | |
177 | |
178 If `query-replace-interactive' is non-nil, the last incremental search | |
179 string is used as FROM-STRING--you don't have to specify it with the | |
180 minibuffer. | |
181 | |
182 This function is usually the wrong thing to use in a Lisp program. | |
183 What you probably want is a loop like this: | |
184 (while (search-forward FROM-STRING nil t) | |
185 (replace-match TO-STRING nil t)) | |
186 which will run faster and will not set the mark or print anything." | |
187 (interactive (query-replace-read-args "Replace string" nil)) | |
188 (perform-replace from-string to-string nil nil delimited)) | |
189 | |
190 (defun replace-regexp (regexp to-string &optional delimited) | |
191 "Replace things after point matching REGEXP with TO-STRING. | |
192 Preserve case in each match if `case-replace' and `case-fold-search' | |
193 are non-nil and REGEXP has no uppercase letters. | |
194 \(Preserving case means that if the string matched is all caps, or capitalized, | |
195 then its replacement is upcased or capitalized.) | |
196 | |
197 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | |
198 only matches surrounded by word boundaries. | |
199 In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP, | |
200 and `\\=\\N' (where N is a digit) stands for | |
201 whatever what matched the Nth `\\(...\\)' in REGEXP. | |
202 | |
203 If `query-replace-interactive' is non-nil, the last incremental search | |
204 regexp is used as REGEXP--you don't have to specify it with the minibuffer. | |
205 | |
206 This function is usually the wrong thing to use in a Lisp program. | |
207 What you probably want is a loop like this: | |
208 (while (re-search-forward REGEXP nil t) | |
209 (replace-match TO-STRING nil nil)) | |
210 which will run faster and will not set the mark or print anything." | |
211 (interactive (query-replace-read-args "Replace regexp" t)) | |
212 (perform-replace regexp to-string nil t delimited)) | |
213 | |
214 | |
1069 | 215 |
216 ;; gse wonders: Is there a better place for this to go? Might other packages | |
217 ;; want to use it? | |
428 | 218 (defvar regexp-history nil |
219 "History list for some commands that read regular expressions.") | |
220 | |
1069 | 221 (defun operate-on-non-matching-lines (regexp delete kill &optional beg end) |
222 "Internal function used by delete-non-matching-lines, | |
223 kill-non-matching-lines, and copy-matching-lines. | |
224 | |
225 REGEXP is a regular expression to *not* match when performing | |
226 operations. | |
227 | |
228 If DELETE is non-nil, the lines of text are deleted. It doesn't make | |
229 sense to set this to nil if KILL is nil -- nothing will happen. | |
230 | |
231 If KILL is non-nil, the lines of text are stored in the kill ring (as | |
232 one block of text). | |
233 | |
234 BEG and END, if non-nil, specify the start and end locations to work | |
235 within. If these are nil, point and point-max are used. | |
236 | |
237 A match split across lines preserves all the lines it lies in. | |
238 Applies to all lines after point. | |
239 | |
240 Returns the number of lines matched." | |
241 (with-search-caps-disable-folding regexp t | |
242 (save-excursion | |
243 ;; Move to a beginning point if specified. | |
244 (when beg (goto-char beg)) | |
245 ;; Always start on the beginning of a line. | |
246 (or (bolp) (forward-line 1)) | |
247 | |
248 (let ((matched-text nil) | |
249 (curmatch-start (point)) | |
2610 | 250 (limit (copy-marker (point-max))) |
251 (matched-text-buffer (generate-new-buffer " *matched-text*")) | |
252 lines-matched) | |
1069 | 253 ;; Limit search if limits were specified. |
254 (when end (setq limit (copy-marker end))) | |
255 | |
256 ;; Search. Stop if we are at end of buffer or outside the | |
257 ;; limit. | |
258 (while (not (or | |
259 (eobp) | |
260 (and limit (>= (point) limit)))) | |
261 ;; curmatch-start is first char not preserved by previous match. | |
262 (if (not (re-search-forward regexp limit 'move)) | |
263 (let ((curmatch-end limit)) | |
2610 | 264 (append-to-buffer matched-text-buffer curmatch-start curmatch-end) |
1069 | 265 (if delete (delete-region curmatch-start curmatch-end))) |
266 (let ((curmatch-end (save-excursion (goto-char (match-beginning 0)) | |
2610 | 267 (beginning-of-line) |
268 (point)))) | |
1069 | 269 ;; Now curmatch-end is first char preserved by the new match. |
270 (if (< curmatch-start curmatch-end) | |
271 (progn | |
2610 | 272 (append-to-buffer matched-text-buffer curmatch-start curmatch-end) |
1069 | 273 (if delete (delete-region curmatch-start curmatch-end)))))) |
274 (setq curmatch-start (save-excursion (forward-line 1) | |
2610 | 275 (point))) |
1069 | 276 ;; If the match was empty, avoid matching again at same place. |
277 (and (not (eobp)) (= (match-beginning 0) (match-end 0)) | |
278 (forward-char 1))) | |
279 | |
280 ;; If any lines were matched and KILL is non-nil, insert the | |
281 ;; matched lines into the kill ring. | |
2610 | 282 (setq matched-text (buffer-string matched-text-buffer)) |
1069 | 283 (if (and matched-text kill) (kill-new matched-text)) |
284 | |
285 ;; Return the number of matched lines. | |
2610 | 286 (setq lines-matched |
287 (with-current-buffer matched-text-buffer | |
288 (count-lines (point-min) (point-max)))) | |
289 (kill-buffer matched-text-buffer) | |
290 lines-matched)))) | |
1069 | 291 |
428 | 292 (define-function 'keep-lines 'delete-non-matching-lines) |
293 (defun delete-non-matching-lines (regexp) | |
1069 | 294 "Delete lines that do not match REGEXP, from point to the end of the |
295 buffer (or within the region, if it is active)." | |
428 | 296 (interactive (list (read-from-minibuffer |
297 "Keep lines (containing match for regexp): " | |
298 nil nil nil 'regexp-history))) | |
1069 | 299 (let ((beg nil) |
300 (end nil) | |
301 (count nil)) | |
302 (when (region-active-p) | |
303 (setq beg (region-beginning)) | |
304 (setq end (region-end))) | |
305 (setq count (operate-on-non-matching-lines regexp t nil beg end)) | |
1476 | 306 (when (interactive-p) |
307 (message "%i lines deleted" count)))) | |
1069 | 308 |
309 (defun kill-non-matching-lines (regexp) | |
310 "Delete the lines that do not match REGEXP, from point to the end of | |
311 the buffer (or within the region, if it is active). The deleted lines | |
312 are placed in the kill ring as one block of text." | |
313 (interactive (list (read-from-minibuffer | |
314 "Kill non-matching lines (regexp): " | |
315 nil nil nil 'regexp-history))) | |
316 (let ((beg nil) | |
317 (end nil) | |
318 (count nil)) | |
319 (when (region-active-p) | |
320 (setq beg (region-beginning)) | |
321 (setq end (region-end))) | |
322 (setq count (operate-on-non-matching-lines regexp t t beg end)) | |
1476 | 323 (when (interactive-p) |
324 (message "%i lines killed" count)))) | |
1069 | 325 |
326 (defun copy-non-matching-lines (regexp) | |
327 "Find all lines that do not match REGEXP from point to the end of the | |
328 buffer (or within the region, if it is active), and place them in the | |
329 kill ring as one block of text." | |
330 (interactive (list (read-from-minibuffer | |
331 "Copy non-matching lines (regexp): " | |
332 nil nil nil 'regexp-history))) | |
333 (let ((beg nil) | |
334 (end nil) | |
335 (count nil)) | |
336 (when (region-active-p) | |
337 (setq beg (region-beginning)) | |
338 (setq end (region-end))) | |
339 (setq count (operate-on-non-matching-lines regexp nil t beg end)) | |
1476 | 340 (when (interactive-p) |
341 (message "%i lines copied" count)))) | |
1069 | 342 |
343 (defun operate-on-matching-lines (regexp delete kill &optional beg end) | |
344 "Internal function used by delete-matching-lines, kill-matching-lines, | |
345 and copy-matching-lines. | |
346 | |
347 If DELETE is non-nil, the lines of text are deleted. It doesn't make | |
348 sense to set this to nil if KILL is nil -- nothing will happen. | |
349 | |
350 If KILL is non-nil, the lines of text are stored in the kill ring (as | |
351 one block of text). | |
352 | |
353 BEG and END, if non-nil, specify the start and end locations to work | |
354 within. If these are nil, point and point-max are used. | |
355 | |
356 If a match is split across lines, all the lines it lies in are deleted. | |
357 Applies to lines after point. | |
358 Returns the number of lines matched." | |
359 (with-search-caps-disable-folding regexp t | |
428 | 360 (save-excursion |
1069 | 361 (let ((matched-text nil) |
362 (curmatch-start nil) | |
363 (curmatch-end nil) | |
2610 | 364 (limit nil) |
365 (matched-text-buffer (generate-new-buffer " *matched-text*")) | |
366 lines-matched) | |
1069 | 367 ;; Limit search if limits were specified. |
368 (when beg (goto-char beg)) | |
369 (when end (setq limit (copy-marker end))) | |
370 | |
371 (while (and (not (eobp)) | |
372 (re-search-forward regexp limit t)) | |
373 (setq curmatch-start (save-excursion (goto-char (match-beginning 0)) | |
374 (beginning-of-line) | |
375 (point))) | |
376 (setq curmatch-end (progn (forward-line 1) (point))) | |
2610 | 377 (append-to-buffer matched-text-buffer curmatch-start curmatch-end) |
1069 | 378 (if delete (delete-region curmatch-start curmatch-end))) |
2610 | 379 (setq matched-text (buffer-string matched-text-buffer)) |
1069 | 380 (if (and matched-text kill) (kill-new matched-text)) |
381 | |
382 ;; Return the number of matched lines. | |
2610 | 383 (setq lines-matched |
384 (with-current-buffer matched-text-buffer | |
385 (count-lines (point-min) (point-max)))) | |
386 (kill-buffer matched-text-buffer) | |
387 lines-matched)))) | |
428 | 388 |
389 (define-function 'flush-lines 'delete-matching-lines) | |
390 (defun delete-matching-lines (regexp) | |
1069 | 391 "Delete the lines that match REGEXP, from point to the end of the |
392 buffer (or within the region, if it is active)." | |
428 | 393 (interactive (list (read-from-minibuffer |
394 "Flush lines (containing match for regexp): " | |
395 nil nil nil 'regexp-history))) | |
1069 | 396 (let ((beg nil) |
397 (end nil) | |
398 (count nil)) | |
399 (when (region-active-p) | |
400 (setq beg (region-beginning)) | |
401 (setq end (region-end))) | |
402 (setq count (operate-on-matching-lines regexp t nil beg end)) | |
1476 | 403 (when (interactive-p) |
404 (message "%i lines deleted" count)))) | |
1069 | 405 |
406 (defun kill-matching-lines (regexp) | |
407 "Delete the lines that match REGEXP, from point to the end of the | |
408 buffer (or within the region, if it is active). The deleted lines are | |
409 placed in the kill ring as one block of text." | |
410 (interactive (list (read-from-minibuffer | |
411 "Kill lines (containing match for regexp): " | |
412 nil nil nil 'regexp-history))) | |
413 (let ((beg nil) | |
414 (end nil) | |
415 (count nil)) | |
416 (when (region-active-p) | |
417 (setq beg (region-beginning)) | |
418 (setq end (region-end))) | |
419 (setq count (operate-on-matching-lines regexp t t beg end)) | |
1476 | 420 (when (interactive-p) |
421 (message "%i lines killed" count)))) | |
1069 | 422 |
423 (defun copy-matching-lines (regexp) | |
424 "Find all lines that match REGEXP from point to the end of the | |
425 buffer (or within the region, if it is active), and place them in the | |
426 kill ring as one block of text." | |
427 (interactive (list (read-from-minibuffer | |
428 "Copy lines (containing match for regexp): " | |
429 nil nil nil 'regexp-history))) | |
430 (let ((beg nil) | |
431 (end nil) | |
432 (count nil)) | |
433 (when (region-active-p) | |
434 (setq beg (region-beginning)) | |
435 (setq end (region-end))) | |
436 (setq count (operate-on-matching-lines regexp nil t beg end)) | |
1476 | 437 (when (interactive-p) |
438 (message "%i lines copied" count)))) | |
428 | 439 |
440 (define-function 'how-many 'count-matches) | |
441 (defun count-matches (regexp) | |
442 "Print number of matches for REGEXP following point." | |
443 (interactive (list (read-from-minibuffer | |
444 "How many matches for (regexp): " | |
445 nil nil nil 'regexp-history))) | |
446 (with-interactive-search-caps-disable-folding regexp t | |
447 (let ((count 0) opoint) | |
448 (save-excursion | |
449 (while (and (not (eobp)) | |
450 (progn (setq opoint (point)) | |
451 (re-search-forward regexp nil t))) | |
452 (if (= opoint (point)) | |
453 (forward-char 1) | |
454 (setq count (1+ count)))) | |
455 (message "%d occurrences" count))))) | |
456 | |
457 | |
3000 | 458 ;;; occur code moved to occur.el |
428 | 459 |
460 ;; It would be nice to use \\[...], but there is no reasonable way | |
461 ;; to make that display both SPC and Y. | |
462 (defconst query-replace-help | |
444 | 463 "Type Space or `y' to replace one match, Delete or `n' to skip to next, |
428 | 464 RET or `q' to exit, Period to replace one match and exit, |
465 Comma to replace but not move point immediately, | |
466 C-r to enter recursive edit (\\[exit-recursive-edit] to get out again), | |
467 C-w to delete match and recursive edit, | |
468 C-l to clear the frame, redisplay, and offer same replacement again, | |
469 ! to replace all remaining matches with no more questions, | |
470 ^ to move point back to previous match." | |
444 | 471 |
428 | 472 "Help message while in query-replace") |
473 | |
474 (defvar query-replace-map nil | |
475 "Keymap that defines the responses to questions in `query-replace'. | |
476 The \"bindings\" in this map are not commands; they are answers. | |
477 The valid answers include `act', `skip', `act-and-show', | |
478 `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', | |
479 `automatic', `backup', `exit-prefix', and `help'.") | |
480 | |
481 ;; Why does it seem that ever file has a different method of doing this? | |
482 (if query-replace-map | |
483 nil | |
484 (let ((map (make-sparse-keymap))) | |
485 (set-keymap-name map 'query-replace-map) | |
486 (define-key map " " 'act) | |
487 (define-key map "\d" 'skip) | |
488 (define-key map [delete] 'skip) | |
489 (define-key map [backspace] 'skip) | |
490 (define-key map "y" 'act) | |
491 (define-key map "n" 'skip) | |
492 (define-key map "Y" 'act) | |
493 (define-key map "N" 'skip) | |
494 (define-key map "," 'act-and-show) | |
495 (define-key map [escape] 'exit) | |
496 (define-key map "q" 'exit) | |
497 (define-key map [return] 'exit) | |
498 (define-key map "." 'act-and-exit) | |
499 (define-key map "\C-r" 'edit) | |
500 (define-key map "\C-w" 'delete-and-edit) | |
501 (define-key map "\C-l" 'recenter) | |
502 (define-key map "!" 'automatic) | |
503 (define-key map "^" 'backup) | |
504 (define-key map [(control h)] 'help) ;; XEmacs change | |
505 (define-key map [f1] 'help) | |
506 (define-key map [help] 'help) | |
507 (define-key map "?" 'help) | |
508 (define-key map "\C-g" 'quit) | |
509 (define-key map "\C-]" 'quit) | |
510 ;FSFmacs (define-key map "\e" 'exit-prefix) | |
511 (define-key map [escape] 'exit-prefix) | |
444 | 512 |
428 | 513 (setq query-replace-map map))) |
514 | |
515 ;; isearch-mode is dumped, so don't autoload. | |
516 ;(autoload 'isearch-highlight "isearch") | |
517 | |
518 ;; XEmacs | |
519 (defun perform-replace-next-event (event) | |
442 | 520 (if search-highlight |
428 | 521 (let ((aborted t)) |
522 (unwind-protect | |
523 (progn | |
524 (if (match-beginning 0) | |
525 (isearch-highlight (match-beginning 0) (match-end 0))) | |
526 (next-command-event event) | |
527 (setq aborted nil)) | |
528 (isearch-dehighlight aborted))) | |
529 (next-command-event event))) | |
530 | |
531 (defun perform-replace (from-string replacements | |
532 query-flag regexp-flag delimited-flag | |
533 &optional repeat-count map) | |
534 "Subroutine of `query-replace'. Its complexity handles interactive queries. | |
535 Don't use this in your own program unless you want to query and set the mark | |
536 just as `query-replace' does. Instead, write a simple loop like this: | |
537 (while (re-search-forward \"foo[ \t]+bar\" nil t) | |
538 (replace-match \"foobar\" nil nil)) | |
539 which will run faster and probably do exactly what you want. | |
444 | 540 When searching for a match, this function uses |
541 `replace-search-function' and `replace-re-search-function'." | |
428 | 542 (or map (setq map query-replace-map)) |
543 (let* ((event (make-event)) | |
544 (nocasify (not (and case-fold-search case-replace | |
545 (string-equal from-string | |
546 (downcase from-string))))) | |
547 (literal (not regexp-flag)) | |
444 | 548 (search-function (if regexp-flag |
549 replace-re-search-function | |
428 | 550 replace-search-function)) |
551 (search-string from-string) | |
552 (real-match-data nil) ; the match data for the current match | |
553 (next-replacement nil) | |
554 (replacement-index 0) | |
555 (keep-going t) | |
556 (stack nil) | |
557 (next-rotate-count 0) | |
558 (replace-count 0) | |
559 (lastrepl nil) ;Position after last match considered. | |
560 ;; If non-nil, it is marker saying where in the buffer to | |
561 ;; stop. | |
562 (limit nil) | |
563 (match-again t) | |
564 ;; XEmacs addition | |
565 (qr-case-fold-search | |
566 (if (and case-fold-search search-caps-disable-folding) | |
567 (no-upper-case-p search-string regexp-flag) | |
568 case-fold-search)) | |
569 (message | |
570 (if query-flag | |
571 (substitute-command-keys | |
572 "Query replacing %s with %s: (\\<query-replace-map>\\[help] for help) ")))) | |
573 ;; If the region is active, operate on region. | |
574 (when (region-active-p) | |
575 ;; Original Per Abrahamsen's code simply narrowed the region, | |
576 ;; thus providing a visual indication of the search boundary. | |
577 ;; Stallman, on the other hand, handles it like this. | |
578 (setq limit (copy-marker (region-end))) | |
579 (goto-char (region-beginning)) | |
580 (zmacs-deactivate-region)) | |
581 (if (stringp replacements) | |
582 (setq next-replacement replacements) | |
583 (or repeat-count (setq repeat-count 1))) | |
584 (if delimited-flag | |
585 (setq search-function replace-re-search-function | |
586 search-string (concat "\\b" | |
587 (if regexp-flag from-string | |
588 (regexp-quote from-string)) | |
589 "\\b"))) | |
590 (push-mark) | |
591 (undo-boundary) | |
592 (unwind-protect | |
593 ;; Loop finding occurrences that perhaps should be replaced. | |
594 (while (and keep-going | |
595 (not (eobp)) | |
596 (or (null limit) (< (point) limit)) | |
597 (let ((case-fold-search qr-case-fold-search)) | |
598 (funcall search-function search-string limit)) | |
599 ;; If the search string matches immediately after | |
600 ;; the previous match, but it did not match there | |
601 ;; before the replacement was done, ignore the match. | |
602 (if (or (eq lastrepl (point)) | |
603 (and regexp-flag | |
604 (eq lastrepl (match-beginning 0)) | |
605 (not match-again))) | |
606 (if (or (eobp) | |
607 (and limit (>= (point) limit))) | |
608 nil | |
444 | 609 ;; Don't replace the null string |
428 | 610 ;; right after end of previous replacement. |
611 (forward-char 1) | |
612 (let ((case-fold-search qr-case-fold-search)) | |
613 (funcall search-function search-string limit))) | |
614 t)) | |
615 | |
616 ;; Save the data associated with the real match. | |
617 (setq real-match-data (match-data)) | |
618 | |
619 ;; Before we make the replacement, decide whether the search string | |
620 ;; can match again just after this match. | |
621 (if regexp-flag | |
444 | 622 (progn |
428 | 623 (setq match-again (looking-at search-string)) |
624 ;; XEmacs addition | |
625 (store-match-data real-match-data))) | |
626 ;; If time for a change, advance to next replacement string. | |
627 (if (and (listp replacements) | |
628 (= next-rotate-count replace-count)) | |
629 (progn | |
630 (setq next-rotate-count | |
631 (+ next-rotate-count repeat-count)) | |
632 (setq next-replacement (nth replacement-index replacements)) | |
633 (setq replacement-index (% (1+ replacement-index) (length replacements))))) | |
634 (if (not query-flag) | |
635 (progn | |
636 (store-match-data real-match-data) | |
637 (replace-match next-replacement nocasify literal) | |
638 (setq replace-count (1+ replace-count))) | |
639 (undo-boundary) | |
640 (let ((help-form | |
641 '(concat (format "Query replacing %s%s with %s.\n\n" | |
642 (if regexp-flag (gettext "regexp ") "") | |
643 from-string next-replacement) | |
644 (substitute-command-keys query-replace-help))) | |
645 done replaced def) | |
646 ;; Loop reading commands until one of them sets done, | |
647 ;; which means it has finished handling this occurrence. | |
648 (while (not done) | |
649 ;; Don't fill up the message log | |
650 ;; with a bunch of identical messages. | |
651 ;; XEmacs change | |
652 (display-message 'prompt | |
653 (format message from-string next-replacement)) | |
654 (perform-replace-next-event event) | |
655 (setq def (lookup-key map (vector event))) | |
656 ;; Restore the match data while we process the command. | |
657 (store-match-data real-match-data) | |
658 (cond ((eq def 'help) | |
659 (with-output-to-temp-buffer (gettext "*Help*") | |
660 (princ (concat | |
661 (format "Query replacing %s%s with %s.\n\n" | |
662 (if regexp-flag "regexp " "") | |
663 from-string next-replacement) | |
664 (substitute-command-keys | |
665 query-replace-help))) | |
666 (save-excursion | |
667 (set-buffer standard-output) | |
668 (help-mode)))) | |
669 ((eq def 'exit) | |
670 (setq keep-going nil) | |
671 (setq done t)) | |
672 ((eq def 'backup) | |
673 (if stack | |
674 (let ((elt (car stack))) | |
675 (goto-char (car elt)) | |
676 (setq replaced (eq t (cdr elt))) | |
677 (or replaced | |
678 (store-match-data (cdr elt))) | |
679 (setq stack (cdr stack))) | |
680 (message "No previous match") | |
681 (ding 'no-terminate) | |
682 (sit-for 1))) | |
683 ((eq def 'act) | |
684 (or replaced | |
685 (replace-match next-replacement nocasify literal)) | |
686 (setq done t replaced t)) | |
687 ((eq def 'act-and-exit) | |
688 (or replaced | |
689 (replace-match next-replacement nocasify literal)) | |
690 (setq keep-going nil) | |
691 (setq done t replaced t)) | |
692 ((eq def 'act-and-show) | |
693 (if (not replaced) | |
694 (progn | |
695 (replace-match next-replacement nocasify literal) | |
696 (store-match-data nil) | |
697 (setq replaced t)))) | |
698 ((eq def 'automatic) | |
699 (or replaced | |
700 (replace-match next-replacement nocasify literal)) | |
701 (setq done t query-flag nil replaced t)) | |
702 ((eq def 'skip) | |
703 (setq done t)) | |
704 ((eq def 'recenter) | |
705 (recenter nil)) | |
706 ((eq def 'edit) | |
707 (store-match-data | |
708 (prog1 (match-data) | |
709 (save-excursion (recursive-edit)))) | |
710 ;; Before we make the replacement, | |
711 ;; decide whether the search string | |
712 ;; can match again just after this match. | |
713 (if regexp-flag | |
714 (setq match-again (looking-at search-string)))) | |
715 ((eq def 'delete-and-edit) | |
716 (delete-region (match-beginning 0) (match-end 0)) | |
717 (store-match-data (prog1 (match-data) | |
718 (save-excursion (recursive-edit)))) | |
719 (setq replaced t)) | |
720 ;; Note: we do not need to treat `exit-prefix' | |
721 ;; specially here, since we reread | |
722 ;; any unrecognized character. | |
723 (t | |
724 (setq this-command 'mode-exited) | |
725 (setq keep-going nil) | |
726 (setq unread-command-events | |
727 (cons event unread-command-events)) | |
728 (setq done t)))) | |
729 ;; Record previous position for ^ when we move on. | |
730 ;; Change markers to numbers in the match data | |
731 ;; since lots of markers slow down editing. | |
732 (setq stack | |
733 (cons (cons (point) | |
734 (or replaced | |
735 (match-data t))) | |
736 stack)) | |
737 (if replaced (setq replace-count (1+ replace-count))))) | |
738 (setq lastrepl (point))) | |
739 ;; Useless in XEmacs. We handle (de)highlighting through | |
740 ;; perform-replace-next-event. | |
741 ;(replace-dehighlight) | |
742 ) | |
743 (or unread-command-events | |
744 (message "Replaced %d occurrence%s" | |
745 replace-count | |
746 (if (= replace-count 1) "" "s"))) | |
747 (and keep-going stack))) | |
748 | |
749 ;; FSFmacs code: someone should port it. | |
750 | |
751 ;(defvar query-replace-highlight nil | |
752 ; "*Non-nil means to highlight words during query replacement.") | |
753 | |
754 ;(defvar replace-overlay nil) | |
755 | |
756 ;(defun replace-dehighlight () | |
757 ; (and replace-overlay | |
758 ; (progn | |
759 ; (delete-overlay replace-overlay) | |
760 ; (setq replace-overlay nil)))) | |
761 | |
762 ;(defun replace-highlight (start end) | |
763 ; (and query-replace-highlight | |
764 ; (progn | |
765 ; (or replace-overlay | |
766 ; (progn | |
767 ; (setq replace-overlay (make-overlay start end)) | |
768 ; (overlay-put replace-overlay 'face | |
769 ; (if (internal-find-face 'query-replace) | |
770 ; 'query-replace 'region)))) | |
771 ; (move-overlay replace-overlay start end (current-buffer))))) | |
772 | |
773 ;;; replace.el ends here |