;;; isearch.el --- incremental search minor mode
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 2001
+;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 01, 2003
;; Free Software Foundation, Inc.
;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
;; Added word search option to isearch-edit-string.
;; Renamed isearch-quit to isearch-abort.
;; Numerous changes to comments and doc strings.
-;;
+;;
;; Revision 1.3 92/06/29 13:10:08 liberte
;; Moved modal isearch-mode handling into isearch-mode.
;; Got rid of buffer-local isearch variables.
If the value is `open', if the text matched is made invisible by
an overlay having an `invisible' property and that overlay has a property
`isearch-open-invisible', then incremental search will show the contents.
-\(This applies when using `outline.el' and `hideshow.el'.)"
+\(This applies when using `outline.el' and `hideshow.el'.)
+See also `reveal-mode' if you want overlays to automatically be opened
+whenever point is in one of them."
:type '(choice (const :tag "Match hidden text" t)
(const :tag "Open overlays" open)
(const :tag "Don't match hidden text" nil))
This variable makes a difference when `search-invisible' is set to `open'.
It means that after search makes some invisible text visible
to show the match, it makes the text invisible again when the match moves.
-Ordinarily the text becomes invisible again at the end of the search."
- :type 'boolean
+Ordinarily the text becomes invisible again at the end of the search."
+ :type 'boolean
:group 'isearch)
(defcustom isearch-resume-enabled t
;; Make function keys, etc, exit the search.
(define-key map [t] 'isearch-other-control-char)
;; Control chars, by default, end isearch mode transparently.
- ;; We need these explicit definitions because, in a dense keymap,
+ ;; We need these explicit definitions because, in a dense keymap,
;; the binding for t does not affect characters.
;; We use a dense keymap to save space.
(while (< i ?\ )
(error "Inconsistency in isearch.el"))
(define-key map "\e\e\e" 'isearch-cancel)
(define-key map [escape escape escape] 'isearch-cancel)
-
+
(define-key map "\C-q" 'isearch-quote-char)
(define-key map "\r" 'isearch-exit)
(define-key map "\t" 'isearch-printing-char)
(define-key map " " 'isearch-whitespace-chars)
(define-key map [?\S-\ ] 'isearch-whitespace-chars)
-
+
(define-key map "\C-w" 'isearch-yank-word-or-char)
(define-key map "\C-y" 'isearch-yank-line)
(defvar isearch-forward nil) ; Searching in the forward direction.
(defvar isearch-regexp nil) ; Searching for a regexp.
(defvar isearch-word nil) ; Searching for words.
+(defvar isearch-hidden nil) ; Non-nil if the string exists but is invisible.
(defvar isearch-cmds nil
"Stack of search status sets.
With a prefix argument, do an incremental regular expression search instead.
\\<isearch-mode-map>
As you type characters, they add to the search string and are found.
-The following non-printing keys are bound in `isearch-mode-map'.
+The following non-printing keys are bound in `isearch-mode-map'.
Type \\[isearch-delete-char] to cancel characters from end of search string.
Type \\[isearch-exit] to exit, leaving point at location found.
Type \\[isearch-complete] to complete the search string using the search ring.
If an input method is turned on in the current buffer, that input
-method is also active while you are typing a characters to search. To
+method is also active while you are typing characters to search. To
toggle the input method, type \\[isearch-toggle-input-method]. It
also toggles the input method in the current buffer.
\\[isearch-toggle-specified-input-method], and specify an input method
you want to use.
-The above keys, bound in `isearch-mode-map', are often controlled by
+The above keys, bound in `isearch-mode-map', are often controlled by
options; do M-x apropos on search-.* to find them.
Other control and meta characters terminate the search
and are then executed normally (depending on `search-exit-option').
;;(defvar isearch-commands '(isearch-forward isearch-backward
;; isearch-forward-regexp isearch-backward-regexp)
;; "List of commands for which isearch-mode does not recursive-edit.")
-
+
(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
"Start isearch minor mode. Called by `isearch-forward', etc.
(add-hook 'mouse-leave-buffer-hook 'isearch-done)
(add-hook 'kbd-macro-termination-hook 'isearch-done)
- ;; isearch-mode can be made modal (in the sense of not returning to
- ;; the calling function until searching is completed) by entering
+ ;; isearch-mode can be made modal (in the sense of not returning to
+ ;; the calling function until searching is completed) by entering
;; a recursive-edit and exiting it when done isearching.
(if recursive-edit
(let ((isearch-recursive-edit t))
(if (not (input-pending-p))
(isearch-message))
(if (and isearch-slow-terminal-mode
- (not (or isearch-small-window
+ (not (or isearch-small-window
(pos-visible-in-window-p))))
(let ((found-point (point)))
(setq isearch-small-window t)
(defun isearch-update-ring (string &optional regexp)
"Add STRING to the beginning of the search ring.
REGEXP says which ring to use."
- (if regexp
+ (if regexp
(if (or (null regexp-search-ring)
(not (string= string (car regexp-search-ring))))
(progn
- (setq regexp-search-ring
- (cons string regexp-search-ring))
+ (push string regexp-search-ring)
(if (> (length regexp-search-ring) regexp-search-ring-max)
(setcdr (nthcdr (1- search-ring-max) regexp-search-ring)
nil))))
(if (or (null search-ring)
(not (string= string (car search-ring))))
(progn
- (setq search-ring (cons string search-ring))
+ (push string search-ring)
(if (> (length search-ring) search-ring-max)
(setcdr (nthcdr (1- search-ring-max) search-ring) nil))))))
search and `search-nonincremental-instead' is non-nil, do a
nonincremental search instead via `isearch-edit-string'."
(interactive)
- (if (and search-nonincremental-instead
+ (if (and search-nonincremental-instead
(= 0 (length isearch-string)))
(let ((isearch-nonincremental t))
(isearch-edit-string)))
)
;; Actually terminate isearching until editing is done.
- ;; This is so that the user can do anything without failure,
+ ;; This is so that the user can do anything without failure,
;; like switch buffers and start another isearch, and return.
(condition-case err
(isearch-done t t)
(isearch-message) ;; for read-char
(unwind-protect
- (let* (;; Why does following read-char echo?
+ (let* (;; Why does following read-char echo?
;;(echo-keystrokes 0) ;; not needed with above message
(e (let ((cursor-in-echo-area t))
(read-event)))
(mapconcat 'isearch-text-char-description
isearch-new-string "")))
;; Always resume isearching by restarting it.
- (isearch-mode isearch-forward
- isearch-regexp
- isearch-op-fun
+ (isearch-mode isearch-forward
+ isearch-regexp
+ isearch-op-fun
nil
isearch-word)
;; Reinvoke the pending search.
(isearch-search)
(isearch-update)
- (if isearch-nonincremental
+ (if isearch-nonincremental
(progn
;; (sit-for 1) ;; needed if isearch-done does: (message "")
(isearch-done))))
(or (if isearch-regexp
(car regexp-search-ring)
(car search-ring))
- "")
+ (error "No previous search string"))
isearch-message
(mapconcat 'isearch-text-char-description
isearch-string "")
(if (and (window-minibuffer-p w)
(not (minibuffer-window-active-p w))) ; in echo area
(isearch-yank-x-selection)
- (when binding
+ (when (functionp binding)
(call-interactively binding)))))
"Pull next character or word from buffer into search string."
(interactive)
(isearch-yank-internal
- (lambda ()
+ (lambda ()
(if (or (= (char-syntax (or (char-after) 0)) ?w)
(= (char-syntax (or (char-after (1+ (point))) 0)) ?w))
(forward-word 1)
(defun isearch-yank-line ()
"Pull rest of line from buffer into search string."
(interactive)
- (isearch-yank-internal (lambda () (line-end-position))))
+ (isearch-yank-internal 'line-end-position))
(defun isearch-search-and-update ()
;; unsuccessful regexp search may become
;; successful by addition of characters which
;; make isearch-string valid
- isearch-regexp)
+ isearch-regexp
+ ;; If the string was found but was completely invisible,
+ ;; it might now be partly visible, so try again.
+ (prog1 isearch-hidden (setq isearch-hidden nil)))
;; In reverse search, adding stuff at
;; the end may cause zero or many more chars to be
;; matched, in the string following point.
(max cs isearch-barrier)
(min cs isearch-barrier)))))))
(isearch-process-search-char last-command-char))
-
+
(defun isearch-|-char ()
"If in regexp search, jump to the barrier."
;; obviously wrong for the case that a down-mouse event
;; on another window invokes this function. The event
;; will contain the window clicked on and that window's
- ;; buffer is certainaly not always in Isearch mode.
+ ;; buffer is certainly not always in Isearch mode.
;;
;; Leave the code in, but check for current buffer not
;; being in Isearch mode for now, until someone tells
"Match all whitespace chars, if in regexp mode.
If you want to search for just a space, type \\<isearch-mode-map>\\[isearch-quote-char] SPC."
(interactive)
- (if isearch-regexp
+ (if isearch-regexp
(if (and search-whitespace-regexp (not isearch-within-brackets)
(not isearch-invalid-regexp))
(isearch-process-search-string search-whitespace-regexp " ")
;; Helper for isearch-complete and isearch-complete-edit
;; Return t if completion OK, nil if no completion exists.
(let* ((ring (if isearch-regexp regexp-search-ring search-ring))
- (alist (mapcar (function (lambda (string) (list string))) ring))
(completion-ignore-case case-fold-search)
- (completion (try-completion isearch-string alist)))
+ (completion (try-completion isearch-string ring)))
(cond
((eq completion t)
;; isearch-string stays the same
(progn
(if completion-auto-help
(with-output-to-temp-buffer "*Isearch completions*"
- (display-completion-list
- (all-completions isearch-string alist))))
+ (display-completion-list
+ (all-completions isearch-string ring))))
t)
(and completion
(setq isearch-string completion))))
If there is no completion possible, say so and continue searching."
(interactive)
(if (isearch-complete1)
- (isearch-edit-string)
+ (progn (setq isearch-message
+ (mapconcat 'isearch-text-char-description
+ isearch-string ""))
+ (isearch-edit-string))
;; else
(sit-for 1)
(isearch-update)))
(defun isearch-complete-edit ()
"Same as `isearch-complete' except in the minibuffer."
(interactive)
- (setq isearch-string (buffer-string))
+ (setq isearch-string (field-string))
(if (isearch-complete1)
(progn
(delete-field)
(isearch-top-state))
(defun isearch-push-state ()
- (setq isearch-cmds
+ (setq isearch-cmds
(cons (list isearch-string isearch-message (point)
- isearch-success isearch-forward isearch-other-end
+ isearch-success isearch-forward isearch-other-end
isearch-word
isearch-invalid-regexp isearch-wrapped isearch-barrier
isearch-within-brackets isearch-case-fold-search)
;; Called when opening an overlay, and we are still in isearch.
(defun isearch-open-overlay-temporary (ov)
- (if (not (null (overlay-get ov 'isearch-open-invisible-temporary)))
+ (if (not (null (overlay-get ov 'isearch-open-invisible-temporary)))
;; Some modes would want to open the overlays temporary during
;; isearch in their own way, they should set the
;; `isearch-open-invisible-temporary' to a function doing this.
(defun isearch-range-invisible (beg end)
"Return t if all the text from BEG to END is invisible."
- (and (/= beg end)
- ;; Check that invisibility runs up to END.
- (save-excursion
- (goto-char beg)
- (let (
- ;; can-be-opened keeps track if we can open some overlays.
- (can-be-opened (eq search-invisible 'open))
- ;; the list of overlays that could be opened
- (crt-overlays nil))
- (when (and can-be-opened isearch-hide-immediately)
- (isearch-close-unnecessary-overlays beg end))
- ;; If the following character is currently invisible,
- ;; skip all characters with that same `invisible' property value.
- ;; Do that over and over.
- (while (and (< (point) end)
- (let ((prop
- (get-char-property (point) 'invisible)))
- (if (eq buffer-invisibility-spec t)
- prop
- (or (memq prop buffer-invisibility-spec)
- (assq prop buffer-invisibility-spec)))))
- (if (get-text-property (point) 'invisible)
- (progn
- (goto-char (next-single-property-change (point) 'invisible
- nil end))
- ;; if text is hidden by an `invisible' text property
- ;; we cannot open it at all.
- (setq can-be-opened nil))
- (unless (null can-be-opened)
- (let ((overlays (overlays-at (point)))
- ov-list
- o
- invis-prop)
- (while overlays
- (setq o (car overlays)
- invis-prop (overlay-get o 'invisible))
- (if (if (eq buffer-invisibility-spec t)
- invis-prop
- (or (memq invis-prop buffer-invisibility-spec)
- (assq invis-prop buffer-invisibility-spec)))
- (if (overlay-get o 'isearch-open-invisible)
- (setq ov-list (cons o ov-list))
- ;; We found one overlay that cannot be
- ;; opened, that means the whole chunk
- ;; cannot be opened.
- (setq can-be-opened nil)))
- (setq overlays (cdr overlays)))
- (if can-be-opened
- ;; It makes sense to append to the open
- ;; overlays list only if we know that this is
- ;; t.
- (setq crt-overlays (append ov-list crt-overlays)))))
- (goto-char (next-overlay-change (point)))))
- ;; See if invisibility reaches up thru END.
- (if (>= (point) end)
- (if (and (not (null can-be-opened)) (consp crt-overlays))
- (progn
- (setq isearch-opened-overlays
- (append isearch-opened-overlays crt-overlays))
- (mapc 'isearch-open-overlay-temporary crt-overlays)
- nil)
- t))))))
+ (when (/= beg end)
+ ;; Check that invisibility runs up to END.
+ (save-excursion
+ (goto-char beg)
+ (let (;; can-be-opened keeps track if we can open some overlays.
+ (can-be-opened (eq search-invisible 'open))
+ ;; the list of overlays that could be opened
+ (crt-overlays nil))
+ (when (and can-be-opened isearch-hide-immediately)
+ (isearch-close-unnecessary-overlays beg end))
+ ;; If the following character is currently invisible,
+ ;; skip all characters with that same `invisible' property value.
+ ;; Do that over and over.
+ (while (and (< (point) end)
+ (let ((prop
+ (get-char-property (point) 'invisible)))
+ (if (eq buffer-invisibility-spec t)
+ prop
+ (or (memq prop buffer-invisibility-spec)
+ (assq prop buffer-invisibility-spec)))))
+ (if (get-text-property (point) 'invisible)
+ (progn
+ (goto-char (next-single-property-change (point) 'invisible
+ nil end))
+ ;; if text is hidden by an `invisible' text property
+ ;; we cannot open it at all.
+ (setq can-be-opened nil))
+ (when can-be-opened
+ (let ((overlays (overlays-at (point)))
+ ov-list
+ o
+ invis-prop)
+ (while overlays
+ (setq o (car overlays)
+ invis-prop (overlay-get o 'invisible))
+ (if (if (eq buffer-invisibility-spec t)
+ invis-prop
+ (or (memq invis-prop buffer-invisibility-spec)
+ (assq invis-prop buffer-invisibility-spec)))
+ (if (overlay-get o 'isearch-open-invisible)
+ (setq ov-list (cons o ov-list))
+ ;; We found one overlay that cannot be
+ ;; opened, that means the whole chunk
+ ;; cannot be opened.
+ (setq can-be-opened nil)))
+ (setq overlays (cdr overlays)))
+ (if can-be-opened
+ ;; It makes sense to append to the open
+ ;; overlays list only if we know that this is
+ ;; t.
+ (setq crt-overlays (append ov-list crt-overlays)))))
+ (goto-char (next-overlay-change (point)))))
+ ;; See if invisibility reaches up thru END.
+ (if (>= (point) end)
+ (if (and can-be-opened (consp crt-overlays))
+ (progn
+ (setq isearch-opened-overlays
+ (append isearch-opened-overlays crt-overlays))
+ (mapc 'isearch-open-overlay-temporary crt-overlays)
+ nil)
+ (setq isearch-hidden t)))))))
\f
;; Highlighting
"Return t if there are no upper case chars in STRING.
If REGEXP-FLAG is non-nil, disregard letters preceded by `\\' (but not `\\\\')
since they have special meaning in a regexp."
- (let (quote-flag (i 0) (len (length string)) found)
+ (let (quote-flag (i 0) (len (length string)) found)
(while (and (not found) (< i len))
(let ((char (aref string i)))
(if (and regexp-flag (eq char ?\\))
(setq quote-flag (not quote-flag))
(if (and (not quote-flag) (not (eq char (downcase char))))
- (setq found t))))
+ (setq found t))
+ (setq quote-flag nil)))
(setq i (1+ i)))
(not found)))