]> code.delx.au - gnu-emacs/blobdiff - lisp/isearch.el
* w32-fns.el (w32-shell-dos-semantics):
[gnu-emacs] / lisp / isearch.el
index 130685fb8826180a3aa383e97a9adb61ecf0cd2f..c343472767768f511bf6622f087a1a13a342ce5c 100644 (file)
@@ -491,6 +491,9 @@ This is like `describe-bindings', but displays only isearch keys."
     (define-key map "\M-r" 'isearch-toggle-regexp)
     (define-key map "\M-e" 'isearch-edit-string)
 
+    (define-key map "\M-sr" 'isearch-toggle-regexp)
+    (define-key map "\M-sw" 'isearch-toggle-word)
+
     (define-key map [?\M-%] 'isearch-query-replace)
     (define-key map [?\C-\M-%] 'isearch-query-replace-regexp)
     (define-key map "\M-so" 'isearch-occur)
@@ -506,6 +509,7 @@ This is like `describe-bindings', but displays only isearch keys."
     (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)
+    (define-key map "\C-w"  'isearch-edit-string-set-word)
     (define-key map "\C-f"  'isearch-yank-char-in-minibuffer)
     (define-key map [right] 'isearch-yank-char-in-minibuffer)
     map)
@@ -529,6 +533,9 @@ Each set is a vector of the form:
 (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).
@@ -596,6 +603,7 @@ Each set is a vector of the form:
 (define-key esc-map "\C-s" 'isearch-forward-regexp)
 (define-key global-map "\C-r" 'isearch-backward)
 (define-key esc-map "\C-r" 'isearch-backward-regexp)
+(define-key search-map "w" 'isearch-forward-word)
 
 ;; Entry points to isearch-mode.
 
@@ -630,13 +638,9 @@ Type \\[isearch-quote-char] to quote control character to search for it.
 If you try to exit with the search string still empty, it invokes
  nonincremental search.
 
-Type \\[isearch-query-replace] to start `query-replace' with string to\
- replace from last search string.
-Type \\[isearch-query-replace-regexp] to start `query-replace-regexp'\
- with string to replace from last search string.
-
 Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity.
 Type \\[isearch-toggle-regexp] to toggle regular-expression mode.
+Type \\[isearch-toggle-word] to toggle word mode.
 Type \\[isearch-edit-string] to edit the search string in the minibuffer.
 
 Also supported is a search ring of the previous 16 search strings.
@@ -645,6 +649,15 @@ Type \\[isearch-ring-retreat] to search for the previous item in the search\
  ring.
 Type \\[isearch-complete] to complete the search string using the search ring.
 
+Type \\[isearch-query-replace] to run `query-replace' with string to\
+ replace from last search string.
+Type \\[isearch-query-replace-regexp] to run `query-replace-regexp'\
+ with the last search string.
+Type \\[isearch-occur] to run `occur' that shows\
+ the last search string.
+Type \\[isearch-highlight-regexp] to run `highlight-regexp'\
+ that highlights the last search string.
+
 Type \\[isearch-describe-bindings] to display all isearch key bindings.
 Type \\[isearch-describe-key] to display documentation of isearch key.
 Type \\[isearch-describe-mode] to display documentation of isearch mode.
@@ -674,8 +687,8 @@ the calling function until the search is done."
   "\
 Do incremental search forward for regular expression.
 With a prefix argument, do a regular string search instead.
-Like ordinary incremental search except that your input
-is treated as a regexp.  See \\[isearch-forward] for more info.
+Like ordinary incremental search except that your input is treated
+as a regexp.  See the command `isearch-forward' for more information.
 
 In regexp incremental searches, a space or spaces normally matches
 any whitespace (the variable `search-whitespace-regexp' controls
@@ -684,11 +697,21 @@ and nothing else, enter C-q SPC."
   (interactive "P\np")
   (isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
 
+(defun isearch-forward-word (&optional not-word no-recursive-edit)
+  "\
+Do incremental search forward for a sequence of words.
+With a prefix argument, do a regular string search instead.
+Like ordinary incremental search except that your input is treated
+as a sequence of words without regard to how the words are separated.
+See the command `isearch-forward' for more information."
+  (interactive "P\np")
+  (isearch-mode t nil nil (not no-recursive-edit) (null not-word)))
+
 (defun isearch-backward (&optional regexp-p no-recursive-edit)
   "\
 Do incremental search backward.
 With a prefix argument, do a regular expression search instead.
-See \\[isearch-forward] for more information."
+See the command `isearch-forward' for more information."
   (interactive "P\np")
   (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
 
@@ -696,8 +719,8 @@ See \\[isearch-forward] for more information."
   "\
 Do incremental search backward for regular expression.
 With a prefix argument, do a regular string search instead.
-Like ordinary incremental search except that your input
-is treated as a regexp.  See \\[isearch-forward] for more info."
+Like ordinary incremental search except that your input is treated
+as a regexp.  See the command `isearch-forward' for more information."
   (interactive "P\np")
   (isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
 
@@ -1092,31 +1115,11 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
          ;; 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?
-                    ;;(echo-keystrokes 0) ;; not needed with above message
-                    (e (let ((cursor-in-echo-area t))
-                         (read-event)))
+             (let* ((message-log-max nil)
                     ;; Binding minibuffer-history-symbol to nil is a work-around
                     ;; for some incompatibility with gmhist.
-                    (minibuffer-history-symbol)
-                    (message-log-max nil))
-               ;; If the first character the user types when we prompt them
-               ;; for a string is the yank-word character, then go into
-               ;; word-search mode.  Otherwise unread that character and
-               ;; read a key the normal way.
-               ;; Word search does not apply (yet) to regexp searches,
-               ;; no check is made here.
-               (message "%s" (isearch-message-prefix nil nil t))
-               (if (memq (lookup-key isearch-mode-map (vector e))
-                         '(isearch-yank-word
-                           isearch-yank-word-or-char))
-                   (setq isearch-word t;; so message-prefix is right
-                         isearch-new-word t)
-                 (cancel-kbd-macro-events)
-                 (isearch-unread e))
-               (setq cursor-in-echo-area nil)
+                    (minibuffer-history-symbol))
                (setq isearch-new-string
                       (read-from-minibuffer
                        (isearch-message-prefix nil nil isearch-nonincremental)
@@ -1190,6 +1193,15 @@ If first char entered is \\[isearch-yank-word-or-char], then do word search inst
      (isearch-abort)  ;; outside of let to restore outside global values
      )))
 
+;; Obsolete usage of `C-s M-e C-w'.  Remove after 23.1.
+(defvar isearch-new-word)
+(defun isearch-edit-string-set-word ()
+  "Do word search after exiting `isearch-edit-string'."
+  (interactive)
+  (message "This feature is obsolete since 23.1; use `M-s w' instead.")
+  (setq isearch-word t isearch-new-word t))
+
+
 (defun isearch-nonincremental-exit-minibuffer ()
   (interactive)
   (setq isearch-nonincremental t)
@@ -1303,6 +1315,13 @@ Use `isearch-exit' to quit without signaling."
   (setq isearch-success t isearch-adjusted t)
   (isearch-update))
 
+(defun isearch-toggle-word ()
+  "Toggle word searching on or off."
+  (interactive)
+  (setq isearch-word (not isearch-word))
+  (setq isearch-success t isearch-adjusted t)
+  (isearch-update))
+
 (defun isearch-toggle-case-fold ()
   "Toggle case folding in searching on or off."
   (interactive)
@@ -1317,16 +1336,27 @@ Use `isearch-exit' to quit without signaling."
   (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))
@@ -1340,16 +1370,22 @@ Use `isearch-exit' to quit without signaling."
      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.
@@ -1357,7 +1393,10 @@ Interactively, REGEXP is the current search regexp or a quoted search
 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
@@ -1368,22 +1407,39 @@ string.  NLINES has the same meaning as in `occur'."
 (declare-function hi-lock-regexp-okay "hi-lock" (regexp))
 (declare-function hi-lock-read-face-name "hi-lock" ())
 
-(defun isearch-highlight-regexp (regexp &optional face)
+(defun isearch-highlight-regexp ()
   "Run `highlight-regexp' with regexp from the current search string.
-Interactively, REGEXP is the current search regexp or a quoted search
-string.  FACE has the same meaning as in `highlight-regexp'."
-  (interactive
-   (list
-    (progn
-      (require 'hi-lock nil t)
-      (hi-lock-regexp-okay
-       (if isearch-regexp isearch-string (regexp-quote isearch-string))))
-    (hi-lock-read-face-name)))
-  (isearch-done)
-  (isearch-clean-overlays)
-  ;; (add-to-history 'hi-lock-regexp-history regexp)
-  (let ((case-fold-search isearch-case-fold-search))
-    (hi-lock-face-buffer regexp face)))
+It exits Isearch mode and calls `hi-lock-face-buffer' with its regexp
+argument from the last search regexp or a quoted search string,
+and reads its face argument using `hi-lock-read-face-name'."
+  (interactive)
+  (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)
+  (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 ()
@@ -1667,8 +1723,6 @@ Scroll-bar or mode-line events are processed appropriately."
 ;; Scroll-bar functions:
 (if (fboundp 'scroll-bar-toolkit-scroll)
     (put 'scroll-bar-toolkit-scroll 'isearch-scroll t))
-(if (fboundp 'mac-handle-scroll-bar-event)
-    (put 'mac-handle-scroll-bar-event 'isearch-scroll t))
 (if (fboundp 'w32-handle-scroll-bar-event)
     (put 'w32-handle-scroll-bar-event 'isearch-scroll t))
 
@@ -2111,6 +2165,8 @@ If there is no completion possible, say so and continue searching."
                   (if isearch-wrapped "wrapped ")
                   (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
@@ -2124,7 +2180,8 @@ If there is no completion possible, say so and continue searching."
   (concat (if c-q-hack "^Q" "")
          (if isearch-error
              (concat " [" isearch-error "]")
-           "")))
+           "")
+         (or isearch-message-suffix-add "")))
 
 \f
 ;; Searching
@@ -2142,7 +2199,12 @@ Can be changed via `isearch-search-fun-function' for special needs."
       (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
@@ -2179,9 +2241,9 @@ Can be changed via `isearch-search-fun-function' for special needs."
     (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))
+      (if (and multi-isearch-next-buffer-current-function
+              (buffer-live-p multi-isearch-current-buffer))
+         (switch-to-buffer multi-isearch-current-buffer))
       (goto-char pos1))
     pos1))
 
@@ -2562,23 +2624,32 @@ by other Emacs features."
 (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."