Mercurial > hg > xemacs-beta
diff lisp/prim/replace.el @ 72:b9518feda344 r20-0b31
Import from CVS: tag r20-0b31
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:03:46 +0200 |
parents | 131b0175ea99 |
children | 54cc21c15cbb |
line wrap: on
line diff
--- a/lisp/prim/replace.el Mon Aug 13 09:03:07 2007 +0200 +++ b/lisp/prim/replace.el Mon Aug 13 09:03:46 2007 +0200 @@ -15,20 +15,22 @@ ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with XEmacs; see the file COPYING. If not, write to the -;; Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with XEmacs; see the file COPYING. If not, write to the Free +;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +;; 02111-1307, USA. -;;; Synched up with: FSF 19.30. +;;; Synched up with: FSF 19.34 [Partially]. ;;; Commentary: ;; This package supplies the string and regular-expression replace functions ;; documented in the XEmacs Reference Manual. +;; All the gettext calls are for XEmacs I18N3 message catalog support. + ;;; Code: -(defvar case-replace t "\ +(defconst case-replace t "\ *Non-nil means `query-replace' should preserve case in replacements. What this means is that `query-replace' will change the case of the replacement text so that it matches the text that was replaced. @@ -145,6 +147,9 @@ "Replace occurrences of FROM-STRING with TO-STRING. Preserve case in each match if `case-replace' and `case-fold-search' are non-nil and FROM-STRING has no uppercase letters. +\(Preserving case means that if the string matched is all caps, or capitalized, +then its replacement is upcased or capitalized.) + Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace only matches surrounded by word boundaries. @@ -252,8 +257,8 @@ (if occur-mode-map () (setq occur-mode-map (make-sparse-keymap)) - (set-keymap-name occur-mode-map 'occur-mode-map) - (define-key occur-mode-map 'button2 'occur-mode-mouse-goto) + (set-keymap-name occur-mode-map 'occur-mode-map) ; XEmacs + (define-key occur-mode-map [mouse-2] 'occur-mode-mouse-goto) (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence) (define-key occur-mode-map "\C-m" 'occur-mode-goto-occurrence)) @@ -271,15 +276,26 @@ (kill-all-local-variables) (use-local-map occur-mode-map) (setq major-mode 'occur-mode) - (setq mode-name (gettext "Occur")) + (setq mode-name (gettext "Occur")) ; XEmacs (make-local-variable 'occur-buffer) (make-local-variable 'occur-nlines) (make-local-variable 'occur-pos-list) - (require 'mode-motion) - (setq mode-motion-hook 'mode-motion-highlight-line) + (require 'mode-motion) ; XEmacs + (setq mode-motion-hook 'mode-motion-highlight-line) ; XEmacs (run-hooks 'occur-mode-hook)) -(defun occur-mode-mouse-goto (e) +;; FSF Version of next function: +; (let (buffer pos) +; (save-excursion +; (set-buffer (window-buffer (posn-window (event-end event)))) +; (save-excursion +; (goto-char (posn-point (event-end event))) +; (setq pos (occur-mode-find-occurrence)) +; (setq buffer occur-buffer))) +; (pop-to-buffer buffer) +; (goto-char (marker-position pos)))) + +(defun occur-mode-mouse-goto (event) "Go to the occurrence highlighted by mouse. This function is only reasonable when bound to a mouse key in the occur buffer" (interactive "e") @@ -293,6 +309,7 @@ (select-frame frame-save) (select-window window-save)))) +;; Called occur-mode-find-occurrence in FSF (defun occur-mode-goto-occurrence () "Go to the occurrence the current line describes." (interactive) @@ -323,7 +340,7 @@ (error "No occurrence on this line")) (or pos (error "No occurrence on this line")) - ;; don't raise window unless it isn't visible + ;; XEmacs: don't raise window unless it isn't visible ;; allow for the possibility that the occur buffer is on another frame (or (and window (window-live-p window) @@ -344,7 +361,7 @@ ;;; Damn you Jamie, this is utter trash. (defvar list-matching-lines-whole-buffer t "If t, occur operates on whole buffer, otherwise occur starts from point. -default is nil.") +default is t.") (define-function 'occur 'list-matching-lines) (defun list-matching-lines (regexp &optional nlines) @@ -355,8 +372,8 @@ If variable `list-matching-lines-whole-buffer' is non-nil, the entire buffer is searched, otherwise search begins at point. -Each line is displayed with NLINES lines before and after, -or -NLINES before if NLINES is negative. +Each line is displayed with NLINES lines before and after, or -NLINES +before if NLINES is negative. NLINES defaults to `list-matching-lines-default-context-lines'. Interactively it is the prefix arg. @@ -364,6 +381,7 @@ It serves as a menu to find any of the occurrences in this buffer. \\[describe-mode] in that buffer will explain how." (interactive + ;; XEmacs change (list (let* ((default (or (symbol-near-point) (and regexp-history (car regexp-history)))) @@ -396,6 +414,8 @@ (buffer (current-buffer)) (linenum 1) (prevpos (point-min)) + ;; The rest of this function is very different from FSF. + ;; Presumably that's due to Jamie's misfeature (final-context-start (make-marker))) (if (not list-matching-lines-whole-buffer) (save-excursion @@ -420,7 +440,7 @@ (save-excursion (if list-matching-lines-whole-buffer (beginning-of-buffer)) - (message "Searching for %s ..." regexp) + (message (format "Searching for %s ..." regexp)) ;; Find next match, but give up if prev match was at end of buffer. (while (and (not (= prevpos (point-max))) (re-search-forward regexp nil t)) @@ -498,24 +518,27 @@ ;; It would be nice to use \\[...], but there is no reasonable way ;; to make that display both SPC and Y. -(defvar query-replace-help (purecopy - "Type Space or `y' to replace one match, Delete or `n' to skip to next, +(defconst query-replace-help + (purecopy + "Type Space or `y' to replace one match, Delete or `n' to skip to next, RET or `q' to exit, Period to replace one match and exit, Comma to replace but not move point immediately, C-r to enter recursive edit (\\[exit-recursive-edit] to get out again), C-w to delete match and recursive edit, C-l to clear the frame, redisplay, and offer same replacement again, ! to replace all remaining matches with no more questions, -^ to move point back to previous match.") +^ to move point back to previous match." +) "Help message while in query-replace") -(defvar query-replace-map nil +(defvar query-replace-map nil "Keymap that defines the responses to questions in `query-replace'. The \"bindings\" in this map are not commands; they are answers. The valid answers include `act', `skip', `act-and-show', `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', `automatic', `backup', `exit-prefix', and `help'.") +;; Why does it seem that ever file has a different method of doing this? (if query-replace-map nil (let ((map (make-sparse-keymap))) @@ -552,6 +575,7 @@ (autoload 'isearch-highlight "isearch") +;; XEmacs (defun perform-replace-next-event (event) (if isearch-highlight (let ((aborted t)) @@ -575,8 +599,8 @@ (or map (setq map query-replace-map)) (let* ((event (make-event)) (nocasify (not (and case-fold-search case-replace - (string-equal from-string - (downcase from-string))))) + (string-equal from-string + (downcase from-string))))) (literal (not regexp-flag)) (search-function (if regexp-flag 're-search-forward 'search-forward)) (search-string from-string) @@ -609,186 +633,195 @@ "\\b"))) (push-mark) (undo-boundary) - ;; Loop finding occurrences that perhaps should be replaced. - (while (and keep-going - (not (eobp)) - (let ((case-fold-search qr-case-fold-search)) - (funcall search-function search-string nil t)) - ;; If the search string matches immediately after - ;; the previous match, but it did not match there - ;; before the replacement was done, ignore the match. - (if (or (eq lastrepl (point)) - (and regexp-flag - (eq lastrepl (match-beginning 0)) - (not match-again))) + (unwind-protect + ;; Loop finding occurrences that perhaps should be replaced. + (while (and keep-going + (not (eobp)) + (let ((case-fold-search qr-case-fold-search)) + (funcall search-function search-string nil t)) + ;; If the search string matches immediately after + ;; the previous match, but it did not match there + ;; before the replacement was done, ignore the match. + (if (or (eq lastrepl (point)) + (and regexp-flag + (eq lastrepl (match-beginning 0)) + (not match-again))) + (if (eobp) + nil + ;; Don't replace the null string + ;; right after end of previous replacement. + (forward-char 1) + (let ((case-fold-search qr-case-fold-search)) + (funcall search-function search-string nil t))) + t)) - (if (eobp) - nil - ;; Don't replace the null string - ;; right after end of previous replacement. - (forward-char 1) - (let ((case-fold-search qr-case-fold-search)) - (funcall search-function search-string nil t))) - t)) - ;; Save the data associated with the real match. - (setq real-match-data (match-data)) - - ;; Before we make the replacement, decide whether the search string - ;; can match again just after this match. - (if regexp-flag - (progn - (setq match-again (looking-at search-string)) - (store-match-data real-match-data))) + ;; Save the data associated with the real match. + (setq real-match-data (match-data)) - ;; If time for a change, advance to next replacement string. - (if (and (listp replacements) - (= next-rotate-count replace-count)) - (progn - (setq next-rotate-count - (+ next-rotate-count repeat-count)) - (setq next-replacement (nth replacement-index replacements)) - (setq replacement-index (% (1+ replacement-index) (length replacements))))) - (if (not query-flag) - (progn - (store-match-data real-match-data) - (replace-match next-replacement nocasify literal) - (setq replace-count (1+ replace-count))) - (undo-boundary) - (let ((help-form - '(concat (format "Query replacing %s%s with %s.\n\n" - (if regexp-flag (gettext "regexp ") "") - from-string next-replacement) - (substitute-command-keys query-replace-help))) - (done nil) - (replaced nil) - def) - ;; Loop reading commands until one of them sets done, - ;; which means it has finished handling this occurrence. - (while (not done) - ;; Don't fill up the message log - ;; with a bunch of identical messages. - (display-message 'prompt - (format message from-string next-replacement)) - (perform-replace-next-event event) - (setq def (lookup-key map (vector event))) - ;; Restore the match data while we process the command. - (store-match-data real-match-data) - (cond ((eq def 'help) - (with-output-to-temp-buffer (gettext "*Help*") - (princ (concat - (format "Query replacing %s%s with %s.\n\n" - (if regexp-flag "regexp " "") - from-string next-replacement) - (substitute-command-keys - query-replace-help))) + ;; Before we make the replacement, decide whether the search string + ;; can match again just after this match. + (if regexp-flag + (progn + (setq match-again (looking-at search-string)) + ;; XEmacs addition + (store-match-data real-match-data))) + ;; If time for a change, advance to next replacement string. + (if (and (listp replacements) + (= next-rotate-count replace-count)) + (progn + (setq next-rotate-count + (+ next-rotate-count repeat-count)) + (setq next-replacement (nth replacement-index replacements)) + (setq replacement-index (% (1+ replacement-index) (length replacements))))) + (if (not query-flag) + (progn + (store-match-data real-match-data) + (replace-match next-replacement nocasify literal) + (setq replace-count (1+ replace-count))) + (undo-boundary) + (let ((help-form + '(concat (format "Query replacing %s%s with %s.\n\n" + (if regexp-flag (gettext "regexp ") "") + from-string next-replacement) + (substitute-command-keys query-replace-help))) + done replaced def) + ;; Loop reading commands until one of them sets done, + ;; which means it has finished handling this occurrence. + (while (not done) + ;; Don't fill up the message log + ;; with a bunch of identical messages. + ;; XEmacs change + (display-message 'prompt + (format message from-string next-replacement)) + (perform-replace-next-event event) + (setq def (lookup-key map (vector event))) + ;; Restore the match data while we process the command. + (store-match-data real-match-data) + (cond ((eq def 'help) + (with-output-to-temp-buffer (gettext "*Help*") + (princ (concat + (format "Query replacing %s%s with %s.\n\n" + (if regexp-flag "regexp " "") + from-string next-replacement) + (substitute-command-keys + query-replace-help))) (save-excursion (set-buffer standard-output) (help-mode)))) - ((eq def 'exit) - (setq keep-going nil) - (setq done t)) - ((eq def 'backup) - (if stack - (let ((elt (car stack))) - (goto-char (car elt)) - (setq replaced (eq t (cdr elt))) - (or replaced - (store-match-data (cdr elt))) - (setq stack (cdr stack))) - (progn + ((eq def 'exit) + (setq keep-going nil) + (setq done t)) + ((eq def 'backup) + (if stack + (let ((elt (car stack))) + (goto-char (car elt)) + (setq replaced (eq t (cdr elt))) + (or replaced + (store-match-data (cdr elt))) + (setq stack (cdr stack))) (message "No previous match") (ding 'no-terminate) - (sit-for 1)))) - ((eq def 'act) - (or replaced - (replace-match next-replacement nocasify literal)) - (setq done t replaced t)) - ((eq def 'act-and-exit) - (or replaced - (replace-match next-replacement nocasify literal)) - (setq keep-going nil) - (setq done t replaced t)) - ((eq def 'act-and-show) - (if (not replaced) - (progn - (replace-match next-replacement nocasify literal) - (setq replaced t)))) - ((eq def 'automatic) - (or replaced - (replace-match next-replacement nocasify literal)) - (setq done t query-flag nil replaced t)) - ((eq def 'skip) - (setq done t)) - ((eq def 'recenter) - (recenter nil)) - ((eq def 'edit) - (store-match-data - (prog1 (match-data) - (save-excursion (recursive-edit)))) - ;; Before we make the replacement, - ;; decide whether the search string - ;; can match again just after this match. - (if regexp-flag - (setq match-again (looking-at search-string)))) - ((eq def 'delete-and-edit) - (delete-region (match-beginning 0) (match-end 0)) - (store-match-data (prog1 (match-data) - (save-excursion (recursive-edit)))) - (setq replaced t)) - ;; Note: we do not need to treat `exit-prefix' - ;; specially here, since we reread - ;; any unrecognized character. - (t - (setq this-command 'mode-exited) - (setq keep-going nil) - (setq unread-command-events - (cons event unread-command-events)) - (setq done t)))) - ;; Record previous position for ^ when we move on. - ;; Change markers to numbers in the match data - ;; since lots of markers slow down editing. - (setq stack - (cons (cons (point) - (or replaced - (mapcar - #'(lambda (elt) - (if (markerp elt) - (prog1 (marker-position elt) - (set-marker elt nil)) - elt)) - (match-data)))) - stack)) - (if replaced (setq replace-count (1+ replace-count))))) - (setq lastrepl (point))) + (sit-for 1))) + ((eq def 'act) + (or replaced + (replace-match next-replacement nocasify literal)) + (setq done t replaced t)) + ((eq def 'act-and-exit) + (or replaced + (replace-match next-replacement nocasify literal)) + (setq keep-going nil) + (setq done t replaced t)) + ((eq def 'act-and-show) + (if (not replaced) + (progn + (replace-match next-replacement nocasify literal) + (setq replaced t)))) + ((eq def 'automatic) + (or replaced + (replace-match next-replacement nocasify literal)) + (setq done t query-flag nil replaced t)) + ((eq def 'skip) + (setq done t)) + ((eq def 'recenter) + (recenter nil)) + ((eq def 'edit) + (store-match-data + (prog1 (match-data) + (save-excursion (recursive-edit)))) + ;; Before we make the replacement, + ;; decide whether the search string + ;; can match again just after this match. + (if regexp-flag + (setq match-again (looking-at search-string)))) + ((eq def 'delete-and-edit) + (delete-region (match-beginning 0) (match-end 0)) + (store-match-data (prog1 (match-data) + (save-excursion (recursive-edit)))) + (setq replaced t)) + ;; Note: we do not need to treat `exit-prefix' + ;; specially here, since we reread + ;; any unrecognized character. + (t + (setq this-command 'mode-exited) + (setq keep-going nil) + (setq unread-command-events + (cons event unread-command-events)) + (setq done t)))) + ;; Record previous position for ^ when we move on. + ;; Change markers to numbers in the match data + ;; since lots of markers slow down editing. + (setq stack + (cons (cons (point) + (or replaced + (mapcar + #'(lambda (elt) + (if (markerp elt) + (prog1 (marker-position elt) + (set-marker elt nil)) + elt)) + (match-data)))) + stack)) + (if replaced (setq replace-count (1+ replace-count))))) + (setq lastrepl (point))) + (replace-dehighlight)) (or unread-command-events (message "Replaced %d occurrence%s" replace-count (if (= replace-count 1) "" "s"))) (and keep-going stack))) -; FSF 19.30 original: -; (defun match-string (num &optional string) -; "Return string of text matched by last search. -; NUM specifies which parenthesized expression in the last regexp. -; Value is nil if NUMth pair didn't match, or there were less than NUM pairs. -; Zero means the entire text matched by the whole regexp or whole string. -; STRING should be given if the last search was by `string-match' on STRING." -; (if (match-beginning num) -; (if string -; (substring string (match-beginning num) (match-end num)) -; (buffer-substring (match-beginning num) (match-end num))))) +(defvar query-replace-highlight nil + "*Non-nil means to highlight words during query replacement.") + +(defvar replace-overlay nil) + +(defun replace-dehighlight () + (and replace-overlay + (progn + (delete-overlay replace-overlay) + (setq replace-overlay nil)))) -;; #### - this could stand to be in C... -(defmacro match-string (n &optional string) - "Returns the Nth subexpression matched by the last regular expression -search. The second argument, STRING, must be specified if the last -regular expression search was done with `string-match'." - ;; #### - note that match-beginning is byte coded, so it's more efficient - ;; to just call it twice than it is to let-bind its return value... --Stig - `(and (match-beginning ,n) - ,(if string - `(substring ,string (match-beginning ,n) (match-end ,n)) - `(buffer-substring (match-beginning ,n) (match-end ,n))))) +(defun replace-highlight (start end) + (and query-replace-highlight + (progn + (or replace-overlay + (progn + (setq replace-overlay (make-overlay start end)) + (overlay-put replace-overlay 'face + (if (internal-find-face 'query-replace) + 'query-replace 'region)))) + (move-overlay replace-overlay start end (current-buffer))))) + +(defun match-string (num &optional string) + "Return string of text matched by last search. +NUM specifies which parenthesized expression in the last regexp. + Value is nil if NUMth pair didn't match, or there were less than NUM pairs. +Zero means the entire text matched by the whole regexp or whole string. +STRING should be given if the last search was by `string-match' on STRING." + (if (match-beginning num) + (if string + (substring string (match-beginning num) (match-end num)) + (buffer-substring (match-beginning num) (match-end num))))) (defmacro save-match-data (&rest body) "Execute BODY forms, restoring the global value of the match data."