X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/a8f783b2195993d23955968bdff96b739f904b79..dba1ec5561d98290d8a450c5b3e939363e7f9176:/lisp/isearch.el diff --git a/lisp/isearch.el b/lisp/isearch.el index 4b694846e7..85b8924ac0 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -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 + +;; |$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 @@ -85,11 +87,90 @@ ;; - 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. @@ -123,6 +204,7 @@ ;;; 3/18/92 Fixed invalid-regexp. ;;; 3/18/92 Fixed yanking in regexps. +;;; Code: ;;;========================================================================= @@ -134,7 +216,7 @@ ;; 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