]> code.delx.au - gnu-emacs/blobdiff - lisp/isearch.el
* lisp/isearch.el (minibuffer-local-isearch-map): Bind "\r" to `exit-minibuffer'
[gnu-emacs] / lisp / isearch.el
index 54ec3f2b05274ca9909725b263d86e3da7472320..04fd594e7f15d9ae2772f1103bbf492193899efb 100644 (file)
@@ -1,6 +1,6 @@
 ;;; isearch.el --- incremental search minor mode
 
-;; Copyright (C) 1992-1997, 1999-201 Free Software Foundation, Inc.
+;; Copyright (C) 1992-1997, 1999-2013 Free Software Foundation, Inc.
 
 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
 ;; Maintainer: FSF
@@ -47,7 +47,7 @@
 ;; modify the search string before executing the search.  There are
 ;; three commands to terminate the editing: C-s and C-r exit the
 ;; minibuffer and search forward and reverse respectively, while C-m
-;; exits and does a nonincremental search.
+;; exits and searches in the last search direction.
 
 ;; Exiting immediately from isearch uses isearch-edit-string instead
 ;; of nonincremental-search, if search-nonincremental-instead is non-nil.
@@ -176,7 +176,7 @@ is non-nil if the user quits the search.")
 
 (defvar isearch-message-function nil
   "Function to call to display the search prompt.
-If nil, use `isearch-message'.")
+If nil, use function `isearch-message'.")
 
 (defvar isearch-wrap-function nil
   "Function to call to wrap the search when search is failed.
@@ -520,7 +520,7 @@ This is like `describe-bindings', but displays only Isearch keys."
     (define-key map "\C-x" nil)
     (define-key map [?\C-x t] 'isearch-other-control-char)
     (define-key map "\C-x8" nil)
-    (define-key map "\C-x8\r" 'isearch-other-control-char)
+    (define-key map "\C-x8\r" 'isearch-insert-char-by-name)
 
     map)
   "Keymap for `isearch-mode'.")
@@ -528,7 +528,7 @@ This is like `describe-bindings', but displays only Isearch keys."
 (defvar minibuffer-local-isearch-map
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map minibuffer-local-map)
-    (define-key map "\r"    'isearch-nonincremental-exit-minibuffer)
+    (define-key map "\r"    'exit-minibuffer)
     (define-key map "\M-\t" 'isearch-complete-edit)
     (define-key map "\C-s"  'isearch-forward-exit-minibuffer)
     (define-key map "\C-r"  'isearch-reverse-exit-minibuffer)
@@ -735,8 +735,9 @@ Other control and meta characters terminate the search
  and are then executed normally (depending on `search-exit-option').
 Likewise for function keys and mouse button events.
 
-If this function is called non-interactively, it does not return to
-the calling function until the search is done."
+If this function is called non-interactively with a nil NO-RECURSIVE-EDIT,
+it does not return to the calling function until the search is done.
+See the function `isearch-mode' for more information."
 
   (interactive "P\np")
   (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
@@ -799,7 +800,23 @@ as a regexp.  See the command `isearch-forward' for more information."
 
 (defun isearch-mode (forward &optional regexp op-fun recursive-edit word)
   "Start Isearch minor mode.
-It is called by the function `isearch-forward' and other related functions."
+It is called by the function `isearch-forward' and other related functions.
+
+The non-nil arg FORWARD means searching in the forward direction.
+
+The non-nil arg REGEXP does an incremental regular expression search.
+
+The arg OP-FUN is a function to be called after each input character
+is processed.  (It is not called after characters that exit the search.)
+
+When the arg RECURSIVE-EDIT is non-nil, this function behaves modally and
+does not return to the calling function until the search is completed.
+To behave this way it enters a recursive-edit and exits it when done
+isearching.
+
+The arg WORD, if t, does incremental search for a sequence of words,
+ignoring punctuation.  If the value is a function, it is called to
+convert the search string to a regexp used by regexp search functions."
 
   ;; Initialize global vars.
   (setq isearch-forward forward
@@ -1101,13 +1118,14 @@ nonincremental search instead via `isearch-edit-string'."
 
 (defun isearch-fail-pos (&optional msg)
   "Return position of first mismatch in search string, or nil if none.
-If MSG is non-nil, use `isearch-message', otherwise `isearch-string'."
+If MSG is non-nil, use variable `isearch-message', otherwise `isearch-string'."
   (let ((cmds isearch-cmds)
        (curr-msg (if msg isearch-message isearch-string))
        succ-msg)
     (when (or (not isearch-success) isearch-error)
-      (while (or (not (isearch--state-success (car cmds)))
-                 (isearch--state-error (car cmds)))
+      (while (and cmds
+                 (or (not (isearch--state-success (car cmds)))
+                     (isearch--state-error (car cmds))))
         (pop cmds))
       (setq succ-msg (and cmds (if msg (isearch--state-message (car cmds))
                                 (isearch--state-string (car cmds)))))
@@ -1118,23 +1136,17 @@ If MSG is non-nil, use `isearch-message', otherwise `isearch-string'."
          (length succ-msg)
        0))))
 
-(defun isearch-edit-string ()
-  "Edit the search string in the minibuffer.
-The following additional command keys are active while editing.
-\\<minibuffer-local-isearch-map>
-\\[exit-minibuffer] to resume incremental searching with the edited string.
-\\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search.
-\\[isearch-forward-exit-minibuffer] to resume isearching forward.
-\\[isearch-reverse-exit-minibuffer] to resume isearching backward.
-\\[isearch-complete-edit] to complete the search string using the search ring."
-
+(defmacro with-isearch-suspended (&rest body)
+  "Exit Isearch mode, run BODY, and reinvoke the pending search.
+You can update the global isearch variables by setting new values to
+`isearch-new-string', `isearch-new-message', `isearch-new-forward',
+`isearch-new-word', `isearch-new-case-fold'."
   ;; This code is very hairy for several reasons, explained in the code.
   ;; Mainly, isearch-mode must be terminated while editing and then restarted.
   ;; If there were a way to catch any change of buffer from the minibuffer,
   ;; this could be simplified greatly.
   ;; Editing doesn't back up the search point.  Should it?
-  (interactive)
-  (condition-case nil
+  `(condition-case nil
       (progn
        (let ((isearch-nonincremental isearch-nonincremental)
 
@@ -1197,29 +1209,7 @@ The following additional command keys are active while editing.
          (setq old-point (point) old-other-end isearch-other-end)
 
          (unwind-protect
-             (let* ((message-log-max nil)
-                    ;; Don't add a new search string to the search ring here
-                    ;; in `read-from-minibuffer'. It should be added only
-                    ;; by `isearch-update-ring' called from `isearch-done'.
-                    (history-add-new-input nil)
-                    ;; 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 isearch-nonincremental)
-                      (cons isearch-string (1+ (or (isearch-fail-pos)
-                                                   (length isearch-string))))
-                       minibuffer-local-isearch-map nil
-                       (if isearch-regexp
-                          (cons 'regexp-search-ring
-                                (1+ (or regexp-search-ring-yank-pointer -1)))
-                        (cons 'search-ring
-                              (1+ (or search-ring-yank-pointer -1))))
-                       nil t)
-                     isearch-new-message
-                     (mapconcat 'isearch-text-char-description
-                                isearch-new-string "")))
+             (progn ,@body)
 
            ;; Set point at the start (end) of old match if forward (backward),
            ;; so after exiting minibuffer isearch resumes at the start (end)
@@ -1278,17 +1268,56 @@ The following additional command keys are active while editing.
      (isearch-abort)  ;; outside of let to restore outside global values
      )))
 
