X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/1a3a6707240ac01920c578693969d4d96c0d1059..6696af6580eea3a04f6459758b78817ee0f9d216:/lisp/isearch.el diff --git a/lisp/isearch.el b/lisp/isearch.el index b5c47ede4f..3bcc23a2f9 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -1,58 +1,37 @@ -;; Incremental search minor mode. -;; Copyright (C) 1992 Free Software Foundation, Inc. +;;; isearch.el --- incremental search minor mode. -;; LCD Archive Entry: -;; isearch-mode|Daniel LaLiberte|liberte@cs.uiuc.edu -;; |A minor mode replacement for isearch.el. -;; |$Date: 1992/11/01 22:10:59 $|$Revision: 1.14 $|~/modes/isearch-mode.el +;; Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. -;; This file is not yet part of GNU Emacs, but it is based almost -;; entirely on isearch.el which is part of GNU Emacs. +;; Author: Daniel LaLiberte -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY. No author or distributor -;; accepts responsibility to anyone for the consequences of using it -;; or for whether it serves any particular purpose or works at all, -;; unless he says so in writing. Refer to the GNU Emacs General Public -;; License for full details. - -;; Everyone is granted permission to copy, modify and redistribute -;; GNU Emacs, but only under the conditions described in the -;; GNU Emacs General Public License. A copy of this license is -;; supposed to have been given to you along with GNU Emacs so you -;; can know your rights and responsibilities. It should be in a -;; file named COPYING. Among other things, the copyright notice -;; and this notice must be preserved on all copies. +;; |$Date: 1994/08/30 07:03:33 $|$Revision: 1.72 $ -;;;==================================================================== -;; Instructions +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. -;; Searching with isearch-mode.el should work just like isearch.el, -;; except it is done in a temporary minor mode that terminates when -;; you finish searching. +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. -;; To use isearch-mode instead of the standard isearch.el, add the -;; following to your .emacs file. The standard key bindings to -;; isearch-forward, etc, will then use isearch-mode instead of -;; isearch. +;;; Commentary: -;; (fset 'isearch 'isearch-mode) -;; (autoload 'isearch-mode "isearch-mode") +;;;==================================================================== +;; Instructions ;; For programmed use of isearch-mode, e.g. calling (isearch-forward), ;; isearch-mode behaves modally and does not return until the search ;; is completed. It uses a recursive-edit to behave this way. Note: ;; gnus does it wrong: (call-interactively 'isearch-forward). -;; If any package you use invokes isearching non-interactively to get -;; the modal behavior described above, you must use the redefinitions -;; of isearch-forward, etc. found in this file instead of those in -;; loaddefs.el. The simplest way to ensure this is to just load -;; isearch-mode explicitly in your .emacs instead of using the above -;; fset and autoload. - -;; (load "isearch-mode") - ;; The key bindings active within isearch-mode are defined below in ;; `isearch-mode-map' which is given bindings close to the default ;; characters of the original isearch.el. With `isearch-mode', @@ -81,32 +60,14 @@ ;; the last possible moment. ;; TODO -;; - Integrate the emacs 19 generalized commmand history. +;; - Integrate the emacs 19 generalized command history. ;; - Think about incorporating query-replace. ;; - Hooks and options for failed search. -;;;==================================================================== -;;; Change History - -;;; $Header: /gd/gnu/emacs/19.0/lisp/RCS/isearch-mode.el,v 1.14 1992/11/01 22:10:59 rms Exp $ -;;; $Log: isearch-mode.el,v $ -; 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 -; +;;; Change Log: + +;;; Changes before those recorded in ChangeLog: + ;;; 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. @@ -140,6 +101,7 @@ ;;; 3/18/92 Fixed invalid-regexp. ;;; 3/18/92 Fixed yanking in regexps. +;;; Code: ;;;========================================================================= @@ -172,7 +134,7 @@ that the search has reached.") ;;;======================================================================== ;;; Some additional options and constants. -(defvar search-upper-case t +(defvar search-upper-case 'not-yanks "*If non-nil, upper case chars disable case fold searching. That is, upper and lower case chars must match exactly. This applies no matter where the chars come from, but does not @@ -192,9 +154,7 @@ You might want to use something like \"[ \\t\\r\\n]+\" instead.") ;; currently a clean thing to do. Once highlighting is made clean, ;; this feature can be re-enabled and advertised. (defvar search-highlight nil - "Whether isearch and query-replace should highlight the text which -currently matches the search-string.") - + "*Non-nil means incremental search highlights the current match.") (defvar isearch-mode-hook nil "Function(s) to call after starting up an incremental search.") @@ -235,6 +195,11 @@ Default value, nil, means edit the string instead.") (or isearch-mode-map (let* ((i 0) (map (make-keymap))) + (or (vectorp (nth 1 map)) + (error "The initialization of isearch-mode-map must be updated")) + ;; Give this map a vector 256 long, for dense binding + ;; of a larger range of ordinary characters. + (setcar (cdr map) (make-vector 256 nil)) ;; Make function keys, etc, exit the search. (define-key map [t] 'isearch-other-control-char) @@ -246,10 +211,10 @@ Default value, nil, means edit the string instead.") (define-key map (make-string 1 i) 'isearch-other-control-char) (setq i (1+ i))) - ;; Printing chars extend the selection by default. + ;; Printing chars extend the search string by default. (setq i ?\ ) - (while (< i 128) - (define-key map (make-string 1 i) 'isearch-printing-char) + (while (< i (length (nth 1 map))) + (define-key map (vector i) 'isearch-printing-char) (setq i (1+ i))) ;; Several non-printing chars change the searching behavior. @@ -260,9 +225,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) @@ -271,38 +233,60 @@ 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 to nil + ;; so that the default binding does not apply. + ;; As a result, these keys translate thru function-key-map + ;; as normal, and they have the effect of the equivalent ASCII char. + ;; We bind [escape] below. + (define-key map [tab] 'nil) + (define-key map [kp-0] 'nil) + (define-key map [kp-1] 'nil) + (define-key map [kp-2] 'nil) + (define-key map [kp-3] 'nil) + (define-key map [kp-4] 'nil) + (define-key map [kp-5] 'nil) + (define-key map [kp-6] 'nil) + (define-key map [kp-7] 'nil) + (define-key map [kp-8] 'nil) + (define-key map [kp-9] 'nil) + (define-key map [kp-add] 'nil) + (define-key map [kp-subtract] 'nil) + (define-key map [kp-multiply] 'nil) + (define-key map [kp-divide] 'nil) + (define-key map [kp-decimal] 'nil) + (define-key map [kp-separator] 'nil) + (define-key map [kp-equal] 'nil) + (define-key map [kp-tab] 'nil) + (define-key map [kp-space] 'nil) + (define-key map [kp-enter] 'nil) + (define-key map [delete] 'nil) + (define-key map [backspace] 'nil) + (define-key map [return] 'nil) + (define-key map [newline] 'nil) + ;; Define keys for regexp chars * ? |. ;; Nothing special for + because it matches at least once. (define-key map "*" 'isearch-*-char) (define-key map "?" 'isearch-*-char) (define-key map "|" 'isearch-|-char) - ;; You can reenable global keys by binding them locally to nil. - ;; For the help char this doesnt work quite as expected because - ;; isearch-mode is not a major mode. Also the echo area is not - ;; restored after the help command while isearch-mode is - ;; still active. Furthermore, we should not assume that the - ;; help-command is on C-h. But here is how it would be done: - ;; (define-key map "\C-h" nil) - - ;; Instead bind C-h to special help command for isearch-mode. - (define-key map "\C-h" 'isearch-mode-help) +;;; Turned off because I find I expect to get the global definition--rms. +;;; ;; Instead bind C-h to special help command for isearch-mode. +;;; (define-key map "\C-h" 'isearch-mode-help) ;; To handle local bindings with meta char prefix keys, define ;; another full keymap. This must be done for any other prefix ;; 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-sparse-keymap)) + (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) -;;; (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))) (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-\t" 'isearch-complete) @@ -315,6 +299,7 @@ Default value, nil, means edit the string instead.") ;; Some bindings you may want to put in your isearch-mode-hook. ;; Suggest some alternates... +;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-case-fold) ;; (define-key isearch-mode-map "\C-t" 'isearch-toggle-regexp) ;; (define-key isearch-mode-map "\C-^" 'isearch-edit-string) @@ -348,11 +333,15 @@ Default value, nil, means edit the string instead.") (defvar isearch-success t) ; Searching is currently successful. (defvar isearch-invalid-regexp nil) ; Regexp not well formed. +(defvar isearch-within-brackets nil) ; Regexp has unclosed [. (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-case-fold-search nil) ; case-fold-search while searching. +; case-fold-search while searching. +; either nil, t, or 'yes. 'yes means the same as t except that mixed +; case in the search string is ignored. +(defvar isearch-case-fold-search nil) (defvar isearch-adjusted nil) (defvar isearch-slow-terminal-mode nil) @@ -361,7 +350,6 @@ Default value, nil, means edit the string instead.") (defvar isearch-opoint 0) ;;; The window configuration active at the beginning of the search. (defvar isearch-window-configuration nil) -(defvar isearch-old-local-map nil) ;; Flag to indicate a yank occurred, so don't move the cursor. (defvar isearch-yank-flag nil) @@ -400,10 +388,10 @@ Default value, nil, means edit the string instead.") ;;;=============================================================== ;;; Entry points to isearch-mode. ;;; These four functions should replace those in loaddefs.el -;;; An alternative is to fset isearch-forward etc to isearch-mode, +;;; An alternative is to defalias 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. @@ -421,7 +409,6 @@ Type \\[isearch-yank-word] to yank word 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-quote-char] to quote control character to search for it. -Type \\[isearch-whitespace-chars] to match all whitespace chars in regexp. \\[isearch-abort] while searching or when search has failed cancels input\ back to what has been found successfully. @@ -442,34 +429,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 () @@ -506,6 +493,7 @@ is treated as a regexp. See \\[isearch-forward] for more info." isearch-adjusted nil isearch-yank-flag nil isearch-invalid-regexp nil + isearch-within-brackets nil ;; Use (baud-rate) for now, for sake of other versions. isearch-slow-terminal-mode (and (<= (baud-rate) search-slow-speed) (> (window-height) @@ -514,26 +502,36 @@ is treated as a regexp. See \\[isearch-forward] for more info." isearch-small-window nil isearch-opoint (point) - isearch-window-configuration (current-window-configuration) - 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)) + (setq isearch-window-configuration + (if isearch-slow-terminal-mode (current-window-configuration) nil)) + +;; 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 + ;; It is ugly to show region highlighting while the search + ;; is going on. And we don't want the mark active at the end either. + (setq deactivate-mark t) + (isearch-push-state) - (use-local-map isearch-mode-map) + (make-local-variable 'overriding-local-map) + (setq overriding-local-map isearch-mode-map) (isearch-update) (run-hooks 'isearch-mode-hook) ;; isearch-mode can be made modal (in the sense of not returning to ;; the calling function until searching is completed) by entering ;; a recursive-edit and exiting it when done isearching. - (if recursive-edit (recursive-edit)) - ) + (if recursive-edit + (let ((isearch-recursive-edit t)) + (recursive-edit))) + isearch-success) ;;;==================================================== @@ -544,7 +542,7 @@ is treated as a regexp. See \\[isearch-forward] for more info." (if (if isearch-event-data-type (null unread-command-event) (if isearch-gnu-emacs-events - (null unread-command-char) + (null unread-command-events) (< unread-command-char 0))) (progn (if (not (input-pending-p)) @@ -571,7 +569,8 @@ is treated as a regexp. See \\[isearch-forward] for more info." (if isearch-other-end (if (< isearch-other-end (point)) ; isearch-forward? (isearch-highlight isearch-other-end (point)) - (isearch-highlight (point) isearch-other-end))) + (isearch-highlight (point) isearch-other-end)) + (isearch-dehighlight nil)) )) (setq ;; quit-flag nil not for isearch-mode isearch-adjusted nil @@ -579,26 +578,31 @@ is treated as a regexp. See \\[isearch-forward] for more info." ) -(defun isearch-done (&optional nopush) +(defun isearch-done (&optional nopush edit) ;; 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 overriding-local-map nil) ;; (setq pre-command-hook isearch-old-pre-command-hook) ; for lemacs (isearch-dehighlight t) (let ((found-start (window-start (selected-window))) (found-point (point))) - (set-window-configuration isearch-window-configuration) + (if isearch-window-configuration + (set-window-configuration isearch-window-configuration)) + + (if isearch-small-window + (goto-char found-point) + ;; Exiting the save-window-excursion clobbers window-start; restore it. + (set-window-start (selected-window) found-start t))) ;; If there was movement, mark the starting position. ;; Maybe should test difference between and set mark iff > threshold. (if (/= (point) isearch-opoint) - (push-mark isearch-opoint) + (progn + (push-mark isearch-opoint t) + (or executing-macro (> (minibuffer-depth) 0) + (message "Mark saved where search started"))) ;; (message "") why is this needed? ) - (if isearch-small-window - (goto-char found-point) - ;; Exiting the save-window-excursion clobbers window-start; restore it. - (set-window-start (selected-window) found-start t))) (setq isearch-mode nil) (set-buffer-modified-p (buffer-modified-p)) ;; update modeline @@ -622,11 +626,11 @@ is treated as a regexp. See \\[isearch-forward] for more info." (setcdr (nthcdr (1- search-ring-max) search-ring) nil)))))) (run-hooks 'isearch-mode-end-hook) - (if isearch-recursive-edit (exit-recursive-edit))) + (and (not edit) isearch-recursive-edit (exit-recursive-edit))) ;;;======================================================= ;;; Switching buffers should first terminate isearch-mode. -;;; This is done quite differently for each varient of emacs. +;;; This is done quite differently for each variant of emacs. ;;; For lemacs, see Exiting in lemacs below ;; For Emacs 19, the frame switch event is handled. @@ -634,7 +638,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))))) ;;;======================================================== @@ -662,21 +666,21 @@ The following additional command keys are active while editing. \\[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-backward-exit-minibuffer] to resume isearching backward. +\\[isearch-reverse-exit-minibuffer] to resume isearching backward. \\[isearch-ring-advance-edit] to replace the search string with the next item in the search ring. -\\[isearch-ring-retreat-edit] to replace the search string with the previou item in the search ring. +\\[isearch-ring-retreat-edit] to replace the search string with the previous item in the search ring. \\[isearch-complete-edit] to complete the search string using the search ring. - +\\ If first char entered is \\[isearch-yank-word], then do word search instead." ;; 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 doesnt back up the search point. Should it? + ;; Editing doesn't back up the search point. Should it? (interactive) (condition-case err - (let (isearch-nonincremental ; should search nonincrementally? + (let ((isearch-nonincremental isearch-nonincremental) ;; Locally bind all isearch global variables to protect them ;; from recursive isearching. @@ -696,6 +700,7 @@ If first char entered is \\[isearch-yank-word], then do word search instead." (isearch-adjusted isearch-adjusted) (isearch-yank-flag isearch-yank-flag) (isearch-invalid-regexp isearch-invalid-regexp) + (isearch-within-brackets isearch-within-brackets) (isearch-other-end isearch-other-end) (isearch-opoint isearch-opoint) (isearch-slow-terminal-mode isearch-slow-terminal-mode) @@ -709,7 +714,7 @@ 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 t) + (isearch-done t t) (exit nil)) ; was recursive editing (isearch-message) ;; for read-char @@ -717,8 +722,7 @@ If first char entered is \\[isearch-yank-word], then do word search instead." (let* (;; Why does following read-char echo? ;;(echo-keystrokes 0) ;; not needed with above message (e (let ((cursor-in-echo-area t)) - (if isearch-event-data-type - (allocate-event) (read-char)))) + (read-event))) ;; Binding minibuffer-history-symbol to nil is a work-around ;; for some incompatibility with gmhist. (minibuffer-history-symbol)) @@ -730,12 +734,7 @@ If first char entered is \\[isearch-yank-word], then do word search instead." ;; no check is made here. (message (isearch-message-prefix nil nil t)) (if (eq 'isearch-yank-word - (lookup-key - isearch-mode-map - (char-to-string - (if isearch-event-data-type - (or (event-to-character (next-command-event e)) 0) - e)))) + (lookup-key isearch-mode-map (vector e))) (setq isearch-word t ;; so message-prefix is right isearch-new-word t) (isearch-unread e)) @@ -746,13 +745,14 @@ If first char entered is \\[isearch-yank-word], then do word search instead." isearch-string minibuffer-local-isearch-map nil 'junk-ring)) - isearch-new-message (mapconcat 'text-char-description - isearch-new-string ""))) + isearch-new-message + (mapconcat 'isearch-text-char-description + isearch-new-string ""))) ;; Always resume isearching by restarting it. (isearch-mode isearch-forward isearch-regexp isearch-op-fun - isearch-recursive-edit + nil isearch-word) ;; Copy new local values to isearch globals @@ -804,7 +804,7 @@ If first char entered is \\[isearch-yank-word], then do word search instead." Otherwise, revert to previous successful search and continue searching. Use `isearch-exit' to quit without signalling." (interactive) -;; (ding) signal instead below, if quiting +;; (ding) signal instead below, if quitting (discard-input) (if isearch-success ;; If search is successful, move back to starting point @@ -841,14 +841,21 @@ Use `isearch-exit' to quit without signalling." (setq isearch-forward (not isearch-forward))) (setq isearch-barrier (point)) ; For subsequent \| if regexp. - (setq isearch-success t) - (or (equal isearch-string "") - (progn + + (if (equal isearch-string "") + (setq isearch-success t) + (if (and isearch-success (equal (match-end 0) (match-beginning 0))) ;; If repeating a search that found ;; an empty string, ensure we advance. - (if (equal (match-end 0) (match-beginning 0)) - (forward-char (if isearch-forward 1 -1))) - (isearch-search))) + (if (if isearch-forward (eobp) (bobp)) + ;; If there's nowhere to advance to, fail (and wrap next time). + (progn + (setq isearch-success nil) + (ding)) + (forward-char (if isearch-forward 1 -1)) + (isearch-search)) + (isearch-search))) + (isearch-push-state) (isearch-update)) @@ -870,6 +877,19 @@ Use `isearch-exit' to quit without signalling." (if isearch-regexp (setq isearch-word nil)) (isearch-update)) +(defun isearch-toggle-case-fold () + "Toggle case folding in searching on or off." + (interactive) + (setq isearch-case-fold-search + (if isearch-case-fold-search nil 'yes)) + (message "%s%s [case %ssensitive]" + (isearch-message-prefix) + isearch-message + (if isearch-case-fold-search "in" "")) + (setq isearch-adjusted t) + (sit-for 1) + (isearch-update)) + (defun isearch-delete-char () "Discard last input item and move point back. If no previous match was done, just beep." @@ -882,18 +902,23 @@ If no previous match was done, just beep." (defun isearch-yank (chunk) ;; Helper for isearch-yank-word and isearch-yank-line - (let ((string (save-excursion - (and (not isearch-forward) isearch-other-end - (goto-char isearch-other-end)) - (buffer-substring - (point) - (save-excursion - (cond - ((eq chunk 'word) - (forward-word 1)) - ((eq chunk 'line) - (end-of-line))) - (point)))))) + ;; CHUNK should be word, line or kill. + (let ((string (cond + ((eq chunk 'kill) + (current-kill 0)) + (t + (save-excursion + (and (not isearch-forward) isearch-other-end + (goto-char isearch-other-end)) + (buffer-substring + (point) + (save-excursion + (cond + ((eq chunk 'word) + (forward-word 1)) + ((eq chunk 'line) + (end-of-line))) + (point)))))))) ;; Downcase the string if not supposed to case-fold yanked strings. (if (and isearch-case-fold-search (eq 'not-yanks search-upper-case)) @@ -908,6 +933,10 @@ If no previous match was done, just beep." isearch-yank-flag t)) (isearch-search-and-update)) +(defun isearch-yank-kill () + "Pull string from kill ring into search string." + (interactive) + (isearch-yank 'kill)) (defun isearch-yank-word () "Pull next word from buffer into search string." @@ -943,6 +972,7 @@ If no previous match was done, just beep." (min isearch-opoint isearch-barrier)))) (setq isearch-success t isearch-invalid-regexp nil + isearch-within-brackets nil isearch-other-end (match-end 0)) ;; Not regexp, not reverse, or no match at point. (if (and isearch-other-end (not isearch-adjusted)) @@ -994,41 +1024,46 @@ 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 applies to editing the string." - (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))))) - +(defalias 'isearch-other-control-char 'isearch-other-meta-char) (defun isearch-other-meta-char () - "Any other meta char => exit the search normally and reread the character. + "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 ((eq search-exit-option 'edit) (let ((key (this-command-keys))) - (isearch-unread (+ 128 (aref key (1- (length key)))))) + (apply 'isearch-unread (listify-key-sequence key))) (isearch-edit-string)) (search-exit-option - (let ((key (this-command-keys))) - (isearch-unread (+ 128 (aref key (1- (length key)))))) - (isearch-done)) + (let ((key (this-command-keys)) + (index 0) + window) + (apply 'isearch-unread (listify-key-sequence key)) + ;; Properly handle scroll-bar and mode-line clicks + ;; for which a dummy prefix event was generated as (aref key 0). + (and (> (length key) 1) + (symbolp (aref key 0)) + (listp (aref key 1)) + ;; These events now have a symbol; they used to have a list. + ;; Accept either one. Other events have a number here. + (not (numberp (posn-point (event-start (aref key 1))))) + (setq index 1)) + ;; If we got a mouse click, maybe it was read with the buffer + ;; it was clicked on. If so, that buffer, not the current one, + ;; is in isearch mode. So end the search in that buffer. + (if (and (listp (aref key index)) + (setq window (posn-window (event-start (aref key index)))) + (windowp window)) + (save-excursion + (set-buffer (window-buffer window)) + (isearch-done)) + (isearch-done)))) (t;; otherwise nil (isearch-process-search-string (this-command-keys) (this-command-keys))))) - (defun isearch-quote-char () "Quote special characters for incremental search." (interactive) @@ -1041,20 +1076,20 @@ Obsolete." (isearch-process-search-char ?\n)) (defun isearch-printing-char () - "Any other printing character => add it to the search string and search." + "Add this ordinary printing character to the search string and search." (interactive) (isearch-process-search-char (isearch-last-command-char))) (defun isearch-whitespace-chars () "Match all whitespace chars, if in regexp mode. -If not in regexp mode, activate word search." +If you want to search for just a space, type C-q SPC." (interactive) (if isearch-regexp - (if search-whitespace-regexp + (if (and search-whitespace-regexp (not isearch-within-brackets)) (isearch-process-search-string search-whitespace-regexp " ") (isearch-printing-char)) (progn - ;; This way of doing word search doesnt correctly extend current search. + ;; This way of doing word search doesn't correctly extend current search. ;; (setq isearch-word t) ;; (setq isearch-adjusted t) ;; (goto-char isearch-barrier) @@ -1087,9 +1122,9 @@ If not in regexp mode, activate word search." () (set yank-pointer-name (setq yank-pointer - (% (+ (or yank-pointer 0) - (if advance (1- length) 1)) - length))) + (mod (+ (or yank-pointer 0) + (if advance -1 1)) + length))) (setq isearch-string (nth yank-pointer ring) isearch-message (mapconcat 'isearch-text-char-description isearch-string ""))))) @@ -1131,11 +1166,8 @@ If not in regexp mode, activate word search." () (set yank-pointer-name (setq yank-pointer - (% (+ (or yank-pointer 0) - ;; Add LENGTH here to ensure a positive result. - length - (% (- n) length)) - length))) + (mod (- (or yank-pointer 0) n) + length))) (erase-buffer) (insert (nth yank-pointer ring)) @@ -1221,7 +1253,9 @@ If there is no completion possible, say so and continue searching." isearch-word (nth 6 cmd) isearch-invalid-regexp (nth 7 cmd) isearch-wrapped (nth 8 cmd) - isearch-barrier (nth 9 cmd)) + isearch-barrier (nth 9 cmd) + isearch-within-brackets (nth 10 cmd) + isearch-case-fold-search (nth 11 cmd)) (goto-char (car (cdr (cdr cmd)))))) (defun isearch-pop-state () @@ -1234,7 +1268,8 @@ If there is no completion possible, say so and continue searching." (cons (list isearch-string isearch-message (point) isearch-success isearch-forward isearch-other-end isearch-word - isearch-invalid-regexp isearch-wrapped isearch-barrier) + isearch-invalid-regexp isearch-wrapped isearch-barrier + isearch-within-brackets isearch-case-fold-search) isearch-cmds))) @@ -1258,7 +1293,8 @@ If there is no completion possible, say so and continue searching." (and isearch-invalid-regexp ellipsis (condition-case () (progn (re-search-forward isearch-string (point) t) - (setq isearch-invalid-regexp nil)) + (setq isearch-invalid-regexp nil + isearch-within-brackets nil)) (error nil))) ;; If currently failing, display no ellipsis. (or isearch-success (setq ellipsis nil)) @@ -1286,12 +1322,14 @@ If there is no completion possible, say so and continue searching." (defun isearch-search () ;; Do the search with the current search string. (isearch-message nil t) - (if search-upper-case - (setq isearch-case-fold-search (isearch-no-upper-case-p isearch-string))) + (if (and (eq isearch-case-fold-search t) search-upper-case) + (setq isearch-case-fold-search + (isearch-no-upper-case-p isearch-string isearch-regexp))) (condition-case lossage (let ((inhibit-quit nil) (case-fold-search isearch-case-fold-search)) (if isearch-regexp (setq isearch-invalid-regexp nil)) + (setq isearch-within-brackets nil) (setq isearch-success (funcall (cond (isearch-word @@ -1312,6 +1350,8 @@ If there is no completion possible, say so and continue searching." (invalid-regexp (setq isearch-invalid-regexp (car (cdr lossage))) + (setq isearch-within-brackets (string-match "\\`Unmatched \\[" + isearch-invalid-regexp)) (if (string-match "\\`Premature \\|\\`Unmatched \\|\\`Invalid " isearch-invalid-regexp) @@ -1332,89 +1372,69 @@ If there is no completion possible, say so and continue searching." ;;;======================================================== ;;; Highlighting -(defun isearch-highlight (begin end)) -(defun isearch-dehighlight (totally)) +(defvar isearch-overlay nil) -;; lemacs uses faces -'(progn -(defvar isearch-extent nil) - -(or (find-face 'isearch) ;; this face is initialized by x-faces.el - (make-face 'isearch)) ;; since isearch is preloaded - -(defun isearch-lemacs-highlight (begin end) - (if (null isearch-highlight) +(defun isearch-highlight (beg end) + (if (or (null search-highlight) (null window-system)) nil - (if (and (extentp isearch-extent) - (eq (extent-buffer isearch-extent) (current-buffer))) - (set-extent-endpoints isearch-extent begin end) - (if (and (extentp isearch-extent) - (bufferp (extent-buffer isearch-extent)) - (buffer-name (extent-buffer isearch-extent))) - (delete-extent isearch-extent)) - (setq isearch-extent (make-extent begin end (current-buffer)))) - (set-extent-face isearch-extent 'isearch))) - -(defun isearch-lemacs-dehighlight (totally) - (if (and isearch-highlight isearch-extent) - (if totally - (let ((inhibit-quit t)) - (if (and (extentp isearch-extent) - (bufferp (extent-buffer isearch-extent)) - (buffer-name (extent-buffer isearch-extent))) - (delete-extent isearch-extent)) - (setq isearch-extent nil)) - (if (and (extentp isearch-extent) - (bufferp (extent-buffer isearch-extent)) - (buffer-name (extent-buffer isearch-extent))) - (set-extent-face isearch-extent 'default) - (isearch-dehighlight t))))) - -(fset 'isearch-highlight (symbol-function 'isearch-lemacs-highlight)) -(fset 'isearch-dehighlight (symbol-function 'isearch-lemacs-dehighlight)) -) + (or isearch-overlay (setq isearch-overlay (make-overlay beg end))) + (move-overlay isearch-overlay beg end (current-buffer)) + (overlay-put isearch-overlay 'face + (if (internal-find-face 'isearch nil) + 'isearch 'region)))) + +(defun isearch-dehighlight (totally) + (if isearch-overlay + (delete-overlay isearch-overlay))) ;;;=========================================================== ;;; General utilities -;; (fset 'isearch-member-equal (symbol-function 'member)) ; for emacs 19 - -(defun isearch-member-equal (item list) - "Return non-nil if ITEM is `equal' to some item in LIST. -Actually return the list whose car is that item." - (while (and list (not (equal item (car list)))) - (setq list (cdr list))) - list) - -(defun isearch-no-upper-case-p (string) - "Return t if there are no upper case chars in string. -But upper case chars preceeded by \\ (but not \\\\) do not count since they -have special meaning in a regexp." +(defun isearch-no-upper-case-p (string regexp-flag) + "Return t if there are no upper case chars in STRING. +If REGEXP-FLAG is non-nil, disregard letters preceeded by `\\' (but not `\\\\') +since they have special meaning in a regexp." (let ((case-fold-search nil)) - (not (string-match "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]" string)))) + (not (string-match (if regexp-flag "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]" + "[A-Z]") + string)))) ;;;================================================= -;;; Special functions for lemacs events. +;; Portability functions to support various Emacs versions. ;; To quiet the byte-compiler. (defvar unread-command-event) +(defvar unread-command-events) (defvar last-command-event) (defun isearch-char-to-string (c) (if (integerp c) (make-string 1 c) - (make-string 1 (event-to-character c)))) + (if (and (symbolp c) (get c 'ascii-character)) + (make-string 1 (get c 'ascii-character)) + (make-string 1 (event-to-character c))))) (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))) + (if (and (integerp c) (or (< c ?\ ) (= c ?\^?))) + (text-char-description c) + (isearch-char-to-string c))) + +(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. @@ -1422,106 +1442,4 @@ have special meaning in a regexp." last-command-event last-command-char)) - - - -;;;======================================================== -;;; Exiting in lemacs - -;; This is a large amount of code to support automatic termination of -;; isearch-mode when a command (however it is invoked) is not an -;; isearch command, or the buffer is switched out from under -;; isearch-mode. Only later versions of lemacs have the pre-command-hook. - -;;(if isearch-pre-command-hook-exists -;;(progn - -;;;; This list must be modified whenever the available commands are modified. -;;(mapcar (function (lambda (command) -;; (put command 'isearch-command t))) -;; '(isearch-printing-char -;; isearch-return-char -;; isearch-repeat-forward -;; isearch-repeat-backward -;; isearch-delete-char -;; isearch-abort -;; isearch-quote-char -;; isearch-exit -;; isearch-printing-char -;; isearch-printing-char -;; isearch-yank-word -;; isearch-yank-line -;; isearch-*-char -;; isearch-*-char -;; isearch-|-char -;; isearch-toggle-regexp -;; isearch-edit-string -;; isearch-mode-help -;; isearch-ring-advance -;; isearch-ring-retreat -;; isearch-ring-advance-edit -;; isearch-ring-retreat-edit -;; isearch-whitespace-chars -;; isearch-complete -;; isearch-complete-edit -;; isearch-edit-string -;; isearch-toggle-regexp -;; ;; The following may not be needed since isearch-mode is off already. -;; isearch-forward-exit-minibuffer -;; isearch-reverse-exit-minibuffer -;; isearch-nonincremental-exit-minibuffer)) - -;;(defun isearch-pre-command-hook () -;; ;; -;; ;; For use as the value of `pre-command-hook' when isearch-mode is active. -;; ;; If the command about to be executed is not one of the isearch commands, -;; ;; then isearch-mode is turned off before that command is executed. -;; ;; -;; ;; If the command about to be executed is self-insert-command, or is a -;; ;; keyboard macro of a single key sequence which is bound to self-insert- -;; ;; command, then we add those chars to the search ring instead of inserting -;; ;; them in the buffer. In this way, the set of self-searching characters -;; ;; need not be exhaustively enumerated, but is derived from other maps. -;; ;; -;; (isearch-maybe-frob-keyboard-macros) -;; (if (and (symbolp this-command) -;; (get this-command 'isearch-command)) -;; nil -;; (isearch-done))) - -;;(defun isearch-maybe-frob-keyboard-macros () -;; ;; -;; ;; If the command about to be executed is `self-insert-command' then change -;; ;; the command to `isearch-printing-char' instead, meaning add the last- -;; ;; typed character to the search string. -;; ;; -;; ;; If `this-command' is a string or a vector (that is, a keyboard macro) -;; ;; and it contains only one command, which is bound to self-insert-command, -;; ;; then do the same thing as for self-inserting commands: arrange for that -;; ;; character to be added to the search string. If we didn't do this, then -;; ;; typing a compose sequence (a la x-compose.el) would terminate the search -;; ;; and insert the character, instead of searching for that character. -;; ;; -;; (cond ((eq this-command 'self-insert-command) -;; (setq this-command 'isearch-printing-char)) -;; ((and (stringp this-command) -;; (eq (key-binding this-command) 'self-insert-command)) -;; (setq last-command-char (aref this-command 0) -;; last-command-event (character-to-event last-command-char) -;; this-command 'isearch-printing-char)) -;; ((and (vectorp this-command) -;; (eq (key-binding this-command) 'self-insert-command)) -;; (let* ((desc (aref this-command 0)) -;; (code (cond ((integerp desc) desc) -;; ((symbolp desc) (get desc character-set-property)) -;; ((consp desc) -;; (and (null (cdr desc)) -;; (get (car desc) character-set-property))) -;; (t nil)))) -;; (if code -;; (setq last-command-char code -;; last-command-event (character-to-event last-command-char) -;; this-command 'isearch-printing-char)))) -;; )) - -;;)) +;;; isearch.el ends here