;;; isearch.el --- incremental search minor mode
;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
-;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
;; Maintainer: FSF
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
(defvar isearch-mode-end-hook-quit nil
"Non-nil while running `isearch-mode-end-hook' if user quit the search.")
+(defvar isearch-message-function nil
+ "Function to call to display the search prompt.
+If nil, use `isearch-message'.")
+
(defvar isearch-wrap-function nil
"Function to call to wrap the search when search is failed.
If nil, move point to the beginning of the buffer for a forward search,
string and search for it.
Type \\[isearch-yank-line] to yank rest of line onto end of search string\
and search for it.
-Type \\[isearch-yank-kill] to yank last killed text onto end of search string\
- and search for it.
+Type \\[isearch-yank-kill] to yank the last string of killed text.
Type \\[isearch-quote-char] to quote control character to search for it.
\\[isearch-abort] while searching or when search has failed cancels input\
back to what has
(null executing-kbd-macro))
(progn
(if (not (input-pending-p))
- (isearch-message))
+ (if isearch-message-function
+ (funcall isearch-message-function)
+ (isearch-message)))
(if (and isearch-slow-terminal-mode
(not (or isearch-small-window
(pos-visible-in-window-p))))
(lazy-highlight-cleanup lazy-highlight-cleanup)
(let ((found-start (window-start (selected-window)))
(found-point (point)))
- (if isearch-window-configuration
- (set-window-configuration isearch-window-configuration))
-
- (if isearch-small-window
- (goto-char found-point)
- ;; Exiting the save-window-excursion clobbers window-start; restore it.
- (set-window-start (selected-window) found-start t)))
+ (when isearch-window-configuration
+ (set-window-configuration isearch-window-configuration)
+ (if isearch-small-window
+ (goto-char found-point)
+ ;; set-window-configuration clobbers window-start; restore it.
+ ;; This has an annoying side effect of clearing the last_modiff
+ ;; field of the window, which can cause unwanted scrolling,
+ ;; so don't do it unless truly necessary.
+ (set-window-start (selected-window) found-start t))))
(setq isearch-mode nil)
(if isearch-input-method-local-p
(run-hooks 'isearch-mode-end-hook))
;; If there was movement, mark the starting position.
- ;; Maybe should test difference between and set mark iff > threshold.
+ ;; Maybe should test difference between and set mark only if > threshold.
(if (/= (point) isearch-opoint)
(or (and transient-mark-mode mark-active)
(progn
isearch-original-minibuffer-message-timeout)
(isearch-original-minibuffer-message-timeout
isearch-original-minibuffer-message-timeout)
- )
+ old-point old-other-end)
;; Actually terminate isearching until editing is done.
;; This is so that the user can do anything without failure,
(isearch-done t t)
(exit nil)) ; was recursive editing
+ ;; Save old point and isearch-other-end before reading from minibuffer
+ ;; that can change their values.
+ (setq old-point (point) old-other-end isearch-other-end)
+
(isearch-message) ;; for read-char
(unwind-protect
(let* (;; Why does following read-char echo?
isearch-new-message
(mapconcat 'isearch-text-char-description
isearch-new-string "")))
+
+ ;; Set point at the start (end) of old match if forward (backward),
+ ;; so after exiting minibuffer isearch resumes at the start (end)
+ ;; of this match and can find it again.
+ (if (and old-other-end (eq old-point (point))
+ (eq isearch-forward isearch-new-forward))
+ (goto-char old-other-end))
+
;; Always resume isearching by restarting it.
(isearch-mode isearch-forward
isearch-regexp
;; Reinvoke the pending search.
(isearch-search)
+ (isearch-push-state)
(isearch-update)
(if isearch-nonincremental
(progn
(ding)
(setq isearch-string (substring isearch-string 0 (- (or arg 1)))
isearch-message (mapconcat 'isearch-text-char-description
- isearch-string "")
- ;; Don't move cursor in reverse search.
- isearch-yank-flag t))
- (isearch-search-and-update))
+ isearch-string "")))
+ ;; Use the isearch-other-end as new starting point to be able
+ ;; to find the remaining part of the search string again.
+ (if isearch-other-end (goto-char isearch-other-end))
+ (isearch-search)
+ (isearch-push-state)
+ (isearch-update))
(defun isearch-yank-string (string)
"Pull STRING into search string."
(isearch-back-into-window (eq ab-bel 'above) isearch-point)
(goto-char isearch-point)))
(isearch-update))
+ ;; A mouse click on the isearch message starts editing the search string
+ ((and (eq (car-safe main-event) 'down-mouse-1)
+ (window-minibuffer-p (posn-window (event-start main-event))))
+ ;; Swallow the up-event.
+ (read-event)
+ (isearch-edit-string))
(search-exit-option
(let (window)
(isearch-unread-key-sequence keylist)
(if isearch-forward (< pos2 pos1) (> pos2 pos1))))
(setq pos1 pos2)
(set-match-data match-data)))))
- (if pos1
- (goto-char pos1))
+ (when pos1
+ ;; When using multiple buffers isearch, switch to the new buffer here,
+ ;; because `save-excursion' above doesn't allow doing it inside funcall.
+ (if (and isearch-buffers-next-buffer-function
+ (buffer-live-p isearch-buffers-current-buffer))
+ (switch-to-buffer isearch-buffers-current-buffer))
+ (goto-char pos1))
pos1))
(defun isearch-search ()
;; Do the search with the current search string.
- (isearch-message nil t)
+ (if isearch-message-function
+ (funcall isearch-message-function nil t)
+ (isearch-message nil t))
(if (and (eq isearch-case-fold-search t) search-upper-case)
(setq isearch-case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp)))
(setq found t))
(setq quote-flag nil)))
(setq i (1+ i)))
- (not found)))
+ (not (or found
+ ;; Even if there's no uppercase char, we want to detect the use
+ ;; of [:upper:] or [:lower:] char-class, which indicates
+ ;; clearly that the user cares about case distinction.
+ (and regexp-flag (string-match "\\[:\\(upp\\|low\\)er:]" string)
+ (condition-case err
+ (progn
+ (string-match (substring string 0 (match-beginning 0))
+ "")
+ nil)
+ (invalid-regexp
+ (equal "Unmatched [ or [^" (cadr err)))))))))
;; Portability functions to support various Emacs versions.
;; - the direction of the current search is expected to be given by
;; `isearch-forward';
;; - the variable `isearch-error' is expected to be true
-;; iff `isearch-string' is an invalid regexp.
+;; only if `isearch-string' is an invalid regexp.
(defvar isearch-lazy-highlight-overlays nil)
(defvar isearch-lazy-highlight-wrapped nil)
(defvar isearch-lazy-highlight-window-end nil)
(defvar isearch-lazy-highlight-case-fold-search nil)
(defvar isearch-lazy-highlight-regexp nil)
+(defvar isearch-lazy-highlight-space-regexp nil)
(defun lazy-highlight-cleanup (&optional force)
"Stop lazy highlighting and remove extra highlighting from current buffer.
isearch-lazy-highlight-last-string isearch-string
isearch-lazy-highlight-case-fold-search isearch-case-fold-search
isearch-lazy-highlight-regexp isearch-regexp
- isearch-lazy-highlight-wrapped nil)
+ isearch-lazy-highlight-wrapped nil
+ isearch-lazy-highlight-space-regexp search-whitespace-regexp)
(unless (equal isearch-string "")
(setq isearch-lazy-highlight-timer
(run-with-idle-timer lazy-highlight-initial-delay nil
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 search-whitespace-regexp))
+ (search-spaces-regexp isearch-lazy-highlight-space-regexp))
(condition-case nil
(isearch-search-string
isearch-lazy-highlight-last-string
(run-at-time lazy-highlight-interval nil
'isearch-lazy-highlight-update)))))))))
-(defun isearch-resume (search regexp word forward message case-fold)
+(defun isearch-resume (string regexp word forward message case-fold)
"Resume an incremental search.
-SEARCH is the string or regexp searched for.
+STRING is the string or regexp searched for.
REGEXP non-nil means the resumed search was a regexp search.
WORD non-nil means resume a word search.
FORWARD non-nil means resume a forward search.
MESSAGE is the echo-area message recorded for the search resumed.
CASE-FOLD non-nil means the search was case-insensitive."
(isearch-mode forward regexp nil nil word)
- (setq isearch-string search
+ (setq isearch-string string
isearch-message message
isearch-case-fold-search case-fold)
- (isearch-search))
+ (isearch-search)
+ (isearch-update))
;; arch-tag: 74850515-f7d8-43a6-8a2c-ca90a4c1e675
;;; isearch.el ends here