]> code.delx.au - gnu-emacs/blobdiff - lisp/isearch.el
* isearch.el (isearch-switch-frame-handler): Call
[gnu-emacs] / lisp / isearch.el
index 4b694846e73a91c754154460c170abab00f0c9b9..85b8924ac0d97a7f7c87f406a4c846af0a6d970e 100644 (file)
@@ -1,10 +1,10 @@
-;; Incremental search minor mode.
+;;; isearch.el --- incremental search minor mode.
+
 ;; Copyright (C) 1992 Free Software Foundation, Inc.
 
-;; LCD Archive Entry:
-;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu
-;; |A minor mode replacement for isearch.el.
-;; |$Date: 92/09/14 16:26:02 $|$Revision: 1.4 $|~/modes/isearch-mode.el
+;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
+
+;; |$Date: 1993/03/17 17:17:05 $|$Revision: 1.26 $
 
 ;; This file is not yet part of GNU Emacs, but it is based almost
 ;; entirely on isearch.el which is part of GNU Emacs.
@@ -24,6 +24,8 @@
 ;; file named COPYING.  Among other things, the copyright notice
 ;; and this notice must be preserved on all copies.
 
+;;; Commentary:
+
 ;;;====================================================================
 ;; Instructions
 
 ;; - Think about incorporating query-replace.
 ;; - Hooks and options for failed search.
 
+;;; Change Log:
+
 ;;;====================================================================
 ;;; Change History
 
