;;; replace.el --- replace commands for Emacs
-;; Copyright (C) 1985-1987, 1992, 1994, 1996-1997, 2000-2012
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992, 1994, 1996-1997, 2000-2013 Free
+;; Software Foundation, Inc.
;; Maintainer: FSF
;; Package: emacs
:type 'boolean
:group 'matching)
+(defcustom replace-lax-whitespace nil
+ "Non-nil means `query-replace' matches a sequence of whitespace chars.
+When you enter a space or spaces in the strings to be replaced,
+it will match any sequence matched by the regexp `search-whitespace-regexp'."
+ :type 'boolean
+ :group 'matching
+ :version "24.3")
+
+(defcustom replace-regexp-lax-whitespace nil
+ "Non-nil means `query-replace-regexp' matches a sequence of whitespace chars.
+When you enter a space or spaces in the regexps to be replaced,
+it will match any sequence matched by the regexp `search-whitespace-regexp'."
+ :type 'boolean
+ :group 'matching
+ :version "24.3")
+
(defvar query-replace-history nil
"Default history list for query-replace commands.
See `query-replace-from-history-variable' and
(defvar query-replace-interactive nil
"Non-nil means `query-replace' uses the last search string.
That becomes the \"string to replace\".")
+(make-obsolete-variable 'query-replace-interactive
+ "use `M-n' to pull the last incremental search string
+to the minibuffer that reads the string to replace, or invoke replacements
+from Isearch by using a key sequence like `C-s C-s M-%'." "24.3")
(defcustom query-replace-from-history-variable 'query-replace-history
"History list to use for the FROM argument of `query-replace' commands.
(if query-replace-interactive
(car (if regexp-flag regexp-search-ring search-ring))
(let* ((history-add-new-input nil)
+ (prompt
+ (if query-replace-defaults
+ (format "%s (default %s -> %s): " prompt
+ (query-replace-descr (car query-replace-defaults))
+ (query-replace-descr (cdr query-replace-defaults)))
+ (format "%s: " prompt)))
(from
;; The save-excursion here is in case the user marks and copies
;; a region in order to specify the minibuffer input.
;; That should not clobber the region for the query-replace itself.
(save-excursion
- (read-from-minibuffer
- (if query-replace-defaults
- (format "%s (default %s -> %s): " prompt
- (query-replace-descr (car query-replace-defaults))
- (query-replace-descr (cdr query-replace-defaults)))
- (format "%s: " prompt))
- nil nil nil
- query-replace-from-history-variable
- nil t))))
+ (if regexp-flag
+ (read-regexp prompt nil query-replace-from-history-variable)
+ (read-from-minibuffer
+ prompt nil nil nil query-replace-from-history-variable
+ (car (if regexp-flag regexp-search-ring search-ring)) t)))))
(if (and (zerop (length from)) query-replace-defaults)
(cons (car query-replace-defaults)
(query-replace-compile-replacement
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer.
-If `query-replace-interactive' is non-nil, the last incremental search
-string is used as FROM-STRING--you don't have to specify it with the
-minibuffer.
+Use \\<minibuffer-local-map>\\[next-history-element] \
+to pull the last incremental search string to the minibuffer
+that reads FROM-STRING, or invoke replacements from
+incremental search with a key sequence like `C-s C-s M-%'
+to use its current search string as the string to replace.
Matching is independent of case if `case-fold-search' is non-nil and
FROM-STRING has no uppercase letters. Replacement transfers the case
matched is all caps, or capitalized, then its replacement is upcased
or capitalized.)
+If `replace-lax-whitespace' is non-nil, a space or spaces in the string
+to be replaced will match a sequence of whitespace chars defined by the
+regexp in `search-whitespace-regexp'.
+
Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
only matches surrounded by word boundaries.
Fourth and fifth arg START and END specify the region to operate on.
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer.
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the
-minibuffer.
+Use \\<minibuffer-local-map>\\[next-history-element] \
+to pull the last incremental search regexp to the minibuffer
+that reads REGEXP, or invoke replacements from
+incremental search with a key sequence like `C-M-s C-M-s C-M-%'
+to use its current search regexp as the regexp to replace.
Matching is independent of case if `case-fold-search' is non-nil and
REGEXP has no uppercase letters. Replacement transfers the case
all caps, or capitalized, then its replacement is upcased or
capitalized.)
+If `replace-regexp-lax-whitespace' is non-nil, a space or spaces in the regexp
+to be replaced will match a sequence of whitespace chars defined by the
+regexp in `search-whitespace-regexp'.
+
Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
only matches surrounded by word boundaries.
Fourth and fifth arg START and END specify the region to operate on.
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer.
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the
-minibuffer.
+Use \\<minibuffer-local-map>\\[next-history-element] \
+to pull the last incremental search regexp to the minibuffer
+that reads REGEXP.
Preserves case in each replacement if `case-replace' and `case-fold-search'
are non-nil and REGEXP has no uppercase letters.
+If `replace-regexp-lax-whitespace' is non-nil, a space or spaces in the regexp
+to be replaced will match a sequence of whitespace chars defined by the
+regexp in `search-whitespace-regexp'.
+
Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
only matches that are surrounded by word boundaries.
Fourth and fifth arg START and END specify the region to operate on."
+ (declare (obsolete "use the `\\,' feature of `query-replace-regexp'
+for interactive calls, and `search-forward-regexp'/`replace-match'
+for Lisp calls." "22.1"))
(interactive
(progn
- (barf-if-buffer-read-only)
- (let* ((from
- ;; Let-bind the history var to disable the "foo -> bar" default.
- ;; Maybe we shouldn't disable this default, but for now I'll
- ;; leave it off. --Stef
- (let ((query-replace-to-history-variable nil))
- (query-replace-read-from "Query replace regexp" t)))
- (to (list (read-from-minibuffer
- (format "Query replace regexp %s with eval: "
- (query-replace-descr from))
- nil nil t query-replace-to-history-variable from t))))
- ;; We make TO a list because replace-match-string-symbols requires one,
- ;; and the user might enter a single token.
- (replace-match-string-symbols to)
- (list from (car to) current-prefix-arg
- (if (and transient-mark-mode mark-active)
- (region-beginning))
- (if (and transient-mark-mode mark-active)
- (region-end))))))
+ (barf-if-buffer-read-only)
+ (let* ((from
+ ;; Let-bind the history var to disable the "foo -> bar"
+ ;; default. Maybe we shouldn't disable this default, but
+ ;; for now I'll leave it off. --Stef
+ (let ((query-replace-to-history-variable nil))
+ (query-replace-read-from "Query replace regexp" t)))
+ (to (list (read-from-minibuffer
+ (format "Query replace regexp %s with eval: "
+ (query-replace-descr from))
+ nil nil t query-replace-to-history-variable from t))))
+ ;; We make TO a list because replace-match-string-symbols requires one,
+ ;; and the user might enter a single token.
+ (replace-match-string-symbols to)
+ (list from (car to) current-prefix-arg
+ (if (and transient-mark-mode mark-active)
+ (region-beginning))
+ (if (and transient-mark-mode mark-active)
+ (region-end))))))
(perform-replace regexp (cons 'replace-eval-replacement to-expr)
t 'literal delimited nil nil start end))
-(make-obsolete 'query-replace-regexp-eval
- "for interactive use, use the special `\\,' feature of
-`query-replace-regexp' instead. Non-interactively, a loop
-using `search-forward-regexp' and `replace-match' is preferred." "22.1")
-
(defun map-query-replace-regexp (regexp to-strings &optional n start end)
"Replace some matches for REGEXP with various strings, in rotation.
The second argument TO-STRINGS contains the replacement strings, separated
Non-interactively, TO-STRINGS may be a list of replacement strings.
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the minibuffer.
+Use \\<minibuffer-local-map>\\[next-history-element] \
+to pull the last incremental search regexp to the minibuffer
+that reads REGEXP.
A prefix argument N says to use each replacement string N times
before rotating to the next.
Fourth and fifth arg START and END specify the region to operate on."
(interactive
- (let* ((from (if query-replace-interactive
- (car regexp-search-ring)
- (read-from-minibuffer "Map query replace (regexp): "
- nil nil nil
- query-replace-from-history-variable
- nil t)))
+ (let* ((from (read-regexp "Map query replace (regexp): " nil
+ query-replace-from-history-variable))
(to (read-from-minibuffer
(format "Query replace %s with (space-separated strings): "
(query-replace-descr from))
\(Preserving case means that if the string matched is all caps, or capitalized,
then its replacement is upcased or capitalized.)
+If `replace-lax-whitespace' is non-nil, a space or spaces in the string
+to be replaced will match a sequence of whitespace chars defined by the
+regexp in `search-whitespace-regexp'.
+
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer.
only matches surrounded by word boundaries.
Fourth and fifth arg START and END specify the region to operate on.
-If `query-replace-interactive' is non-nil, the last incremental search
-string is used as FROM-STRING--you don't have to specify it with the
-minibuffer.
+Use \\<minibuffer-local-map>\\[next-history-element] \
+to pull the last incremental search string to the minibuffer
+that reads FROM-STRING.
This function is usually the wrong thing to use in a Lisp program.
What you probably want is a loop like this:
Preserve case in each match if `case-replace' and `case-fold-search'
are non-nil and REGEXP has no uppercase letters.
+If `replace-regexp-lax-whitespace' is non-nil, a space or spaces in the regexp
+to be replaced will match a sequence of whitespace chars defined by the
+regexp in `search-whitespace-regexp'.
+
In Transient Mark mode, if the mark is active, operate on the contents
of the region. Otherwise, operate from point to the end of the buffer.
text, TO-STRING is actually made a list instead of a string.
Use \\[repeat-complex-command] after this command for details.
-If `query-replace-interactive' is non-nil, the last incremental search
-regexp is used as REGEXP--you don't have to specify it with the minibuffer.
+Use \\<minibuffer-local-map>\\[next-history-element] \
+to pull the last incremental search regexp to the minibuffer
+that reads REGEXP.
This function is usually the wrong thing to use in a Lisp program.
What you probably want is a loop like this:
(defvar occur-collect-regexp-history '("\\1")
"History of regexp for occur's collect operation")
-(defun read-regexp (prompt &optional default-value)
- "Read regexp as a string using the regexp history and some useful defaults.
-Prompt for a regular expression with PROMPT (without a colon and
-space) in the minibuffer. The optional argument DEFAULT-VALUE
-provides the value to display in the minibuffer prompt that is
-returned if the user just types RET.
-Values available via M-n are the string at point, the last isearch
-regexp, the last isearch string, and the last replacement regexp."
- (let* ((defaults
- (list (regexp-quote
- (or (funcall (or find-tag-default-function
- (get major-mode 'find-tag-default-function)
- 'find-tag-default))
- ""))
- (car regexp-search-ring)
- (regexp-quote (or (car search-ring) ""))
- (car (symbol-value
- query-replace-from-history-variable))))
- (defaults (delete-dups (delq nil (delete "" defaults))))
- ;; Don't add automatically the car of defaults for empty input
+(defun read-regexp (prompt &optional defaults history)
+ "Read and return a regular expression as a string.
+When PROMPT doesn't end with a colon and space, it adds a final \": \".
+If the first element of DEFAULTS is non-nil, it's added to the prompt.
+
+Optional arg DEFAULTS has the form (DEFAULT . SUGGESTIONS)
+or simply DEFAULT where DEFAULT, if non-nil, should be a string that
+is returned as the default value when the user enters empty input.
+SUGGESTIONS is a list of strings that can be inserted into
+the minibuffer using \\<minibuffer-local-map>\\[next-history-element]. \
+The values supplied in SUGGESTIONS
+are prepended to the list of standard suggestions that include
+the tag at point, the last isearch regexp, the last isearch string,
+and the last replacement regexp.
+
+Optional arg HISTORY is a symbol to use for the history list.
+If HISTORY is nil, `regexp-history' is used."
+ (let* ((default (if (consp defaults) (car defaults) defaults))
+ (suggestions (if (listp defaults) defaults (list defaults)))
+ (suggestions
+ (append
+ suggestions
+ (list
+ ;; Regexp for tag at point.
+ (let* ((tagf (or find-tag-default-function
+ (get major-mode 'find-tag-default-function)
+ 'find-tag-default))
+ (tag (funcall tagf)))
+ (cond ((not tag) "")
+ ((eq tagf 'find-tag-default)
+ (format "\\_<%s\\_>" (regexp-quote tag)))
+ (t (regexp-quote tag))))
+ (car regexp-search-ring)
+ (regexp-quote (or (car search-ring) ""))
+ (car (symbol-value query-replace-from-history-variable)))))
+ (suggestions (delete-dups (delq nil (delete "" suggestions))))
+ ;; Do not automatically add default to the history for empty input.
(history-add-new-input nil)
- (input
- (read-from-minibuffer
- (if default-value
- (format "%s (default %s): " prompt
- (query-replace-descr default-value))
- (format "%s: " prompt))
- nil nil nil 'regexp-history defaults t)))
+ (input (read-from-minibuffer
+ (cond ((string-match-p ":[ \t]*\\'" prompt)
+ prompt)
+ (default
+ (format "%s (default %s): " prompt
+ (query-replace-descr default)))
+ (t
+ (format "%s: " prompt)))
+ nil nil nil (or history 'regexp-history) suggestions t)))
(if (equal input "")
- (or default-value input)
+ ;; Return the default value when the user enters empty input.
+ (or default input)
+ ;; Otherwise, add non-empty input to the history and return input.
(prog1 input
- (add-to-history 'regexp-history input)))))
+ (add-to-history (or history 'regexp-history) input)))))
(defalias 'delete-non-matching-lines 'keep-lines)
\f
(defvar occur-menu-map
(let ((map (make-sparse-keymap)))
- (define-key map [next-error-follow-minor-mode]
- `(menu-item ,(purecopy "Auto Occurrence Display")
+ (bindings--define-key map [next-error-follow-minor-mode]
+ '(menu-item "Auto Occurrence Display"
next-error-follow-minor-mode
- :help ,(purecopy
- "Display another occurrence when moving the cursor")
+ :help "Display another occurrence when moving the cursor"
:button (:toggle . (and (boundp 'next-error-follow-minor-mode)
next-error-follow-minor-mode))))
- (define-key map [separator-1] menu-bar-separator)
- (define-key map [kill-this-buffer]
- `(menu-item ,(purecopy "Kill Occur Buffer") kill-this-buffer
- :help ,(purecopy "Kill the current *Occur* buffer")))
- (define-key map [quit-window]
- `(menu-item ,(purecopy "Quit Occur Window") quit-window
- :help ,(purecopy "Quit the current *Occur* buffer. Bury it, and maybe delete the selected frame")))
- (define-key map [revert-buffer]
- `(menu-item ,(purecopy "Revert Occur Buffer") revert-buffer
- :help ,(purecopy "Replace the text in the *Occur* buffer with the results of rerunning occur")))
- (define-key map [clone-buffer]
- `(menu-item ,(purecopy "Clone Occur Buffer") clone-buffer
- :help ,(purecopy "Create and return a twin copy of the current *Occur* buffer")))
- (define-key map [occur-rename-buffer]
- `(menu-item ,(purecopy "Rename Occur Buffer") occur-rename-buffer
- :help ,(purecopy "Rename the current *Occur* buffer to *Occur: original-buffer-name*.")))
- (define-key map [separator-2] menu-bar-separator)
- (define-key map [occur-mode-goto-occurrence-other-window]
- `(menu-item ,(purecopy "Go To Occurrence Other Window") occur-mode-goto-occurrence-other-window
- :help ,(purecopy "Go to the occurrence the current line describes, in another window")))
- (define-key map [occur-mode-goto-occurrence]
- `(menu-item ,(purecopy "Go To Occurrence") occur-mode-goto-occurrence
- :help ,(purecopy "Go to the occurrence the current line describes")))
- (define-key map [occur-mode-display-occurrence]
- `(menu-item ,(purecopy "Display Occurrence") occur-mode-display-occurrence
- :help ,(purecopy "Display in another window the occurrence the current line describes")))
- (define-key map [occur-next]
- `(menu-item ,(purecopy "Move to Next Match") occur-next
- :help ,(purecopy "Move to the Nth (default 1) next match in an Occur mode buffer")))
- (define-key map [occur-prev]
- `(menu-item ,(purecopy "Move to Previous Match") occur-prev
- :help ,(purecopy "Move to the Nth (default 1) previous match in an Occur mode buffer")))
+ (bindings--define-key map [separator-1] menu-bar-separator)
+ (bindings--define-key map [kill-this-buffer]
+ '(menu-item "Kill Occur Buffer" kill-this-buffer
+ :help "Kill the current *Occur* buffer"))
+ (bindings--define-key map [quit-window]
+ '(menu-item "Quit Occur Window" quit-window
+ :help "Quit the current *Occur* buffer. Bury it, and maybe delete the selected frame"))
+ (bindings--define-key map [revert-buffer]
+ '(menu-item "Revert Occur Buffer" revert-buffer
+ :help "Replace the text in the *Occur* buffer with the results of rerunning occur"))
+ (bindings--define-key map [clone-buffer]
+ '(menu-item "Clone Occur Buffer" clone-buffer
+ :help "Create and return a twin copy of the current *Occur* buffer"))
+ (bindings--define-key map [occur-rename-buffer]
+ '(menu-item "Rename Occur Buffer" occur-rename-buffer
+ :help "Rename the current *Occur* buffer to *Occur: original-buffer-name*."))
+ (bindings--define-key map [occur-edit-buffer]
+ '(menu-item "Edit Occur Buffer" occur-edit-mode
+ :help "Edit the *Occur* buffer and apply changes to the original buffers."))
+ (bindings--define-key map [separator-2] menu-bar-separator)
+ (bindings--define-key map [occur-mode-goto-occurrence-other-window]
+ '(menu-item "Go To Occurrence Other Window" occur-mode-goto-occurrence-other-window
+ :help "Go to the occurrence the current line describes, in another window"))
+ (bindings--define-key map [occur-mode-goto-occurrence]
+ '(menu-item "Go To Occurrence" occur-mode-goto-occurrence
+ :help "Go to the occurrence the current line describes"))
+ (bindings--define-key map [occur-mode-display-occurrence]
+ '(menu-item "Display Occurrence" occur-mode-display-occurrence
+ :help "Display in another window the occurrence the current line describes"))
+ (bindings--define-key map [occur-next]
+ '(menu-item "Move to Next Match" occur-next
+ :help "Move to the Nth (default 1) next match in an Occur mode buffer"))
+ (bindings--define-key map [occur-prev]
+ '(menu-item "Move to Previous Match" occur-prev
+ :help "Move to the Nth (default 1) previous match in an Occur mode buffer"))
map)
"Menu keymap for `occur-mode'.")
(define-key map "r" 'occur-rename-buffer)
(define-key map "c" 'clone-buffer)
(define-key map "\C-c\C-f" 'next-error-follow-minor-mode)
- (define-key map [menu-bar occur] (cons (purecopy "Occur") occur-menu-map))
+ (bindings--define-key map [menu-bar occur] (cons "Occur" occur-menu-map))
map)
"Keymap for `occur-mode'.")
(define-key map "\C-c\C-c" 'occur-cease-edit)
(define-key map "\C-o" 'occur-mode-display-occurrence)
(define-key map "\C-c\C-f" 'next-error-follow-minor-mode)
- (define-key map [menu-bar occur] (cons (purecopy "Occur") occur-menu-map))
+ (bindings--define-key map [menu-bar occur] (cons "Occur" occur-menu-map))
map)
"Keymap for `occur-edit-mode'.")
(line-number-at-pos (window-start))))
(readonly (with-current-buffer buf buffer-read-only))
(win (or (get-buffer-window buf)
- (display-buffer buf t)))
+ (display-buffer buf
+ '(nil (inhibit-same-window . t)
+ (inhibit-switch-frame . t)))))
(line-end (line-end-position))
(text (save-excursion
(goto-char (next-single-property-change
"\\&"
;; Get the regexp for collection pattern.
(let ((default (car occur-collect-regexp-history)))
- (read-string
+ (read-regexp
(format "Regexp to collect (default %s): " default)
- nil 'occur-collect-regexp-history default)))
+ default 'occur-collect-regexp-history)))
;; Otherwise normal occur takes numerical prefix argument.
(when current-prefix-arg
(prefix-numeric-value current-prefix-arg))))))
For example, providing \"defun\\s +\\(\\S +\\)\" for REGEXP and
\"\\1\" for NLINES collects all the function names in a lisp
program. When there is no parenthesized subexpressions in REGEXP
-the entire match is collected. In any case the searched buffers
-are not modified."
+the entire match is collected. In any case the searched buffer
+is not modified."
(interactive (occur-read-primary-args))
(occur-1 regexp nlines (list (current-buffer))))
(cons
(let* ((default (car regexp-history))
(input
- (read-from-minibuffer
+ (read-regexp
(if current-prefix-arg
"List lines in buffers whose names match regexp: "
- "List lines in buffers whose filenames match regexp: ")
- nil
- nil
- nil
- 'regexp-history)))
+ "List lines in buffers whose filenames match regexp: "))))
(if (equal input "")
default
input))
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 screen, redisplay, and offer same replacement again,
-! to replace all remaining matches with no more questions,
+! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
-E to edit the replacement string"
+E to edit the replacement string.
+In multi-buffer replacements type `Y' to replace all remaining
+matches in all remaining buffers with no more questions,
+`N' to skip to the next buffer without replacing remaining matches
+in the current buffer."
"Help message while in `query-replace'.")
(defvar query-replace-map
(define-key map "?" 'help)
(define-key map "\C-g" 'quit)
(define-key map "\C-]" 'quit)
- (define-key map "\e" 'exit-prefix)
+ (define-key map "\C-v" 'scroll-up)
+ (define-key map "\M-v" 'scroll-down)
+ (define-key map [next] 'scroll-up)
+ (define-key map [prior] 'scroll-down)
+ (define-key map [?\C-\M-v] 'scroll-other-window)
+ (define-key map [M-next] 'scroll-other-window)
+ (define-key map [?\C-\M-\S-v] 'scroll-other-window-down)
+ (define-key map [M-prior] 'scroll-other-window-down)
+ ;; Binding ESC would prohibit the M-v binding. Instead, callers
+ ;; should check for ESC specially.
+ ;; (define-key map "\e" 'exit-prefix)
(define-key map [escape] 'exit-prefix)
map)
- "Keymap that defines the responses to questions in `query-replace'.
+ "Keymap of responses to questions posed by commands like `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'.")
+`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
+`scroll-down', `scroll-other-window', `scroll-other-window-down',
+`edit', `edit-replacement', `delete-and-edit', `automatic',
+`backup', `quit', and `help'.
+
+This keymap is used by `y-or-n-p' as well as `query-replace'.")
(defvar multi-query-replace-map
(let ((map (make-sparse-keymap)))
(replace-match newtext fixedcase literal)
noedit)
-(defvar replace-search-function 'search-forward
+(defvar replace-search-function nil
"Function to use when searching for strings to replace.
It is used by `query-replace' and `replace-string', and is called
with three arguments, as if it were `search-forward'.")
-(defvar replace-re-search-function 're-search-forward
+(defvar replace-re-search-function nil
"Function to use when searching for regexps to replace.
It is used by `query-replace-regexp', `replace-regexp',
`query-replace-regexp-eval', and `map-query-replace-regexp'.
case-fold-search))
(nocasify (not (and case-replace case-fold-search)))
(literal (or (not regexp-flag) (eq regexp-flag 'literal)))
- (search-function
- (if regexp-flag
- replace-re-search-function
- replace-search-function))
(search-string from-string)
(real-match-data nil) ; The match data for the current match.
(next-replacement nil)
(vector repeat-count repeat-count
replacements replacements)))))
- (if delimited-flag
- (setq search-function 're-search-forward
- search-string (concat "\\b"
- (if regexp-flag from-string
- (regexp-quote from-string))
- "\\b")))
(when query-replace-lazy-highlight
(setq isearch-lazy-highlight-last-string nil))
;; Loop finding occurrences that perhaps should be replaced.
(while (and keep-going
(not (or (eobp) (and limit (>= (point) limit))))
- ;; Use the next match if it is already known;
- ;; otherwise, search for a match after moving forward
- ;; one char if progress is required.
- (setq real-match-data
- (cond ((consp match-again)
- (goto-char (nth 1 match-again))
- (replace-match-data
- t real-match-data match-again))
- ;; MATCH-AGAIN non-nil means accept an
- ;; adjacent match.
- (match-again
- (and
- (funcall search-function search-string
- limit t)
- ;; For speed, use only integers and
- ;; reuse the list used last time.
- (replace-match-data t real-match-data)))
- ((and (< (1+ (point)) (point-max))
- (or (null limit)
- (< (1+ (point)) limit)))
- ;; If not accepting adjacent matches,
- ;; move one char to the right before
- ;; searching again. Undo the motion
- ;; if the search fails.
- (let ((opoint (point)))
- (forward-char 1)
- (if (funcall
- search-function search-string
- limit t)
- (replace-match-data
- t real-match-data)
- (goto-char opoint)
- nil))))))
+ ;; Let-bind global isearch-* variables to values used
+ ;; to search the next replacement. These let-bindings
+ ;; should be effective both at the time of calling
+ ;; `isearch-search-fun-default' and also at the
+ ;; time of funcalling `search-function'.
+ ;; These isearch-* bindings can't be placed higher
+ ;; outside of this loop because then another I-search
+ ;; used after `recursive-edit' might override them.
+ (let* ((isearch-regexp regexp-flag)
+ (isearch-word delimited-flag)
+ (isearch-lax-whitespace
+ replace-lax-whitespace)
+ (isearch-regexp-lax-whitespace
+ replace-regexp-lax-whitespace)
+ (isearch-case-fold-search case-fold-search)
+ (isearch-adjusted nil)
+ (isearch-nonincremental t) ; don't use lax word mode
+ (isearch-forward t)
+ (search-function
+ (or (if regexp-flag
+ replace-re-search-function
+ replace-search-function)
+ (isearch-search-fun-default))))
+ ;; Use the next match if it is already known;
+ ;; otherwise, search for a match after moving forward
+ ;; one char if progress is required.
+ (setq real-match-data
+ (cond ((consp match-again)
+ (goto-char (nth 1 match-again))
+ (replace-match-data
+ t real-match-data match-again))
+ ;; MATCH-AGAIN non-nil means accept an
+ ;; adjacent match.
+ (match-again
+ (and
+ (funcall search-function search-string
+ limit t)
+ ;; For speed, use only integers and
+ ;; reuse the list used last time.
+ (replace-match-data t real-match-data)))
+ ((and (< (1+ (point)) (point-max))
+ (or (null limit)
+ (< (1+ (point)) limit)))
+ ;; If not accepting adjacent matches,
+ ;; move one char to the right before
+ ;; searching again. Undo the motion
+ ;; if the search fails.
+ (let ((opoint (point)))
+ (forward-char 1)
+ (if (funcall
+ search-function search-string
+ limit t)
+ (replace-match-data
+ t real-match-data)
+ (goto-char opoint)
+ nil)))))))
;; Record whether the match is nonempty, to avoid an infinite loop
;; repeatedly matching the same empty string.
(replace-highlight
(nth 0 real-match-data) (nth 1 real-match-data)
start end search-string
- (or delimited-flag regexp-flag) case-fold-search))
+ regexp-flag delimited-flag case-fold-search))
(setq noedit
(replace-match-maybe-edit
next-replacement nocasify literal
(replace-highlight
(match-beginning 0) (match-end 0)
start end search-string
- (or delimited-flag regexp-flag) case-fold-search)
+ regexp-flag delimited-flag case-fold-search)
;; Bind message-log-max so we don't fill up the message log
;; with a bunch of identical messages.
(let ((message-log-max nil)
(if (= replace-count 1) "" "s")))
(or (and keep-going stack) multi-buffer)))
-(defvar isearch-error)
-(defvar isearch-forward)
-(defvar isearch-case-fold-search)
-(defvar isearch-string)
-
(defvar replace-overlay nil)
(defun replace-highlight (match-beg match-end range-beg range-end
- string regexp case-fold)
+ search-string regexp-flag delimited-flag
+ case-fold-search)
(if query-replace-highlight
(if replace-overlay
(move-overlay replace-overlay match-beg match-end (current-buffer))
(overlay-put replace-overlay 'priority 1001) ;higher than lazy overlays
(overlay-put replace-overlay 'face 'query-replace)))
(if query-replace-lazy-highlight
- (let ((isearch-string string)
- (isearch-regexp regexp)
- (search-whitespace-regexp nil)
- (isearch-case-fold-search case-fold)
+ (let ((isearch-string search-string)
+ (isearch-regexp regexp-flag)
+ (isearch-word delimited-flag)
+ (isearch-lax-whitespace
+ replace-lax-whitespace)
+ (isearch-regexp-lax-whitespace
+ replace-regexp-lax-whitespace)
+ (isearch-case-fold-search case-fold-search)
(isearch-forward t)
+ (isearch-other-end match-beg)
(isearch-error nil))
- ;; Set isearch-word to nil because word-replace is regexp-based,
- ;; so `isearch-search-fun' should not use `word-search-forward'.
- (if (and isearch-word isearch-regexp) (setq isearch-word nil))
(isearch-lazy-highlight-new-loop range-beg range-end))))
(defun replace-dehighlight ()