]> code.delx.au - gnu-emacs/blobdiff - lisp/isearch.el
* lisp/minibuffer.el (completion--insert-strings): Don't get confused by
[gnu-emacs] / lisp / isearch.el
index afc18cae12728cac938a74a3ea1f2d2822185146..6eab3dbcbc4ccaaf0ea2cb7bd5c37deb7c549721 100644 (file)
@@ -1,12 +1,11 @@
 ;;; isearch.el --- incremental search minor mode
 
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
-;;   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1992-1997, 1999-2011  Free Software Foundation, Inc.
 
 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
 ;; Maintainer: FSF
 ;; Keywords: matching
+;; Package: emacs
 
 ;; This file is part of GNU Emacs.
 
@@ -156,6 +155,9 @@ command history."
 (defvar isearch-mode-hook nil
   "Function(s) to call after starting up an incremental search.")
 
+(defvar isearch-update-post-hook nil
+  "Function(s) to call after isearch has found matches in the buffer.")
+
 (defvar isearch-mode-end-hook nil
   "Function(s) to call after terminating an incremental search.
 When these functions are called, `isearch-mode-end-hook-quit'
@@ -235,7 +237,7 @@ Default value, nil, means edit the string instead."
   "Face for highlighting Isearch matches."
   :group 'isearch
   :group 'basic-faces)
-(defvar isearch 'isearch)
+(defvar isearch-face 'isearch)
 
 (defface isearch-fail
   '((((class color) (min-colors 88) (background light))
@@ -462,13 +464,16 @@ This is like `describe-bindings', but displays only Isearch keys."
     (define-key map    "\C-w" 'isearch-yank-word-or-char)
     (define-key map "\M-\C-w" 'isearch-del-char)
     (define-key map "\M-\C-y" 'isearch-yank-char)
-    (define-key map    "\C-y" 'isearch-yank-line)
+    (define-key map    "\C-y" 'isearch-yank-kill)
+    (define-key map "\M-s\C-e" 'isearch-yank-line)
 
-    (define-key map "\C-h" isearch-help-map)
+    (define-key map (char-to-string help-char) isearch-help-map)
+    (define-key map [help] isearch-help-map)
+    (define-key map [f1] isearch-help-map)
 
     (define-key map "\M-n" 'isearch-ring-advance)
     (define-key map "\M-p" 'isearch-ring-retreat)
-    (define-key map "\M-y" 'isearch-yank-kill)
+    (define-key map "\M-y" 'isearch-yank-pop)
 
     (define-key map "\M-\t" 'isearch-complete)
 
@@ -544,7 +549,8 @@ Each set is a vector of the form:
 (defvar isearch-error nil)     ; Error message for failed search.
 (defvar isearch-other-end nil) ; Start (end) of match if forward (backward).
 (defvar isearch-wrapped nil)   ; Searching restarted from the top (bottom).
-(defvar isearch-barrier 0)
+(defvar isearch-barrier 0
+  "Recorded minimum/maximal point for the current search.")
 (defvar isearch-just-started nil)
 (defvar isearch-start-hscroll 0)       ; hscroll when starting the search.
 
@@ -632,6 +638,8 @@ Type \\[isearch-yank-char] to yank char from buffer onto end of search\
 Type \\[isearch-yank-line] to yank rest of line onto end of search string\
  and search for it.
 Type \\[isearch-yank-kill] to yank the last string of killed text.
+Type \\[isearch-yank-pop] to replace string just yanked into search prompt
+ with string killed before it.
 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
@@ -872,7 +880,8 @@ It is called by the function `isearch-forward' and other related functions."
     (isearch-lazy-highlight-new-loop))
   ;; We must prevent the point moving to the end of composition when a
   ;; part of the composition has just been searched.
-  (setq disable-point-adjustment t))
+  (setq disable-point-adjustment t)
+  (run-hooks 'isearch-update-post-hook))
 
 (defun isearch-done (&optional nopush edit)
   "Exit Isearch mode.
@@ -943,7 +952,7 @@ NOPUSH is t and EDIT is t."
       (or (and transient-mark-mode mark-active)
          (progn
            (push-mark isearch-opoint t)
-           (or executing-kbd-macro (> (minibuffer-depth) 0)
+           (or executing-kbd-macro (> (minibuffer-depth) 0) edit
                (message "Mark saved where search started")))))
 
   (and (not edit) isearch-recursive-edit (exit-recursive-edit)))
@@ -1052,6 +1061,23 @@ nonincremental search instead via `isearch-edit-string'."
   (isearch-done)
   (isearch-clean-overlays))
 
+(defvar minibuffer-history-symbol) ;; from external package gmhist.el
+
+(defun isearch-fail-pos ()
+  "Position of first mismatch in search string, or its length if none."
+  (let ((cmds isearch-cmds))
+    (if (and isearch-success (not isearch-error))
+        (length isearch-message)
+      (while (or (not (isearch-success-state (car cmds)))
+                 (isearch-error-state (car cmds)))
+        (pop cmds))
+      (let ((succ-msg (and cmds (isearch-message-state (car cmds)))))
+        (if (and (stringp succ-msg)
+                 (< (length succ-msg) (length isearch-message))
+                 (equal succ-msg
+                        (substring isearch-message 0 (length succ-msg))))
+            (length succ-msg)
+          0)))))
 
 (defun isearch-edit-string ()
   "Edit the search string in the minibuffer.
@@ -1071,7 +1097,7 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
   ;; this could be simplified greatly.
   ;; Editing doesn't back up the search point.  Should it?
   (interactive)
-  (condition-case err
+  (condition-case nil
       (progn
        (let ((isearch-nonincremental isearch-nonincremental)
 
@@ -1106,6 +1132,14 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
              ;; Save current configuration so we can restore it here.
              (isearch-window-configuration (current-window-configuration))
 
+             ;; This could protect the index of the search rings,
+             ;; but we can't reliably count the number of typed M-p
+             ;; in `read-from-minibuffer' to adjust the index accordingly.
+             ;; So when the following is commented out, `isearch-mode'
+             ;; below resets the index to the predictable value nil.
+             ;; (search-ring-yank-pointer search-ring-yank-pointer)
+             ;; (regexp-search-ring-yank-pointer regexp-search-ring-yank-pointer)
+
              ;; Temporarily restore `minibuffer-message-timeout'.
              (minibuffer-message-timeout
               isearch-original-minibuffer-message-timeout)
@@ -1116,7 +1150,7 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
          ;; Actually terminate isearching until editing is done.
          ;; This is so that the user can do anything without failure,
          ;; like switch buffers and start another isearch, and return.
-         (condition-case err
+         (condition-case nil
              (isearch-done t t)
            (exit nil))                 ; was recursive editing
 
@@ -1126,13 +1160,18 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
 
          (unwind-protect
              (let* ((message-log-max nil)
+                    ;; Protect global value of search rings from updating
+                    ;; by `read-from-minibuffer'.  It should be updated only
+                    ;; by `isearch-update-ring' in `isearch-done', not here.
+                    (search-ring search-ring)
+                    (regexp-search-ring regexp-search-ring)
                     ;; Binding minibuffer-history-symbol to nil is a work-around
                     ;; for some incompatibility with gmhist.
                     (minibuffer-history-symbol))
                (setq isearch-new-string
                       (read-from-minibuffer
                        (isearch-message-prefix nil nil isearch-nonincremental)
-                       isearch-string
+                      (cons isearch-string (1+ (isearch-fail-pos)))
                        minibuffer-local-isearch-map nil
                        (if isearch-regexp
                           (cons 'regexp-search-ring
@@ -1165,19 +1204,17 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
                  isearch-word isearch-new-word))
 
          ;; Empty isearch-string means use default.
-         (if (= 0 (length isearch-string))
-             (setq isearch-string (or (car (if isearch-regexp
-                                               regexp-search-ring
-                                             search-ring))
-                                      "")
-
-                   isearch-message
-                   (mapconcat 'isearch-text-char-description
-                              isearch-string ""))
-           ;; This used to set the last search string,
-           ;; but I think it is not right to do that here.
-           ;; Only the string actually used should be saved.
-           ))
+         (when (= 0 (length isearch-string))
+           (setq isearch-string (or (car (if isearch-regexp
+                                             regexp-search-ring
+                                           search-ring))
+                                    "")
+
+                 isearch-message
+                 (mapconcat 'isearch-text-char-description
+                            isearch-string ""))
+           ;; After taking the last element, adjust ring to previous one.
+           (isearch-ring-adjust1 nil)))
 
        ;; This used to push the state as of before this C-s, but it adds
        ;; an inconsistent state where part of variables are from the
@@ -1237,9 +1274,9 @@ Use `isearch-exit' to quit without signaling."
   (interactive)
 ;;  (ding)  signal instead below, if quitting
   (discard-input)
-  (if isearch-success
-      ;; If search is successful, move back to starting point
-      ;; and really do quit.
+  (if (and isearch-success (not isearch-error))
+      ;; If search is successful and has no incomplete regexp,
+      ;; move back to starting point and really do quit.
       (progn
         (setq isearch-success nil)
         (isearch-cancel))
@@ -1264,7 +1301,9 @@ Use `isearch-exit' to quit without signaling."
                  isearch-message
                  (mapconcat 'isearch-text-char-description
                             isearch-string "")
-                 isearch-case-fold-search isearch-last-case-fold-search))
+                 isearch-case-fold-search isearch-last-case-fold-search)
+           ;; After taking the last element, adjust ring to previous one.
+           (isearch-ring-adjust1 nil))
        ;; If already have what to search for, repeat it.
        (or isearch-success
            (progn
@@ -1406,9 +1445,10 @@ string.  NLINES has the same meaning as in `occur'."
      (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
-       ;; `isearch-no-upper-case-p' in `occur-1'
-       (search-upper-case nil))
+       ;; Set `search-upper-case' to nil to not call
+       ;; `isearch-no-upper-case-p' in `occur-1'.
+       (search-upper-case nil)
+       (search-spaces-regexp search-whitespace-regexp))
     (occur regexp nlines)))
 
 (declare-function hi-lock-read-face-name "hi-lock" ())
@@ -1480,20 +1520,28 @@ If search string is empty, just beep."
           (eq 'not-yanks search-upper-case))
       (setq string (downcase string)))
   (if isearch-regexp (setq string (regexp-quote string)))
-  (setq isearch-string (concat isearch-string string)
-       isearch-message
-       (concat isearch-message
-               (mapconcat 'isearch-text-char-description
-                          string ""))
-       ;; Don't move cursor in reverse search.
-       isearch-yank-flag t)
-  (isearch-search-and-update))
+  ;; Don't move cursor in reverse search.
+  (setq isearch-yank-flag t)
+  (isearch-process-search-string
+   string (mapconcat 'isearch-text-char-description string "")))
 
 (defun isearch-yank-kill ()
   "Pull string from kill ring into search string."
   (interactive)
   (isearch-yank-string (current-kill 0)))
 
+(defun isearch-yank-pop ()
+  "Replace just-yanked search string with previously killed string."
+  (interactive)
+  (if (not (memq last-command '(isearch-yank-kill isearch-yank-pop)))
+      ;; Fall back on `isearch-yank-kill' for the benefits of people
+      ;; who are used to the old behavior of `M-y' in isearch mode. In
+      ;; future, this fallback may be changed if we ever change
+      ;; `yank-pop' to do something like the kill-ring-browser.
+      (isearch-yank-kill)
+    (isearch-pop-state)
+    (isearch-yank-string (current-kill 1))))
+
 (defun isearch-yank-x-selection ()
   "Pull current X selection into search string."
   (interactive)
@@ -1542,14 +1590,18 @@ or it might return the position of the end of the line."
   (interactive "p")
   (isearch-yank-internal (lambda () (forward-char arg) (point))))
 
+(declare-function subword-forward "subword" (&optional arg))
 (defun isearch-yank-word-or-char ()
-  "Pull next character or word from buffer into search string."
+  "Pull next character, subword or word from buffer into search string.
+Subword is used when `subword-mode' is activated. "
   (interactive)
   (isearch-yank-internal
    (lambda ()
      (if (or (= (char-syntax (or (char-after) 0)) ?w)
              (= (char-syntax (or (char-after (1+ (point))) 0)) ?w))
-         (forward-word 1)
+        (if (and (boundp 'subword-mode) subword-mode)
+            (subword-forward 1)
+          (forward-word 1))
        (forward-char 1)) (point))))
 
 (defun isearch-yank-word ()
@@ -1712,9 +1764,10 @@ Scroll-bar or mode-line events are processed appropriately."
 ;; attempts this, we scroll the text back again.
 ;;
 ;; We implement this feature with a property called `isearch-scroll'.
-;; If a command's symbol has the value t for this property it is a
-;; scrolling command.  The feature needs to be enabled by setting the
-;; customizable variable `isearch-allow-scroll' to a non-nil value.
+;; If a command's symbol has the value t for this property or for the
+;; `scroll-command' property, it is a scrolling command.  The feature
+;; needs to be enabled by setting the customizable variable
+;; `isearch-allow-scroll' to a non-nil value.
 ;;
 ;; The universal argument commands (e.g. C-u) in simple.el are marked
 ;; as scrolling commands, and isearch.el has been amended to allow
@@ -1731,12 +1784,11 @@ Scroll-bar or mode-line events are processed appropriately."
 (if (fboundp 'w32-handle-scroll-bar-event)
     (put 'w32-handle-scroll-bar-event 'isearch-scroll t))
 
-;; Commands which scroll the window:
+;; Commands which scroll the window (some scroll commands
+;; already have the `scroll-command' property on them):
 (put 'recenter 'isearch-scroll t)
 (put 'recenter-top-bottom 'isearch-scroll t)
 (put 'reposition-window 'isearch-scroll t)
-(put 'scroll-up 'isearch-scroll t)
-(put 'scroll-down 'isearch-scroll t)
 
 ;; Commands which act on the other window
 (put 'list-buffers 'isearch-scroll t)
@@ -1761,7 +1813,7 @@ Scroll-bar or mode-line events are processed appropriately."
   "Whether scrolling is allowed during incremental search.
 If non-nil, scrolling commands can be used in Isearch mode.
 However, the current match will never scroll offscreen.
-If nil, scolling commands will first cancel Isearch mode."
+If nil, scrolling commands will first cancel Isearch mode."
   :type 'boolean
   :group 'isearch)
 
@@ -1825,7 +1877,8 @@ Otherwise return nil."
   (let* ((overriding-terminal-local-map nil)
          (binding (key-binding key-seq)))
     (and binding (symbolp binding) (commandp binding)
-         (eq (get binding 'isearch-scroll) t)
+         (or (eq (get binding 'isearch-scroll) t)
+            (eq (get binding 'scroll-command) t))
          binding)))
 
 (defalias 'isearch-other-control-char 'isearch-other-meta-char)
@@ -1986,12 +2039,6 @@ Isearch mode."
           (setq char (unibyte-char-to-multibyte char)))
       (isearch-process-search-char char))))
 
-(defun isearch-return-char ()
-  "Convert return into newline for incremental search."
-  (interactive)
-  (isearch-process-search-char ?\n))
-(make-obsolete 'isearch-return-char 'isearch-printing-char "19.7")
-
 (defun isearch-printing-char ()
   "Add this ordinary printing character to the search string and search."
   (interactive)
@@ -2038,7 +2085,7 @@ Isearch mode."
        ()
       (set yank-pointer-name
           (setq yank-pointer
-                (mod (+ (or yank-pointer 0)
+                (mod (+ (or yank-pointer (if advance 0 -1))
                         (if advance -1 1))
                      length)))
       (setq isearch-string (nth yank-pointer ring)
@@ -2150,7 +2197,7 @@ If there is no completion possible, say so and continue searching."
             (isearch-message-suffix c-q-hack ellipsis)))
     (if c-q-hack m (let ((message-log-max nil)) (message "%s" m)))))
 
-(defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
+(defun isearch-message-prefix (&optional _c-q-hack ellipsis nonincremental)
   ;; If about to search, and previous search regexp was invalid,
   ;; check that it still is.  If it is valid now,
   ;; let the message we display while searching say that it is valid.
@@ -2183,7 +2230,7 @@ If there is no completion possible, say so and continue searching."
     (propertize (concat (upcase (substring m 0 1)) (substring m 1))
                'face 'minibuffer-prompt)))
 
-(defun isearch-message-suffix (&optional c-q-hack ellipsis)
+(defun isearch-message-suffix (&optional c-q-hack _ellipsis)
   (concat (if c-q-hack "^Q" "")
          (if isearch-error
              (concat " [" isearch-error "]")
@@ -2194,10 +2241,13 @@ If there is no completion possible, say so and continue searching."
 ;; Searching
 
 (defvar isearch-search-fun-function nil
-  "Override `isearch-search-fun'.
-This function should return the search function for Isearch to use.
-It will call this function with three arguments
-as if it were `search-forward'.")
+  "Overrides the default `isearch-search-fun' behaviour.
+This variable's value should be a function, which will be called
+with no arguments, and should return a function that takes three
+arguments: STRING, BOUND, and NOERROR.
+
+This returned function will be used by `isearch-search-string' to
+search for the first occurrence of STRING or its translation.")
 
 (defun isearch-search-fun ()
   "Return the function to use for the search.
@@ -2418,14 +2468,8 @@ update the match data, and return point."
        ;; 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)
+       (while (and (< (point) end) (invisible-p (point)))
+         (if (invisible-p (get-text-property (point) 'invisible))
              (progn
                (goto-char (next-single-property-change (point) 'invisible
                                                        nil end))
@@ -2440,10 +2484,7 @@ update the match data, and return point."
                (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 (invisible-p invis-prop)
                      (if (overlay-get o 'isearch-open-invisible)
                          (setq ov-list (cons o ov-list))
                        ;; We found one overlay that cannot be
@@ -2533,7 +2574,7 @@ since they have special meaning in a regexp."
        (setq isearch-overlay (make-overlay beg end))
        ;; 1001 is higher than lazy's 1000 and ediff's 100+
        (overlay-put isearch-overlay 'priority 1001)
-       (overlay-put isearch-overlay 'face isearch))))
+       (overlay-put isearch-overlay 'face isearch-face))))
 
 (defun isearch-dehighlight ()
   (when isearch-overlay
@@ -2674,6 +2715,8 @@ Attempt to do the search exactly the way the pending Isearch would."
          ;; Clear RETRY unless the search predicate says
          ;; to skip this search hit.
          (if (or (not success)
+                 (= (point) bound) ; like (bobp) (eobp) in `isearch-search'.
+                 (= (match-beginning 0) (match-end 0))
                  (funcall isearch-filter-predicate
                           (match-beginning 0) (match-end 0)))
              (setq retry nil)))
@@ -2763,5 +2806,4 @@ CASE-FOLD non-nil means the search was case-insensitive."
   (isearch-search)
   (isearch-update))
 
-;; arch-tag: 74850515-f7d8-43a6-8a2c-ca90a4c1e675
 ;;; isearch.el ends here