-;;; $Header: /import/kaplan/kaplan/liberte/Isearch/RCS/isearch-mode.el,v 1.4 92/09/14 16:26:02 liberte Exp Locker: liberte $
-;;; $Log:      isearch-mode.el,v $
+;;; $Header: /home/gd/gnu/emacs/19.0/lisp/RCS/isearch.el,v 1.26 1993/03/17 17:17:05 eric Exp jimb $
+;;; $Log: isearch.el,v $
+; Revision 1.26  1993/03/17  17:17:05  eric
+; Add standard library headers.
+;
+; Revision 1.25  1993/03/17  16:44:50  eric
+; Add standard library headers.
+;
+; Revision 1.24  1993/03/17  15:58:09  eric
+; Add standard library headers.
+;
+; Revision 1.23  1993/03/07  20:17:27  rms
+; (isearch-other-meta-char): Call listify-key-sequence.
+; (isearch-unread): Don't call it here.
+; (isearch-mode-map): Bind the ASCII-equivalent function keys.
+;
+; Revision 1.22  1993/03/07  08:43:57  rms
+; (isearch-mode): Don't make a pre-command-hook.
+;
+; Revision 1.21  1993/03/07  04:22:00  rms
+; (isearch-unread): Find last list element by hand.
+;
+; Revision 1.20  1993/03/06  06:15:05  rms
+; (isearch-unread): Handle multiple args.
+; For Emacs 19, use listify-key-sequence.
+; If not Emacs 19, assume they are a meta sequence.
+; (isearch-other-meta-char): Pass the whole key sequence.
+; (isearch-other-control-char): Make this alias for ...-meta-char.
+;
+; Revision 1.19  1993/02/17  21:30:25  rms
+; Fix minor bugs in previous change.
+;
+; Revision 1.18  1993/02/17  20:34:20  rms
+; (isearch-backward-regexp):
+; New arg no-recursive-edit, always non-nil for interactive call.
+; Rename first arg, and set it right in interactive call.
+; (isearch-forward-regexp): Likewise.
+; (isearch-forward, isearch-backward): Likewise no-recursive-edit.
+;
+; Revision 1.17  1993/01/26  01:48:27  jimb
+; JimB's changes since January 18th
+;
+; Revision 1.16  1992/11/16  01:37:06  jimb
+;      * bytecomp.el: Declare unread-command-char an obsolete variable.
+;      * vip.el (vip-escape-to-emacs, vip-prefix-arg-value,
+;      vip-prefix-arg-com): Use unread-command-event instead of
+;      unread-command-char; respect its new semantics.
+;      * isearch-mode.el (isearch-update, isearch-unread): Same.
+;
+; Revision 1.15  1992/11/07  06:17:04  jimb
+;         * isearch.el (isearch-frames-exist): This isn't what we want -
+;      replaced by...
+;      (isearch-gnu-emacs-events): non-nil if should expect events in the
+;      style generated by GNU Emacs 19.  Set if set-frame-height is
+;      fboundp; this is true on any GNU Emacs 19, whether or not it was
+;      compiled with multiple frame support.
+;      (isearch-mode-map): Test isearch-gnu-emacs-events instead of
+;      isearch-frames-exist to see if we should bind switch-frame events.
+;      (isearch-update): Test isearch-gnu-emacs-events instead of
+;      isearch-frames-exist to see if unread-command-char's quiescent
+;      value is nil or -1.
+;
+; Revision 1.14  1992/11/01  22:10:59  rms
+; (isearch-search): Handle all sorts of errors from regexp search.
+;
+; Revision 1.13  1992/10/27  04:11:46  rms
+; (isearch-edit-string):
+; Bind cursor-in-echo-area only around read-char/allocate-event.
+;
+; Revision 1.12  1992/10/20  21:21:47  rms
+; (isearch-mode-map): Make the top-level keymap dense.
+; Explicitly bind control characters at that level.
+;
+; Revision 1.11  1992/10/11  05:25:11  rms
+; (isearch-ring-advance-edit): Delete spurious `)'.
+;
+; Revision 1.10  1992/09/21  08:28:43  rms
+; entered into RCS
+;
 ;;; Revision 1.4  92/09/14  16:26:02  liberte
 ;;; Added prefix args to isearch-forward, etc. to switch between
 ;;;    string and regular expression searching.
 ;;; 3/18/92 Fixed invalid-regexp.
 ;;; 3/18/92 Fixed yanking in regexps.
 
+;;; Code:
 
 \f
 ;;;=========================================================================
 ;; Each of the tests below must work on any version of emacs.
 ;; (Perhaps provide and featurep could be used for this purpose.)
 
-(defconst isearch-frames-exist (fboundp 'select-frame)) ;; emacs 19
+(defconst isearch-gnu-emacs-events (fboundp 'set-frame-height)) ;; emacs 19
 (defconst isearch-pre-command-hook-exists (boundp 'pre-command-hook)) ;; lemacs
 (defconst isearch-event-data-type nil)  ;; lemacs
 
@@ -219,13 +301,18 @@ Default value, nil, means edit the string instead.")
     (let* ((i 0)
           (map (make-keymap)))
 
+      ;; 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, 
+      ;; the binding for t does not affect characters.
+      ;; We use a dense keymap to save space.
       (while (< i ?\ )
        (define-key map (make-string 1 i) 'isearch-other-control-char)
        (setq i (1+ i)))
 
       ;; Printing chars extend the selection by default.
-      ;; This assumes that all remaining chars are printable.
+      (setq i ?\ )
       (while (< i 128)
        (define-key map (make-string 1 i) 'isearch-printing-char)
        (setq i (1+ i)))
@@ -238,9 +325,6 @@ Default value, nil, means edit the string instead.")
     
       (define-key map "\C-q" 'isearch-quote-char)
 
-      ;;  (define-key map "\r" 'isearch-return-char)
-      ;; For version 19, RET (C-m) terminates search and LFD (C-j) matches eol.
-      ;; We could make this conditional.
       (define-key map "\r" 'isearch-exit)
       (define-key map "\C-j" 'isearch-printing-char)
       (define-key map "\t" 'isearch-printing-char)
@@ -249,6 +333,16 @@ Default value, nil, means edit the string instead.")
       (define-key map "\C-w" 'isearch-yank-word)
       (define-key map "\C-y" 'isearch-yank-line)
 
+      ;; Bind the ASCII-equivalent "function keys" explicitly
+      ;; if we bind their equivalents, 
+      ;; since otherwise the default binding would override.
+      ;; We bind [escape] below.
+      (define-key map [tab] 'isearch-printing-char)
+      (define-key map [delete] 'isearch-delete-char)
+      (define-key map [backspace] 'isearch-delete-char)
+      (define-key map [return] 'isearch-exit)
+      (define-key map [newline] 'isearch-printing-char)
+
       ;; Define keys for regexp chars * ? |.
       ;; Nothing special for + because it matches at least once.
       (define-key map "*" 'isearch-*-char)
@@ -271,19 +365,18 @@ Default value, nil, means edit the string instead.")
       ;; keys as well, one full keymap per char of the prefix key.  It
       ;; would be simpler to disable the global keymap, and/or have a
       ;; default local key binding for any key not otherwise bound.
-      (define-key map (char-to-string meta-prefix-char) (make-keymap))
-      (setq i 0)
-      (while (< i 128)
-       (define-key map (char-to-string (+ 128 i));; Needs to be generalized.
-         'isearch-other-meta-char)
-       (setq i (1+ i)))
+      (let ((meta-map (make-sparse-keymap)))
+       (define-key map (char-to-string meta-prefix-char) meta-map)
+       (define-key map [escape] meta-map))
+      (define-key map (vector meta-prefix-char t) 'isearch-other-meta-char)
 
       (define-key map "\M-n" 'isearch-ring-advance)
       (define-key map "\M-p" 'isearch-ring-retreat)
+
       (define-key map "\M-\t" 'isearch-complete)
 
       ;; For emacs 19, switching frames should terminate isearch-mode
-      (if isearch-frames-exist
+      (if isearch-gnu-emacs-events
          (define-key map [switch-frame] 'isearch-switch-frame-handler))
       
       (setq isearch-mode-map map)
@@ -301,8 +394,8 @@ Default value, nil, means edit the string instead.")
 (or minibuffer-local-isearch-map
     (let ((map (copy-keymap minibuffer-local-map)))
       (define-key map "\r" 'isearch-nonincremental-exit-minibuffer)
-;;      (define-key map "\M-n" 'isearch-ring-advance-edit)
-;;      (define-key map "\M-p" 'isearch-ring-retreat-edit)
+      (define-key map "\M-n" 'isearch-ring-advance-edit)
+      (define-key map "\M-p" 'isearch-ring-retreat-edit)
       (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)
@@ -379,7 +472,7 @@ Default value, nil, means edit the string instead.")
 ;;; An alternative is to fset isearch-forward etc to isearch-mode,
 ;;; and look at this-command to set the options accordingly.
 
-(defun isearch-forward (&optional regexp-p)
+(defun isearch-forward (&optional regexp-p no-recursive-edit)
   "\
 Do incremental search forward.
 With a prefix argument, do an incremental regular expression search instead.
@@ -418,34 +511,34 @@ Other control and meta characters terminate the search
 If this function is called non-interactively, it does not return to
 the calling function until the search is done."
 
-  (interactive "P")
-  (isearch-mode t (not (null regexp-p)) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
 
-(defun isearch-forward-regexp (&optional regexp-p)
+(defun isearch-forward-regexp (&optional not-regexp no-recursive-edit)
   "\
 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."
-  (interactive)
-  (isearch-mode t (null regexp-p) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
 
-(defun isearch-backward (&optional regexp-p)
+(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."
-  (interactive)
-  (isearch-mode nil (not (null regexp-p)) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
 
-(defun isearch-backward-regexp (&optional regexp-p)
+(defun isearch-backward-regexp (&optional not-regexp no-recursive-edit)
   "\
 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."
-  (interactive)
-  (isearch-mode nil (null regexp-p) nil (not (interactive-p))))
+  (interactive "P\np")
+  (isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
 
 
 (defun isearch-mode-help ()
@@ -494,8 +587,10 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
        isearch-old-local-map (current-local-map)
        search-ring-yank-pointer nil
        regexp-search-ring-yank-pointer nil)
-  (if isearch-pre-command-hook-exists
-      (add-hook 'pre-command-hook 'isearch-pre-command-hook))
+;; This was for Lucid Emacs.  But now that we have pre-command-hook,
+;; it causes trouble.
+;;  (if isearch-pre-command-hook-exists
+;;      (add-hook 'pre-command-hook 'isearch-pre-command-hook))
   (setq        isearch-mode " Isearch")  ;; forward? regexp?
   (set-buffer-modified-p (buffer-modified-p)) ; update modeline
 
@@ -519,8 +614,8 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   ;; Called after each command to update the display.  
   (if (if isearch-event-data-type
          (null unread-command-event)
-       (if isearch-frames-exist
-           (null unread-command-char)
+       (if isearch-gnu-emacs-events
+           (null unread-command-events)
          (< unread-command-char 0)))
       (progn
        (if (not (input-pending-p))
@@ -555,8 +650,9 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   )
 
 
-(defun isearch-done ()
+(defun isearch-done (&optional nopush)
   ;; Called by all commands that terminate isearch-mode.
+  ;; If NOPUSH is non-nil, we don't push the string on the search ring.
   (use-local-map isearch-old-local-map)
   ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs
   (isearch-dehighlight t)
@@ -578,7 +674,7 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   (setq isearch-mode nil)
   (set-buffer-modified-p (buffer-modified-p))  ;; update modeline
 
-  (if (> (length isearch-string) 0)
+  (if (and (> (length isearch-string) 0) (not nopush))
       ;; Update the ring data.
       (if isearch-regexp 
          (if (or (null regexp-search-ring)
@@ -609,7 +705,7 @@ is treated as a regexp.  See \\[isearch-forward] for more info."
   (interactive) ;; Is this necessary?
   ;; First terminate isearch-mode.
   (isearch-done)
-  (select-frame (car (cdr (isearch-last-command-char)))))
+  (handle-switch-frame (car (cdr (isearch-last-command-char)))))
 
 ;;;========================================================
 
@@ -684,15 +780,16 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
        ;; 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)
+           (isearch-done t)
          (exit nil))                   ; was recursive editing
 
        (isearch-message) ;; for read-char
        (unwind-protect
            (let* (;; Why does following read-char echo?  
                   ;;(echo-keystrokes 0) ;; not needed with above message
-                  (cursor-in-echo-area t)
-                  (e (if isearch-event-data-type (allocate-event) (read-char)))
+                  (e (let ((cursor-in-echo-area t))
+                       (if isearch-event-data-type
+                           (allocate-event) (read-char))))
                   ;; Binding minibuffer-history-symbol to nil is a work-around
                   ;; for some incompatibility with gmhist.
                   (minibuffer-history-symbol))
@@ -715,20 +812,11 @@ If first char entered is \\[isearch-yank-word], then do word search instead."
                (isearch-unread e))
              (setq cursor-in-echo-area nil)
              (setq isearch-new-string
-                   (let ((search-ring search-ring)
-                         (regexp-search-ring regexp-search-ring))
+                   (let (junk-ring)
                      (read-from-minibuffer (isearch-message-prefix)
                                            isearch-string
                                            minibuffer-local-isearch-map nil
-                                           (cons
-                                            (if isearch-regexp
-                                                'regexp-search-ring
-                                              'search-ring)
-                                            (or
-                                             (if isearch-regexp
-                                                 regexp-search-ring-yank-pointer
-                                               search-ring-yank-pointer)
-                                             0))))
+                                           'junk-ring))
                    isearch-new-message (mapconcat 'text-char-description
                                                   isearch-new-string "")))
          ;; Always resume isearching by restarting it.
@@ -793,7 +881,7 @@ Use `isearch-exit' to quit without signalling."
       ;; If search is successful, move back to starting point
       ;; and really do quit.
       (progn (goto-char isearch-opoint)
-            (isearch-done)   ; exit isearch
+            (isearch-done t)   ; exit isearch
             (signal 'quit nil))  ; and pass on quit signal
     ;; If search is failing, rub out until it is once more successful.
     (while (not isearch-success) (isearch-pop-state))
@@ -977,49 +1065,25 @@ If no previous match was done, just beep."
   (isearch-process-search-char (isearch-last-command-char)))
 
 
-(defun isearch-other-control-char ()
-  "Any other control char => unread it and exit the search normally.
-But only if `search-exit-option' is non-nil, the default.
-If it is the symbol `edit', the search string is edited in the minibuffer
-and the control char is unread so that it is applied to the editing."
-  (interactive)
-  (cond
-   ((eq search-exit-option 'edit)
-    (isearch-unread (isearch-last-command-char))
-    (isearch-edit-string))
-   (search-exit-option  ;; any other non-nil value
-    (isearch-unread (isearch-last-command-char))
-    (isearch-done))
-   (t ;; search-exit-option is nil
-    (isearch-process-search-char (isearch-last-command-char)))
-   ))
-
+(fset 'isearch-other-control-char 'isearch-other-meta-char)
 
 (defun isearch-other-meta-char ()
-  "Any other meta char => exit the search normally and reexecute the whole key.
-But only if `search-exit-option' is non-nil."
-  ;; This will probably work in place of isearch-other-control-char too,
-  ;; but here we use unwind-protect and command-execute since it is
-  ;; a multi-char key we would want to unread.
+  "Exit the search normally and reread this key sequence.
+But only if `search-exit-option' is non-nil, the default.
+If it is the symbol `edit', the search string is edited in the minibuffer
+and the meta character is unread so that it applies to editing the string."
   (interactive)
-  (cond
-   (search-exit-option
-    (unwind-protect
-       ;; Exit recursive edit and restore the outside keymap.
-       (isearch-done)
-      ;; Reexecute the key with the outside keymap.
-      ;; Note: this doesnt work unless the entered key is the same 
-      ;; as some outside key since command-execute only takes whole keys.
-      ;; So three character keys typically will not work!
-      ;; Also, executing the command here may not work if isearch was
-      ;; invoked non-interactively, since other input may be expected.
-      ;; We also can't do isearch-edit-string as in -other-control-char.
-      ;; because we need to set unread-command-key, if that existed.
-      ;; So a new unread-command-key would solve all these problems.
-      (command-execute (this-command-keys))))
-   (t  ;; otherwise nil
-    (isearch-process-search-string (this-command-keys) (this-command-keys))
-    )))
+  (cond ((eq search-exit-option 'edit)
+        (let ((key (this-command-keys)))
+          (apply 'isearch-unread (listify-key-sequence key)))
+        (isearch-edit-string))
+       (search-exit-option
+        (let ((key (this-command-keys)))
+          (apply 'isearch-unread (listify-key-sequence key)))
+        (isearch-done))
+       (t;; otherwise nil
+        (isearch-process-search-string (this-command-keys)
+                                       (this-command-keys)))))
 
 
 (defun isearch-quote-char ()
@@ -1125,22 +1189,14 @@ If not in regexp mode, activate word search."
       (set yank-pointer-name
           (setq yank-pointer
                 (% (+ (or yank-pointer 0)
-                      (if advance (+ length (% n length))))
+                      ;; Add LENGTH here to ensure a positive result.
+                      length
+                      (% (- n) length))
                    length)))
 
-    (if (= minibuffer-history-position narg)
-       (error (if (= minibuffer-history-position 1)
-                  "End of history; no next item"
-                "Beginning of history; no preceding item"))
       (erase-buffer)
-      (setq minibuffer-history-position narg)
-      (let ((elt (nth (1- minibuffer-history-position)
-                     (symbol-value minibuffer-history-variable))))
-       (insert
-        (if minibuffer-history-sexp-flag
-            (prin1-to-string elt)
-          elt)))
-      (goto-char (point-min))))))
+      (insert (nth yank-pointer ring))
+      (goto-char (point-max)))))
 
 (defun isearch-ring-retreat-edit (n)
   "Inserts the previous element of the search history into the minibuffer."
@@ -1316,7 +1372,10 @@ If there is no completion possible, say so and continue searching."
      (if (string-match
          "\\`Premature \\|\\`Unmatched \\|\\`Invalid "
          isearch-invalid-regexp)
-        (setq isearch-invalid-regexp "incomplete input"))))
+        (setq isearch-invalid-regexp "incomplete input")))
+    (error
+     ;; stack overflow in regexp search.
+     (setq isearch-invalid-regexp (car (cdr lossage)))))
 
   (if isearch-success
       nil
@@ -1398,6 +1457,7 @@ have special meaning in a regexp."
 
 ;; To quiet the byte-compiler.
 (defvar unread-command-event)
+(defvar unread-command-events)
 (defvar last-command-event)
 
 (defun isearch-char-to-string (c)
@@ -1408,11 +1468,20 @@ have special meaning in a regexp."
 (defun isearch-text-char-description (c)
   (isearch-char-to-string c))
 
-(defun isearch-unread (char-or-event)
-  ;; General function to unread a character or event.
-  (if isearch-event-data-type
-      (setq unread-command-event char-or-event)
-    (setq unread-command-char char-or-event)))
+(defun isearch-unread (&rest char-or-events)
+  ;; General function to unread characters or events.
+  (if isearch-gnu-emacs-events
+      (setq unread-command-events
+           (append char-or-events unread-command-events))
+    (let ((char (if (cdr char-or-events)
+                   (progn
+                     (while (cdr char-or-events)
+                       (setq char-or-events (cdr char-or-events)))
+                     (+ 128 (car char-or-events)))
+                 (car char-or-events))))
+      (if isearch-event-data-type
+         (setq unread-command-event char)
+       (setq unread-command-char char)))))
 
 (defun isearch-last-command-char ()
   ;; General function to return the last command character.
@@ -1523,3 +1592,5 @@ have special meaning in a regexp."
 ;;     ))
 
 ;;))
+
+;;; isearch.el ends here