(defvar isearch-string "") ; The current search string.
(defvar isearch-message "") ; text-char-description version of isearch-string
+(defvar isearch-message-prefix-add nil) ; Additonal text for the message prefix
+(defvar isearch-message-suffix-add nil) ; Additonal text for the message suffix
+
(defvar isearch-success t) ; Searching is currently successful.
(defvar isearch-error nil) ; Error message for failed search.
(defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
(sit-for 1)
(isearch-update))
-(defun isearch-query-replace (&optional regexp-flag)
- "Start `query-replace' with string to replace from last search string."
- (interactive)
+(defun isearch-query-replace (&optional delimited regexp-flag)
+ "Start `query-replace' with string to replace from last search string.
+The arg DELIMITED (prefix arg if interactive), if non-nil, means replace
+only matches surrounded by word boundaries. Note that using the prefix arg
+is possible only when `isearch-allow-scroll' is non-nil, and it don't
+always provides the correct matches for `query-replace', so the preferred
+way to run word replacements from Isearch is `M-s w ... M-%'."
+ (interactive
+ (list current-prefix-arg))
(barf-if-buffer-read-only)
(if regexp-flag (setq isearch-regexp t))
(let ((case-fold-search isearch-case-fold-search)
;; set `search-upper-case' to nil to not call
;; `isearch-no-upper-case-p' in `perform-replace'
- (search-upper-case nil))
- (isearch-done)
+ (search-upper-case nil)
+ ;; Set `isearch-recursive-edit' to nil to prevent calling
+ ;; `exit-recursive-edit' in `isearch-done' that terminates
+ ;; the execution of this command when it is non-nil.
+ ;; We call `exit-recursive-edit' explicitly at the end below.
+ (isearch-recursive-edit nil))
+ (isearch-done nil t)
(isearch-clean-overlays)
(if (and isearch-other-end
(< isearch-other-end (point))
isearch-string
(query-replace-read-to
isearch-string
- (if isearch-regexp "Query replace regexp" "Query replace")
+ (concat "Query replace"
+ (if (or delimited isearch-word) " word" "")
+ (if isearch-regexp " regexp" "")
+ (if (and transient-mark-mode mark-active) " in region" ""))
isearch-regexp)
- t isearch-regexp isearch-word nil nil
+ t isearch-regexp (or delimited isearch-word) nil nil
(if (and transient-mark-mode mark-active) (region-beginning))
- (if (and transient-mark-mode mark-active) (region-end)))))
+ (if (and transient-mark-mode mark-active) (region-end))))
+ (and isearch-recursive-edit (exit-recursive-edit)))
-(defun isearch-query-replace-regexp ()
- "Start `query-replace-regexp' with string to replace from last search string."
- (interactive)
- (isearch-query-replace t))
+(defun isearch-query-replace-regexp (&optional delimited)
+ "Start `query-replace-regexp' with string to replace from last search string.
+See `isearch-query-replace' for more information."
+ (interactive
+ (list current-prefix-arg))
+ (isearch-query-replace delimited t))
(defun isearch-occur (regexp &optional nlines)
"Run `occur' with regexp to search from the current search string.
string. NLINES has the same meaning as in `occur'."
(interactive
(list
- (if isearch-regexp isearch-string (regexp-quote isearch-string))
+ (cond
+ (isearch-word (concat "\\b" (regexp-quote isearch-string) "\\b"))
+ (isearch-regexp isearch-string)
+ (t (regexp-quote isearch-string)))
(if current-prefix-arg (prefix-numeric-value current-prefix-arg))))
(let ((case-fold-search isearch-case-fold-search)
;; set `search-upper-case' to nil to not call
argument from the last search regexp or a quoted search string,
and reads its face argument using `hi-lock-read-face-name'."
(interactive)
- (isearch-done)
- (isearch-clean-overlays)
+ (let (
+ ;; Set `isearch-recursive-edit' to nil to prevent calling
+ ;; `exit-recursive-edit' in `isearch-done' that terminates
+ ;; the execution of this command when it is non-nil.
+ ;; We call `exit-recursive-edit' explicitly at the end below.
+ (isearch-recursive-edit nil))
+ (isearch-done nil t)
+ (isearch-clean-overlays))
(require 'hi-lock nil t)
- ;; (add-to-history 'hi-lock-regexp-history regexp)
- (let ((case-fold-search isearch-case-fold-search)
- ;; TODO: add `search-upper-case' as in `isearch-occur'
- )
- (hi-lock-face-buffer
- (hi-lock-regexp-okay
- (if isearch-regexp isearch-string (regexp-quote isearch-string)))
- (hi-lock-read-face-name))))
+ (let ((string (cond (isearch-regexp isearch-string)
+ ((if (and (eq isearch-case-fold-search t)
+ search-upper-case)
+ (isearch-no-upper-case-p
+ isearch-string isearch-regexp)
+ isearch-case-fold-search)
+ ;; Turn isearch-string into a case-insensitive
+ ;; regexp.
+ (mapconcat
+ (lambda (c)
+ (let ((s (string c)))
+ (if (string-match "[[:alpha:]]" s)
+ (format "[%s%s]" (upcase s) (downcase s))
+ (regexp-quote s))))
+ isearch-string ""))
+ (t (regexp-quote isearch-string)))))
+ (hi-lock-face-buffer string (hi-lock-read-face-name)))
+ (and isearch-recursive-edit (exit-recursive-edit)))
\f
(defun isearch-delete-char ()
(if isearch-word "word " "")
(if isearch-regexp "regexp " "")
(if multi-isearch-next-buffer-current-function "multi " "")
+ (or isearch-message-prefix-add "")
(if nonincremental "search" "I-search")
(if isearch-forward "" " backward")
(if current-input-method
(concat (if c-q-hack "^Q" "")
(if isearch-error
(concat " [" isearch-error "]")
- "")))
+ "")
+ (or isearch-message-suffix-add "")))
\f
;; Searching
(funcall isearch-search-fun-function)
(cond
(isearch-word
- (if isearch-forward 'word-search-forward 'word-search-backward))
+ ;; Use lax versions to not fail at the end of the word while the user
+ ;; adds and removes characters in the search string
+ (if (not (eq (length isearch-string)
+ (length (isearch-string-state (car isearch-cmds)))))
+ (if isearch-forward 'word-search-forward-lax 'word-search-backward-lax)
+ (if isearch-forward 'word-search-forward 'word-search-backward)))
(isearch-regexp
(if isearch-forward 're-search-forward 're-search-backward))
(t
(defun isearch-lazy-highlight-search ()
"Search ahead for the next or previous match, for lazy highlighting.
Attempt to do the search exactly the way the pending isearch would."
- (let ((case-fold-search isearch-lazy-highlight-case-fold-search)
- (isearch-regexp isearch-lazy-highlight-regexp)
- (search-spaces-regexp isearch-lazy-highlight-space-regexp))
- (condition-case nil
- (isearch-search-string
- isearch-lazy-highlight-last-string
- (if isearch-forward
- (min (or isearch-lazy-highlight-end-limit (point-max))
+ (condition-case nil
+ (let ((case-fold-search isearch-lazy-highlight-case-fold-search)
+ (isearch-regexp isearch-lazy-highlight-regexp)
+ (search-spaces-regexp isearch-lazy-highlight-space-regexp)
+ (search-invisible nil) ; don't match invisible text
+ (retry t)
+ (success nil)
+ (bound (if isearch-forward
+ (min (or isearch-lazy-highlight-end-limit (point-max))
+ (if isearch-lazy-highlight-wrapped
+ isearch-lazy-highlight-start
+ (window-end)))
+ (max (or isearch-lazy-highlight-start-limit (point-min))
(if isearch-lazy-highlight-wrapped
- isearch-lazy-highlight-start
- (window-end)))
- (max (or isearch-lazy-highlight-start-limit (point-min))
- (if isearch-lazy-highlight-wrapped
- isearch-lazy-highlight-end
- (window-start))))
- t)
- (error nil))))
+ isearch-lazy-highlight-end
+ (window-start))))))
+ ;; Use a loop like in `isearch-search'
+ (while retry
+ (setq success (isearch-search-string
+ isearch-lazy-highlight-last-string bound t))
+ (if (or (not success)
+ (funcall isearch-success-function
+ (match-beginning 0) (match-end 0)))
+ (setq retry nil)))
+ success)
+ (error nil)))
(defun isearch-lazy-highlight-update ()
"Update highlighting of other matches for current search."