+(defun isearch-edit-string ()
+  "Edit the search string in the minibuffer.
+The following additional command keys are active while editing.
+\\<minibuffer-local-isearch-map>
+\\[exit-minibuffer] to resume incremental searching with the edited string.
+\\[isearch-forward-exit-minibuffer] to resume isearching forward.
+\\[isearch-reverse-exit-minibuffer] to resume isearching backward.
+\\[isearch-complete-edit] to complete the search string using the search ring."
+  (interactive)
+  (with-isearch-suspended
+   (let* ((message-log-max nil)
+         ;; Don't add a new search string to the search ring here
+         ;; in `read-from-minibuffer'. It should be added only
+         ;; by `isearch-update-ring' called from `isearch-done'.
+         (history-add-new-input nil)
+         ;; 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 isearch-nonincremental)
+           (cons isearch-string (1+ (or (isearch-fail-pos)
+                                        (length isearch-string))))
+           minibuffer-local-isearch-map nil
+           (if isearch-regexp
+               (cons 'regexp-search-ring
+                     (1+ (or regexp-search-ring-yank-pointer -1)))
+             (cons 'search-ring
+                   (1+ (or search-ring-yank-pointer -1))))
+           nil t)
+          isearch-new-message
+          (mapconcat 'isearch-text-char-description
+                     isearch-new-string "")))))
+
 (defun isearch-nonincremental-exit-minibuffer ()
   (interactive)
   (setq isearch-nonincremental t)
   (exit-minibuffer))
