Mercurial > hg > xemacs-beta
comparison lisp/prim/replace.el @ 4:b82b59fe008d r19-15b3
Import from CVS: tag r19-15b3
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:46:56 +0200 |
parents | ac2d302a0011 |
children | bcdc7deadc19 |
comparison
equal
deleted
inserted
replaced
3:30df88044ec6 | 4:b82b59fe008d |
---|---|
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 ;; General Public License for more details. | 15 ;; General Public License for more details. |
16 | 16 |
17 ;; You should have received a copy of the GNU General Public License | 17 ;; You should have received a copy of the GNU General Public License |
18 ;; along with XEmacs; see the file COPYING. If not, write to the Free | 18 ;; along with XEmacs; see the file COPYING. If not, write to the Free |
19 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 19 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
20 | 20 ;; 02111-1307, USA. |
21 ;;; Synched up with: FSF 19.30. | 21 |
22 ;;; Synched up with: FSF 19.34 [Partially]. | |
22 | 23 |
23 ;;; Commentary: | 24 ;;; Commentary: |
24 | 25 |
25 ;; This package supplies the string and regular-expression replace functions | 26 ;; This package supplies the string and regular-expression replace functions |
26 ;; documented in the XEmacs Reference Manual. | 27 ;; documented in the XEmacs Reference Manual. |
27 | 28 |
29 ;; All the gettext calls are for XEmacs I18N3 message catalog support. | |
30 | |
28 ;;; Code: | 31 ;;; Code: |
29 | 32 |
30 (defvar case-replace t "\ | 33 (defconst case-replace t "\ |
31 *Non-nil means `query-replace' should preserve case in replacements. | 34 *Non-nil means `query-replace' should preserve case in replacements. |
32 What this means is that `query-replace' will change the case of the | 35 What this means is that `query-replace' will change the case of the |
33 replacement text so that it matches the text that was replaced. | 36 replacement text so that it matches the text that was replaced. |
34 If this variable is nil, the replacement text will be inserted | 37 If this variable is nil, the replacement text will be inserted |
35 exactly as it was specified by the user, irrespective of the case | 38 exactly as it was specified by the user, irrespective of the case |
142 | 145 |
143 (defun replace-string (from-string to-string &optional delimited) | 146 (defun replace-string (from-string to-string &optional delimited) |
144 "Replace occurrences of FROM-STRING with TO-STRING. | 147 "Replace occurrences of FROM-STRING with TO-STRING. |
145 Preserve case in each match if `case-replace' and `case-fold-search' | 148 Preserve case in each match if `case-replace' and `case-fold-search' |
146 are non-nil and FROM-STRING has no uppercase letters. | 149 are non-nil and FROM-STRING has no uppercase letters. |
150 \(Preserving case means that if the string matched is all caps, or capitalized, | |
151 then its replacement is upcased or capitalized.) | |
152 | |
147 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace | 153 Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace |
148 only matches surrounded by word boundaries. | 154 only matches surrounded by word boundaries. |
149 | 155 |
150 If `query-replace-interactive' is non-nil, the last incremental search | 156 If `query-replace-interactive' is non-nil, the last incremental search |
151 string is used as FROM-STRING--you don't have to specify it with the | 157 string is used as FROM-STRING--you don't have to specify it with the |
249 | 255 |
250 (defvar occur-mode-map ()) | 256 (defvar occur-mode-map ()) |
251 (if occur-mode-map | 257 (if occur-mode-map |
252 () | 258 () |
253 (setq occur-mode-map (make-sparse-keymap)) | 259 (setq occur-mode-map (make-sparse-keymap)) |
254 (set-keymap-name occur-mode-map 'occur-mode-map) | 260 (set-keymap-name occur-mode-map 'occur-mode-map) ; XEmacs |
255 (define-key occur-mode-map 'button2 'occur-mode-mouse-goto) | 261 (define-key occur-mode-map [mouse-2] 'occur-mode-mouse-goto) |
256 (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence) | 262 (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence) |
257 (define-key occur-mode-map "\C-m" 'occur-mode-goto-occurrence)) | 263 (define-key occur-mode-map "\C-m" 'occur-mode-goto-occurrence)) |
258 | 264 |
259 (defvar occur-buffer nil) | 265 (defvar occur-buffer nil) |
260 (defvar occur-nlines nil) | 266 (defvar occur-nlines nil) |
268 | 274 |
269 \\{occur-mode-map}" | 275 \\{occur-mode-map}" |
270 (kill-all-local-variables) | 276 (kill-all-local-variables) |
271 (use-local-map occur-mode-map) | 277 (use-local-map occur-mode-map) |
272 (setq major-mode 'occur-mode) | 278 (setq major-mode 'occur-mode) |
273 (setq mode-name (gettext "Occur")) | 279 (setq mode-name (gettext "Occur")) ; XEmacs |
274 (make-local-variable 'occur-buffer) | 280 (make-local-variable 'occur-buffer) |
275 (make-local-variable 'occur-nlines) | 281 (make-local-variable 'occur-nlines) |
276 (make-local-variable 'occur-pos-list) | 282 (make-local-variable 'occur-pos-list) |
277 (require 'mode-motion) | 283 (require 'mode-motion) ; XEmacs |
278 (setq mode-motion-hook 'mode-motion-highlight-line) | 284 (setq mode-motion-hook 'mode-motion-highlight-line) ; XEmacs |
279 (run-hooks 'occur-mode-hook)) | 285 (run-hooks 'occur-mode-hook)) |
280 | 286 |
281 (defun occur-mode-mouse-goto (e) | 287 ;; FSF Version of next function: |
288 ; (let (buffer pos) | |
289 ; (save-excursion | |
290 ; (set-buffer (window-buffer (posn-window (event-end event)))) | |
291 ; (save-excursion | |
292 ; (goto-char (posn-point (event-end event))) | |
293 ; (setq pos (occur-mode-find-occurrence)) | |
294 ; (setq buffer occur-buffer))) | |
295 ; (pop-to-buffer buffer) | |
296 ; (goto-char (marker-position pos)))) | |
297 | |
298 (defun occur-mode-mouse-goto (event) | |
282 "Go to the occurrence highlighted by mouse. | 299 "Go to the occurrence highlighted by mouse. |
283 This function is only reasonable when bound to a mouse key in the occur buffer" | 300 This function is only reasonable when bound to a mouse key in the occur buffer" |
284 (interactive "e") | 301 (interactive "e") |
285 (let ((window-save (selected-window)) | 302 (let ((window-save (selected-window)) |
286 (frame-save (selected-frame))) | 303 (frame-save (selected-frame))) |
290 (mouse-set-point e) | 307 (mouse-set-point e) |
291 (occur-mode-goto-occurrence)) | 308 (occur-mode-goto-occurrence)) |
292 (select-frame frame-save) | 309 (select-frame frame-save) |
293 (select-window window-save)))) | 310 (select-window window-save)))) |
294 | 311 |
312 ;; Called occur-mode-find-occurrence in FSF | |
295 (defun occur-mode-goto-occurrence () | 313 (defun occur-mode-goto-occurrence () |
296 "Go to the occurrence the current line describes." | 314 "Go to the occurrence the current line describes." |
297 (interactive) | 315 (interactive) |
298 (if (or (null occur-buffer) | 316 (if (or (null occur-buffer) |
299 (null (buffer-name occur-buffer))) | 317 (null (buffer-name occur-buffer))) |
320 (occur-source-buffer occur-buffer)) | 338 (occur-source-buffer occur-buffer)) |
321 (if (< line-count 1) | 339 (if (< line-count 1) |
322 (error "No occurrence on this line")) | 340 (error "No occurrence on this line")) |
323 (or pos | 341 (or pos |
324 (error "No occurrence on this line")) | 342 (error "No occurrence on this line")) |
325 ;; don't raise window unless it isn't visible | 343 ;; XEmacs: don't raise window unless it isn't visible |
326 ;; allow for the possibility that the occur buffer is on another frame | 344 ;; allow for the possibility that the occur buffer is on another frame |
327 (or (and window | 345 (or (and window |
328 (window-live-p window) | 346 (window-live-p window) |
329 (frame-visible-p (window-frame window)) | 347 (frame-visible-p (window-frame window)) |
330 (set-buffer occur-source-buffer)) | 348 (set-buffer occur-source-buffer)) |
341 | 359 |
342 ;; XEmacs addition | 360 ;; XEmacs addition |
343 ;;; Damn you Jamie, this is utter trash. | 361 ;;; Damn you Jamie, this is utter trash. |
344 (defvar list-matching-lines-whole-buffer t | 362 (defvar list-matching-lines-whole-buffer t |
345 "If t, occur operates on whole buffer, otherwise occur starts from point. | 363 "If t, occur operates on whole buffer, otherwise occur starts from point. |
346 default is nil.") | 364 default is t.") |
347 | 365 |
348 (define-function 'occur 'list-matching-lines) | 366 (define-function 'occur 'list-matching-lines) |
349 (defun list-matching-lines (regexp &optional nlines) | 367 (defun list-matching-lines (regexp &optional nlines) |
350 "Show all lines in the current buffer containing a match for REGEXP. | 368 "Show all lines in the current buffer containing a match for REGEXP. |
351 | 369 |
352 If a match spreads across multiple lines, all those lines are shown. | 370 If a match spreads across multiple lines, all those lines are shown. |
353 | 371 |
354 If variable `list-matching-lines-whole-buffer' is non-nil, the entire buffer is | 372 If variable `list-matching-lines-whole-buffer' is non-nil, the entire buffer is |
355 searched, otherwise search begins at point. | 373 searched, otherwise search begins at point. |
356 | 374 |
357 Each line is displayed with NLINES lines before and after, | 375 Each line is displayed with NLINES lines before and after, or -NLINES |
358 or -NLINES before if NLINES is negative. | 376 before if NLINES is negative. |
359 NLINES defaults to `list-matching-lines-default-context-lines'. | 377 NLINES defaults to `list-matching-lines-default-context-lines'. |
360 Interactively it is the prefix arg. | 378 Interactively it is the prefix arg. |
361 | 379 |
362 The lines are shown in a buffer named `*Occur*'. | 380 The lines are shown in a buffer named `*Occur*'. |
363 It serves as a menu to find any of the occurrences in this buffer. | 381 It serves as a menu to find any of the occurrences in this buffer. |
364 \\[describe-mode] in that buffer will explain how." | 382 \\[describe-mode] in that buffer will explain how." |
365 (interactive | 383 (interactive |
384 ;; XEmacs change | |
366 (list (let* ((default (or (symbol-near-point) | 385 (list (let* ((default (or (symbol-near-point) |
367 (and regexp-history | 386 (and regexp-history |
368 (car regexp-history)))) | 387 (car regexp-history)))) |
369 (minibuffer-history-minimum-string-length 0) | 388 (minibuffer-history-minimum-string-length 0) |
370 (input | 389 (input |
393 (let ((first t) | 412 (let ((first t) |
394 (dir default-directory) | 413 (dir default-directory) |
395 (buffer (current-buffer)) | 414 (buffer (current-buffer)) |
396 (linenum 1) | 415 (linenum 1) |
397 (prevpos (point-min)) | 416 (prevpos (point-min)) |
417 ;; The rest of this function is very different from FSF. | |
418 ;; Presumably that's due to Jamie's misfeature | |
398 (final-context-start (make-marker))) | 419 (final-context-start (make-marker))) |
399 (if (not list-matching-lines-whole-buffer) | 420 (if (not list-matching-lines-whole-buffer) |
400 (save-excursion | 421 (save-excursion |
401 (beginning-of-line) | 422 (beginning-of-line) |
402 (setq linenum (1+ (count-lines (point-min) (point)))) | 423 (setq linenum (1+ (count-lines (point-min) (point)))) |
495 (if (interactive-p) | 516 (if (interactive-p) |
496 (message "%d matching lines." (length occur-pos-list))))))) | 517 (message "%d matching lines." (length occur-pos-list))))))) |
497 | 518 |
498 ;; It would be nice to use \\[...], but there is no reasonable way | 519 ;; It would be nice to use \\[...], but there is no reasonable way |
499 ;; to make that display both SPC and Y. | 520 ;; to make that display both SPC and Y. |
500 (defvar query-replace-help (purecopy | 521 (defconst query-replace-help |
501 "Type Space or `y' to replace one match, Delete or `n' to skip to next, | 522 (purecopy |
523 "Type Space or `y' to replace one match, Delete or `n' to skip to next, | |
502 RET or `q' to exit, Period to replace one match and exit, | 524 RET or `q' to exit, Period to replace one match and exit, |
503 Comma to replace but not move point immediately, | 525 Comma to replace but not move point immediately, |
504 C-r to enter recursive edit (\\[exit-recursive-edit] to get out again), | 526 C-r to enter recursive edit (\\[exit-recursive-edit] to get out again), |
505 C-w to delete match and recursive edit, | 527 C-w to delete match and recursive edit, |
506 C-l to clear the frame, redisplay, and offer same replacement again, | 528 C-l to clear the frame, redisplay, and offer same replacement again, |
507 ! to replace all remaining matches with no more questions, | 529 ! to replace all remaining matches with no more questions, |
508 ^ to move point back to previous match.") | 530 ^ to move point back to previous match." |
531 ) | |
509 "Help message while in query-replace") | 532 "Help message while in query-replace") |
510 | 533 |
511 (defvar query-replace-map nil | 534 (defvar query-replace-map nil |
512 "Keymap that defines the responses to questions in `query-replace'. | 535 "Keymap that defines the responses to questions in `query-replace'. |
513 The \"bindings\" in this map are not commands; they are answers. | 536 The \"bindings\" in this map are not commands; they are answers. |
514 The valid answers include `act', `skip', `act-and-show', | 537 The valid answers include `act', `skip', `act-and-show', |
515 `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', | 538 `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', |
516 `automatic', `backup', `exit-prefix', and `help'.") | 539 `automatic', `backup', `exit-prefix', and `help'.") |
517 | 540 |
541 ;; Why does it seem that ever file has a different method of doing this? | |
518 (if query-replace-map | 542 (if query-replace-map |
519 nil | 543 nil |
520 (let ((map (make-sparse-keymap))) | 544 (let ((map (make-sparse-keymap))) |
521 (set-keymap-name map 'query-replace-map) | 545 (set-keymap-name map 'query-replace-map) |
522 (define-key map " " 'act) | 546 (define-key map " " 'act) |
549 (setq query-replace-map map))) | 573 (setq query-replace-map map))) |
550 | 574 |
551 | 575 |
552 (autoload 'isearch-highlight "isearch") | 576 (autoload 'isearch-highlight "isearch") |
553 | 577 |
578 ;; XEmacs | |
554 (defun perform-replace-next-event (event) | 579 (defun perform-replace-next-event (event) |
555 (if isearch-highlight | 580 (if isearch-highlight |
556 (let ((aborted t)) | 581 (let ((aborted t)) |
557 (unwind-protect | 582 (unwind-protect |
558 (progn | 583 (progn |
572 (replace-match \"foobar\" nil nil)) | 597 (replace-match \"foobar\" nil nil)) |
573 which will run faster and probably do exactly what you want." | 598 which will run faster and probably do exactly what you want." |
574 (or map (setq map query-replace-map)) | 599 (or map (setq map query-replace-map)) |
575 (let* ((event (make-event)) | 600 (let* ((event (make-event)) |
576 (nocasify (not (and case-fold-search case-replace | 601 (nocasify (not (and case-fold-search case-replace |
577 (string-equal from-string | 602 (string-equal from-string |
578 (downcase from-string))))) | 603 (downcase from-string))))) |
579 (literal (not regexp-flag)) | 604 (literal (not regexp-flag)) |
580 (search-function (if regexp-flag 're-search-forward 'search-forward)) | 605 (search-function (if regexp-flag 're-search-forward 'search-forward)) |
581 (search-string from-string) | 606 (search-string from-string) |
582 (real-match-data nil) ; the match data for the current match | 607 (real-match-data nil) ; the match data for the current match |
583 (next-replacement nil) | 608 (next-replacement nil) |
606 (if regexp-flag from-string | 631 (if regexp-flag from-string |
607 (regexp-quote from-string)) | 632 (regexp-quote from-string)) |
608 "\\b"))) | 633 "\\b"))) |
609 (push-mark) | 634 (push-mark) |
610 (undo-boundary) | 635 (undo-boundary) |
611 ;; Loop finding occurrences that perhaps should be replaced. | 636 (unwind-protect |
612 (while (and keep-going | 637 ;; Loop finding occurrences that perhaps should be replaced. |
613 (not (eobp)) | 638 (while (and keep-going |
614 (let ((case-fold-search qr-case-fold-search)) | 639 (not (eobp)) |
615 (funcall search-function search-string nil t)) | 640 (let ((case-fold-search qr-case-fold-search)) |
616 ;; If the search string matches immediately after | 641 (funcall search-function search-string nil t)) |
617 ;; the previous match, but it did not match there | 642 ;; If the search string matches immediately after |
618 ;; before the replacement was done, ignore the match. | 643 ;; the previous match, but it did not match there |
619 (if (or (eq lastrepl (point)) | 644 ;; before the replacement was done, ignore the match. |
620 (and regexp-flag | 645 (if (or (eq lastrepl (point)) |
621 (eq lastrepl (match-beginning 0)) | 646 (and regexp-flag |
622 (not match-again))) | 647 (eq lastrepl (match-beginning 0)) |
623 | 648 (not match-again))) |
624 (if (eobp) | 649 (if (eobp) |
625 nil | 650 nil |
626 ;; Don't replace the null string | 651 ;; Don't replace the null string |
627 ;; right after end of previous replacement. | 652 ;; right after end of previous replacement. |
628 (forward-char 1) | 653 (forward-char 1) |
629 (let ((case-fold-search qr-case-fold-search)) | 654 (let ((case-fold-search qr-case-fold-search)) |
630 (funcall search-function search-string nil t))) | 655 (funcall search-function search-string nil t))) |
631 t)) | 656 t)) |
632 ;; Save the data associated with the real match. | 657 |
633 (setq real-match-data (match-data)) | 658 ;; Save the data associated with the real match. |
634 | 659 (setq real-match-data (match-data)) |
635 ;; Before we make the replacement, decide whether the search string | 660 |
636 ;; can match again just after this match. | 661 ;; Before we make the replacement, decide whether the search string |
637 (if regexp-flag | 662 ;; can match again just after this match. |
638 (progn | 663 (if regexp-flag |
639 (setq match-again (looking-at search-string)) | 664 (progn |
640 (store-match-data real-match-data))) | 665 (setq match-again (looking-at search-string)) |
641 | 666 ;; XEmacs addition |
642 ;; If time for a change, advance to next replacement string. | 667 (store-match-data real-match-data))) |
643 (if (and (listp replacements) | 668 ;; If time for a change, advance to next replacement string. |
644 (= next-rotate-count replace-count)) | 669 (if (and (listp replacements) |
645 (progn | 670 (= next-rotate-count replace-count)) |
646 (setq next-rotate-count | 671 (progn |
647 (+ next-rotate-count repeat-count)) | 672 (setq next-rotate-count |
648 (setq next-replacement (nth replacement-index replacements)) | 673 (+ next-rotate-count repeat-count)) |
649 (setq replacement-index (% (1+ replacement-index) (length replacements))))) | 674 (setq next-replacement (nth replacement-index replacements)) |
650 (if (not query-flag) | 675 (setq replacement-index (% (1+ replacement-index) (length replacements))))) |
651 (progn | 676 (if (not query-flag) |
652 (store-match-data real-match-data) | 677 (progn |
653 (replace-match next-replacement nocasify literal) | 678 (store-match-data real-match-data) |
654 (setq replace-count (1+ replace-count))) | 679 (replace-match next-replacement nocasify literal) |
655 (undo-boundary) | 680 (setq replace-count (1+ replace-count))) |
656 (let ((help-form | 681 (undo-boundary) |
657 '(concat (format "Query replacing %s%s with %s.\n\n" | 682 (let ((help-form |
658 (if regexp-flag (gettext "regexp ") "") | 683 '(concat (format "Query replacing %s%s with %s.\n\n" |
659 from-string next-replacement) | 684 (if regexp-flag (gettext "regexp ") "") |
660 (substitute-command-keys query-replace-help))) | 685 from-string next-replacement) |
661 (done nil) | 686 (substitute-command-keys query-replace-help))) |
662 (replaced nil) | 687 done replaced def) |
663 def) | 688 ;; Loop reading commands until one of them sets done, |
664 ;; Loop reading commands until one of them sets done, | 689 ;; which means it has finished handling this occurrence. |
665 ;; which means it has finished handling this occurrence. | 690 (while (not done) |
666 (while (not done) | 691 ;; Don't fill up the message log |
667 ;; Don't fill up the message log | 692 ;; with a bunch of identical messages. |
668 ;; with a bunch of identical messages. | 693 ;; XEmacs change |
669 (display-message 'prompt | 694 (display-message 'prompt |
670 (format message from-string next-replacement)) | 695 (format message from-string next-replacement)) |
671 (perform-replace-next-event event) | 696 (perform-replace-next-event event) |
672 (setq def (lookup-key map (vector event))) | 697 (setq def (lookup-key map (vector event))) |
673 ;; Restore the match data while we process the command. | 698 ;; Restore the match data while we process the command. |
674 (store-match-data real-match-data) | 699 (store-match-data real-match-data) |
675 (cond ((eq def 'help) | 700 (cond ((eq def 'help) |
676 (with-output-to-temp-buffer (gettext "*Help*") | 701 (with-output-to-temp-buffer (gettext "*Help*") |
677 (princ (concat | 702 (princ (concat |
678 (format "Query replacing %s%s with %s.\n\n" | 703 (format "Query replacing %s%s with %s.\n\n" |
679 (if regexp-flag "regexp " "") | 704 (if regexp-flag "regexp " "") |
680 from-string next-replacement) | 705 from-string next-replacement) |
681 (substitute-command-keys | 706 (substitute-command-keys |
682 query-replace-help))) | 707 query-replace-help))) |
683 (save-excursion | 708 (save-excursion |
684 (set-buffer standard-output) | 709 (set-buffer standard-output) |
685 (help-mode)))) | 710 (help-mode)))) |
686 ((eq def 'exit) | 711 ((eq def 'exit) |
687 (setq keep-going nil) | 712 (setq keep-going nil) |
688 (setq done t)) | 713 (setq done t)) |
689 ((eq def 'backup) | 714 ((eq def 'backup) |
690 (if stack | 715 (if stack |
691 (let ((elt (car stack))) | 716 (let ((elt (car stack))) |
692 (goto-char (car elt)) | 717 (goto-char (car elt)) |
693 (setq replaced (eq t (cdr elt))) | 718 (setq replaced (eq t (cdr elt))) |
694 (or replaced | 719 (or replaced |
695 (store-match-data (cdr elt))) | 720 (store-match-data (cdr elt))) |
696 (setq stack (cdr stack))) | 721 (setq stack (cdr stack))) |
697 (progn | |
698 (message "No previous match") | 722 (message "No previous match") |
699 (ding 'no-terminate) | 723 (ding 'no-terminate) |
700 (sit-for 1)))) | 724 (sit-for 1))) |
701 ((eq def 'act) | 725 ((eq def 'act) |
702 (or replaced | 726 (or replaced |
703 (replace-match next-replacement nocasify literal)) | 727 (replace-match next-replacement nocasify literal)) |
704 (setq done t replaced t)) | 728 (setq done t replaced t)) |
705 ((eq def 'act-and-exit) | 729 ((eq def 'act-and-exit) |
706 (or replaced | 730 (or replaced |
707 (replace-match next-replacement nocasify literal)) | 731 (replace-match next-replacement nocasify literal)) |
708 (setq keep-going nil) | 732 (setq keep-going nil) |
709 (setq done t replaced t)) | 733 (setq done t replaced t)) |
710 ((eq def 'act-and-show) | 734 ((eq def 'act-and-show) |
711 (if (not replaced) | 735 (if (not replaced) |
712 (progn | 736 (progn |
713 (replace-match next-replacement nocasify literal) | 737 (replace-match next-replacement nocasify literal) |
714 (setq replaced t)))) | 738 (setq replaced t)))) |
715 ((eq def 'automatic) | 739 ((eq def 'automatic) |
716 (or replaced | 740 (or replaced |
717 (replace-match next-replacement nocasify literal)) | 741 (replace-match next-replacement nocasify literal)) |
718 (setq done t query-flag nil replaced t)) | 742 (setq done t query-flag nil replaced t)) |
719 ((eq def 'skip) | 743 ((eq def 'skip) |
720 (setq done t)) | 744 (setq done t)) |
721 ((eq def 'recenter) | 745 ((eq def 'recenter) |
722 (recenter nil)) | 746 (recenter nil)) |
723 ((eq def 'edit) | 747 ((eq def 'edit) |
724 (store-match-data | 748 (store-match-data |
725 (prog1 (match-data) | 749 (prog1 (match-data) |
726 (save-excursion (recursive-edit)))) | 750 (save-excursion (recursive-edit)))) |
727 ;; Before we make the replacement, | 751 ;; Before we make the replacement, |
728 ;; decide whether the search string | 752 ;; decide whether the search string |
729 ;; can match again just after this match. | 753 ;; can match again just after this match. |
730 (if regexp-flag | 754 (if regexp-flag |
731 (setq match-again (looking-at search-string)))) | 755 (setq match-again (looking-at search-string)))) |
732 ((eq def 'delete-and-edit) | 756 ((eq def 'delete-and-edit) |
733 (delete-region (match-beginning 0) (match-end 0)) | 757 (delete-region (match-beginning 0) (match-end 0)) |
734 (store-match-data (prog1 (match-data) | 758 (store-match-data (prog1 (match-data) |
735 (save-excursion (recursive-edit)))) | 759 (save-excursion (recursive-edit)))) |
736 (setq replaced t)) | 760 (setq replaced t)) |
737 ;; Note: we do not need to treat `exit-prefix' | 761 ;; Note: we do not need to treat `exit-prefix' |
738 ;; specially here, since we reread | 762 ;; specially here, since we reread |
739 ;; any unrecognized character. | 763 ;; any unrecognized character. |
740 (t | 764 (t |
741 (setq this-command 'mode-exited) | 765 (setq this-command 'mode-exited) |
742 (setq keep-going nil) | 766 (setq keep-going nil) |
743 (setq unread-command-events | 767 (setq unread-command-events |
744 (cons event unread-command-events)) | 768 (cons event unread-command-events)) |
745 (setq done t)))) | 769 (setq done t)))) |
746 ;; Record previous position for ^ when we move on. | 770 ;; Record previous position for ^ when we move on. |
747 ;; Change markers to numbers in the match data | 771 ;; Change markers to numbers in the match data |
748 ;; since lots of markers slow down editing. | 772 ;; since lots of markers slow down editing. |
749 (setq stack | 773 (setq stack |
750 (cons (cons (point) | 774 (cons (cons (point) |
751 (or replaced | 775 (or replaced |
752 (mapcar | 776 (mapcar |
753 #'(lambda (elt) | 777 #'(lambda (elt) |
754 (if (markerp elt) | 778 (if (markerp elt) |
755 (prog1 (marker-position elt) | 779 (prog1 (marker-position elt) |
756 (set-marker elt nil)) | 780 (set-marker elt nil)) |
757 elt)) | 781 elt)) |
758 (match-data)))) | 782 (match-data)))) |
759 stack)) | 783 stack)) |
760 (if replaced (setq replace-count (1+ replace-count))))) | 784 (if replaced (setq replace-count (1+ replace-count))))) |
761 (setq lastrepl (point))) | 785 (setq lastrepl (point))) |
786 (replace-dehighlight)) | |
762 (or unread-command-events | 787 (or unread-command-events |
763 (message "Replaced %d occurrence%s" | 788 (message "Replaced %d occurrence%s" |
764 replace-count | 789 replace-count |
765 (if (= replace-count 1) "" "s"))) | 790 (if (= replace-count 1) "" "s"))) |
766 (and keep-going stack))) | 791 (and keep-going stack))) |
767 | 792 |
768 ; FSF 19.30 original: | 793 (defvar query-replace-highlight nil |
769 ; (defun match-string (num &optional string) | 794 "*Non-nil means to highlight words during query replacement.") |
770 ; "Return string of text matched by last search. | 795 |
771 ; NUM specifies which parenthesized expression in the last regexp. | 796 (defvar replace-overlay nil) |
772 ; Value is nil if NUMth pair didn't match, or there were less than NUM pairs. | 797 |
773 ; Zero means the entire text matched by the whole regexp or whole string. | 798 (defun replace-dehighlight () |
774 ; STRING should be given if the last search was by `string-match' on STRING." | 799 (and replace-overlay |
775 ; (if (match-beginning num) | 800 (progn |
776 ; (if string | 801 (delete-overlay replace-overlay) |
777 ; (substring string (match-beginning num) (match-end num)) | 802 (setq replace-overlay nil)))) |
778 ; (buffer-substring (match-beginning num) (match-end num))))) | 803 |
779 | 804 (defun replace-highlight (start end) |
780 ;; #### - this could stand to be in C... | 805 (and query-replace-highlight |
781 (defmacro match-string (n &optional string) | 806 (progn |
782 "Returns the Nth subexpression matched by the last regular expression | 807 (or replace-overlay |
783 search. The second argument, STRING, must be specified if the last | 808 (progn |
784 regular expression search was done with `string-match'." | 809 (setq replace-overlay (make-overlay start end)) |
785 ;; #### - note that match-beginning is byte coded, so it's more efficient | 810 (overlay-put replace-overlay 'face |
786 ;; to just call it twice than it is to let-bind its return value... --Stig | 811 (if (internal-find-face 'query-replace) |
787 `(and (match-beginning ,n) | 812 'query-replace 'region)))) |
788 ,(if string | 813 (move-overlay replace-overlay start end (current-buffer))))) |
789 `(substring ,string (match-beginning ,n) (match-end ,n)) | 814 |
790 `(buffer-substring (match-beginning ,n) (match-end ,n))))) | 815 (defun match-string (num &optional string) |
816 "Return string of text matched by last search. | |
817 NUM specifies which parenthesized expression in the last regexp. | |
818 Value is nil if NUMth pair didn't match, or there were less than NUM pairs. | |
819 Zero means the entire text matched by the whole regexp or whole string. | |
820 STRING should be given if the last search was by `string-match' on STRING." | |
821 (if (match-beginning num) | |
822 (if string | |
823 (substring string (match-beginning num) (match-end num)) | |
824 (buffer-substring (match-beginning num) (match-end num))))) | |
791 | 825 |
792 (defmacro save-match-data (&rest body) | 826 (defmacro save-match-data (&rest body) |
793 "Execute BODY forms, restoring the global value of the match data." | 827 "Execute BODY forms, restoring the global value of the match data." |
794 (let ((original (make-symbol "match-data"))) | 828 (let ((original (make-symbol "match-data"))) |
795 (list 'let (list (list original '(match-data))) | 829 (list 'let (list (list original '(match-data))) |