+;; Changing the value of `isearch-nonincremental' has no effect here,
+;; because `isearch-edit-string' ignores this change.  Thus marked as obsolete.
+(make-obsolete 'isearch-nonincremental-exit-minibuffer 'exit-minibuffer "24.4")
 
 (defun isearch-forward-exit-minibuffer ()
+  "Resume isearching forward from the minibuffer that edits the search string."
   (interactive)
   (setq isearch-new-forward t)
   (exit-minibuffer))
 
 (defun isearch-reverse-exit-minibuffer ()
+  "Resume isearching backward from the minibuffer that edits the search string."
   (interactive)
   (setq isearch-new-forward nil)
   (exit-minibuffer))
@@ -1707,6 +1736,9 @@ and reads its face argument using `hi-lock-read-face-name'."
 \f
 (defun isearch-delete-char ()
   "Discard last input item and move point back.
+Last input means the last character or the last isearch command
+that added or deleted characters from the search string,
+moved point, toggled regexp mode or case-sensitivity, etc.
 If no previous match was done, just beep."
   (interactive)
   (if (null (cdr isearch-cmds))
@@ -1716,6 +1748,8 @@ If no previous match was done, just beep."
 
 (defun isearch-del-char (&optional arg)
   "Delete character from end of search string and search again.
+Unlike `isearch-delete-char', it only deletes the last character,
+but doesn't cancel the effect of other isearch command.
 If search string is empty, just beep."
   (interactive "p")
   (if (= 0 (length isearch-string))
@@ -1836,6 +1870,17 @@ Subword is used when `subword-mode' is activated. "
    (lambda () (let ((inhibit-field-text-motion t))
                (line-end-position (if (eolp) 2 1))))))
 
+(defun isearch-insert-char-by-name ()
+  "Read a character by its Unicode name and insert it into search string."
+  (interactive)
+  (with-isearch-suspended
+   (let ((char (read-char-by-name "Insert character (Unicode name or hex): ")))
+     (when char
+       (setq isearch-new-string (concat isearch-string (string char))
+            isearch-new-message (concat isearch-message
+                                        (mapconcat 'isearch-text-char-description
+                                                   (string char) "")))))))
+
 (defun isearch-search-and-update ()
   ;; Do the search and update the display.
   (when (or isearch-success
@@ -2497,6 +2542,7 @@ Can be changed via `isearch-search-fun-function' for special needs."
       ;; the user adds and removes characters in the search string
       ;; (or when using nonincremental word isearch)
       (let ((lax (not (or isearch-nonincremental
+                         (null (car isearch-cmds))
                          (eq (length isearch-string)
                              (length (isearch--state-string
                                        (car isearch-cmds))))))))
@@ -2937,8 +2983,15 @@ by other Emacs features."
     (setq isearch-lazy-highlight-window       (selected-window)
          isearch-lazy-highlight-window-start (window-start)
          isearch-lazy-highlight-window-end   (window-end)
-         isearch-lazy-highlight-start        (point)
-         isearch-lazy-highlight-end          (point)
+         ;; Start lazy-highlighting at the beginning of the found
+         ;; match (`isearch-other-end').  If no match, use point.
+         ;; One of the next two variables (depending on search direction)
+         ;; is used to define the starting position of lazy-highlighting
+         ;; and also to remember the current position of point between
+         ;; calls of `isearch-lazy-highlight-update', and another variable
+         ;; is used to define where the wrapped search must stop.
+         isearch-lazy-highlight-start        (or isearch-other-end (point))
+         isearch-lazy-highlight-end          (or isearch-other-end (point))
          isearch-lazy-highlight-wrapped      nil
          isearch-lazy-highlight-last-string  isearch-string
          isearch-lazy-highlight-case-fold-search isearch-case-fold-search
@@ -3036,6 +3089,9 @@ Attempt to do the search exactly the way the pending Isearch would."
                          (overlay-put ov 'priority 1000)
                          (overlay-put ov 'face lazy-highlight-face)
                          (overlay-put ov 'window (selected-window))))
+                     ;; Remember the current position of point for
+                     ;; the next call of `isearch-lazy-highlight-update'
+                     ;; when `lazy-highlight-max-at-a-time' is too small.
                      (if isearch-lazy-highlight-forward
                          (setq isearch-lazy-highlight-end (point))
                        (setq isearch-lazy-highlight-start (point)))))