isearch.el 110 KB
Newer Older
1
;;; isearch.el --- incremental search minor mode
2

3
;; Copyright (C) 1992-1997, 1999-2012  Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
4

5
;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
6
;; Maintainer: FSF
Dave Love's avatar
Dave Love committed
7
;; Keywords: matching
8
;; Package: emacs
Jim Blandy's avatar
Jim Blandy committed
9

David J. MacKenzie's avatar
David J. MacKenzie committed
10
;; This file is part of GNU Emacs.
Jim Blandy's avatar
Jim Blandy committed
11

12
;; GNU Emacs is free software: you can redistribute it and/or modify
13
;; it under the terms of the GNU General Public License as published by
14 15
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
16

Jim Blandy's avatar
Jim Blandy committed
17
;; GNU Emacs is distributed in the hope that it will be useful,
18 19 20 21 22
;; 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
23
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Jim Blandy's avatar
Jim Blandy committed
24

25 26
;;; Commentary:

Jim Blandy's avatar
Jim Blandy committed
27 28
;; Instructions

29 30
;; For programmed use of isearch-mode, e.g. calling (isearch-forward),
;; isearch-mode behaves modally and does not return until the search
Dave Love's avatar
Dave Love committed
31
;; is completed.  It uses a recursive-edit to behave this way.
32

Jim Blandy's avatar
Jim Blandy committed
33
;; The key bindings active within isearch-mode are defined below in
34 35 36 37 38 39 40
;; `isearch-mode-map' which is given bindings close to the default
;; characters of the original isearch.el.  With `isearch-mode',
;; however, you can bind multi-character keys and it should be easier
;; to add new commands.  One bug though: keys with meta-prefix cannot
;; be longer than two chars.  Also see minibuffer-local-isearch-map
;; for bindings active during `isearch-edit-string'.

Dave Love's avatar
Dave Love committed
41 42 43
;; isearch-mode should work even if you switch windows with the mouse,
;; in which case isearch-mode is terminated automatically before the
;; switch.
44 45 46 47 48 49 50 51 52 53 54 55 56 57

;; The search ring and completion commands automatically put you in
;; the minibuffer to edit the string.  This gives you a chance to
;; modify the search string before executing the search.  There are
;; three commands to terminate the editing: C-s and C-r exit the
;; minibuffer and search forward and reverse respectively, while C-m
;; exits and does a nonincremental search.

;; Exiting immediately from isearch uses isearch-edit-string instead
;; of nonincremental-search, if search-nonincremental-instead is non-nil.
;; The name of this option should probably be changed if we decide to
;; keep the behavior.  No point in forcing nonincremental search until
;; the last possible moment.

58
;;; Code:
59 60


61
;; Some additional options and constants.
62

63 64
(defgroup isearch nil
  "Incremental search minor mode."
Dave Love's avatar
Dave Love committed
65 66
  :link '(emacs-commentary-link "isearch")
  :link '(custom-manual "(emacs)Incremental Search")
67 68 69
  :prefix "isearch-"
  :prefix "search-"
  :group 'matching)
70

71 72

(defcustom search-exit-option t
73
  "Non-nil means random control characters terminate incremental search."
74 75 76 77
  :type 'boolean
  :group 'isearch)

(defcustom search-slow-window-lines 1
78
  "Number of lines in slow search display windows.
79 80
These are the short windows used during incremental search on slow terminals.
Negative means put the slow search window at the top (normally it's at bottom)
81 82 83
and the value is minus the number of lines."
  :type 'integer
  :group 'isearch)
84

85
(defcustom search-slow-speed 1200
86
  "Highest terminal speed at which to use \"slow\" style incremental search.
87
This is the style where a one-line window is created to show the line
88 89 90
that the search has reached."
  :type 'integer
  :group 'isearch)
Jim Blandy's avatar
Jim Blandy committed
91

92
(defcustom search-upper-case 'not-yanks
93
  "If non-nil, upper case chars disable case fold searching.
94 95
That is, upper and lower case chars must match exactly.
This applies no matter where the chars come from, but does not
96
apply to chars in regexps that are prefixed with `\\'.
Juri Linkov's avatar
Juri Linkov committed
97 98
If this value is `not-yanks', text yanked into the search string
in Isearch mode is always downcased."
99 100
  :type '(choice (const :tag "off" nil)
		 (const not-yanks)
101
		 (other :tag "on" t))
102
  :group 'isearch)
Jim Blandy's avatar
Jim Blandy committed
103

104
(defcustom search-nonincremental-instead t
105
  "If non-nil, do a nonincremental search instead of exiting immediately.
106
Actually, `isearch-edit-string' is called to let you enter the search
107 108 109
string, and RET terminates editing and does a nonincremental search."
  :type 'boolean
  :group 'isearch)
Jim Blandy's avatar
Jim Blandy committed
110

111
(defcustom search-whitespace-regexp (purecopy "\\s-+")
112
  "If non-nil, regular expression to match a sequence of whitespace chars.
113
This applies to regular expression incremental search.
114 115 116 117
When you put a space or spaces in the incremental regexp, it stands for
this, unless it is inside of a regexp construct such as [...] or *, + or ?.
You might want to use something like \"[ \\t\\r\\n]+\" instead.
In the Customization buffer, that is `[' followed by a space,
118 119 120 121 122
a tab, a carriage return (control-M), a newline, and `]+'.

When this is nil, each space you type matches literally, against one space."
  :type '(choice (const :tag "Find Spaces Literally" nil)
		 regexp)
123
  :group 'isearch)
Jim Blandy's avatar
Jim Blandy committed
124

125 126
(defcustom search-invisible 'open
  "If t incremental search can match hidden text.
127 128
A nil value means don't match invisible text.
When the value is `open', if the text matched is made invisible by
129 130
an overlay having an `invisible' property and that overlay has a property
`isearch-open-invisible', then incremental search will show the contents.
Stefan Monnier's avatar
Stefan Monnier committed
131 132 133
\(This applies when using `outline.el' and `hideshow.el'.)
See also `reveal-mode' if you want overlays to automatically be opened
whenever point is in one of them."
134 135
  :type '(choice (const :tag "Match hidden text" t)
		 (const :tag "Open overlays" open)
136
		 (const :tag "Don't match hidden text" nil))
137 138 139
  :group 'isearch)

(defcustom isearch-hide-immediately t
140 141 142 143
  "If non-nil, re-hide an invisible match right away.
This variable makes a difference when `search-invisible' is set to `open'.
It means that after search makes some invisible text visible
to show the match, it makes the text invisible again when the match moves.
144 145
Ordinarily the text becomes invisible again at the end of the search."
  :type 'boolean
146
  :group 'isearch)
147

148
(defcustom isearch-resume-in-command-history nil
149 150
  "If non-nil, `isearch-resume' commands are added to the command history.
This allows you to resume earlier Isearch sessions through the
151
command history."
152 153 154
  :type 'boolean
  :group 'isearch)

155 156 157
(defvar isearch-mode-hook nil
  "Function(s) to call after starting up an incremental search.")

158 159 160
(defvar isearch-update-post-hook nil
  "Function(s) to call after isearch has found matches in the buffer.")

161
(defvar isearch-mode-end-hook nil
162 163
  "Function(s) to call after terminating an incremental search.
When these functions are called, `isearch-mode-end-hook-quit'
164
is non-nil if the user quits the search.")
165 166

(defvar isearch-mode-end-hook-quit nil
167
  "Non-nil while running `isearch-mode-end-hook' if the user quits the search.")
168

169 170 171 172
(defvar isearch-message-function nil
  "Function to call to display the search prompt.
If nil, use `isearch-message'.")

173 174 175 176 177 178
(defvar isearch-wrap-function nil
  "Function to call to wrap the search when search is failed.
If nil, move point to the beginning of the buffer for a forward search,
or to the end of the buffer for a backward search.")

(defvar isearch-push-state-function nil
179
  "Function to save a function restoring the mode-specific Isearch state
180 181
to the search status stack.")

182
(defvar isearch-filter-predicate 'isearch-filter-visible
183 184 185 186 187
  "Predicate that filters the search hits that would normally be available.
Search hits that dissatisfy the predicate are skipped.  The function
has two arguments: the positions of start and end of text matched by
the search.  If this function returns nil, continue searching without
stopping at this match.")
188

189
;; Search ring.
Jim Blandy's avatar
Jim Blandy committed
190 191 192

(defvar search-ring nil
  "List of search string sequences.")
193
(defvar regexp-search-ring nil
Jim Blandy's avatar
Jim Blandy committed
194 195
  "List of regular expression search string sequences.")

196
(defcustom search-ring-max 16
197
  "Maximum length of search ring before oldest elements are thrown away."
198 199 200
  :type 'integer
  :group 'isearch)
(defcustom regexp-search-ring-max 16
201
  "Maximum length of regexp search ring before oldest elements are thrown away."
202 203
  :type 'integer
  :group 'isearch)
Jim Blandy's avatar
Jim Blandy committed
204 205

(defvar search-ring-yank-pointer nil
206
  "Index in `search-ring' of last string reused.
207
It is nil if none yet.")
208
(defvar regexp-search-ring-yank-pointer nil
209
  "Index in `regexp-search-ring' of last string reused.
210
It is nil if none yet.")
Jim Blandy's avatar
Jim Blandy committed
211

212
(defcustom search-ring-update nil
213
  "Non-nil if advancing or retreating in the search ring should cause search.
214 215 216
Default value, nil, means edit the string instead."
  :type 'boolean
  :group 'isearch)
217

218 219 220
;;; isearch highlight customization.

(defcustom search-highlight t
221
  "Non-nil means incremental search highlights the current match."
222 223 224 225 226 227 228
  :type 'boolean
  :group 'isearch)

(defface isearch
  '((((class color) (min-colors 88) (background light))
     ;; The background must not be too dark, for that means
     ;; the character is hard to see when the cursor is there.
229
     (:background "magenta3" :foreground "lightskyblue1"))
230 231 232 233 234 235 236 237
    (((class color) (min-colors 88) (background dark))
     (:background "palevioletred2" :foreground "brown4"))
    (((class color) (min-colors 16))
     (:background "magenta4" :foreground "cyan1"))
    (((class color) (min-colors 8))
     (:background "magenta4" :foreground "cyan1"))
    (t (:inverse-video t)))
  "Face for highlighting Isearch matches."
238 239
  :group 'isearch
  :group 'basic-faces)
240
(defvar isearch-face 'isearch)
241

242 243 244 245 246 247 248 249 250 251 252 253
(defface isearch-fail
  '((((class color) (min-colors 88) (background light))
     (:background "RosyBrown1"))
    (((class color) (min-colors 88) (background dark))
     (:background "red4"))
    (((class color) (min-colors 16))
     (:background "red"))
    (((class color) (min-colors 8))
     (:background "red"))
    (((class color grayscale))
     :foreground "grey")
    (t (:inverse-video t)))
Bastien Guerry's avatar
Bastien Guerry committed
254
  "Face for highlighting failed part in Isearch echo-area message."
255
  :version "23.1"
Bastien Guerry's avatar
Bastien Guerry committed
256 257
  :group 'isearch)

258
(defcustom isearch-lazy-highlight t
259
  "Controls the lazy-highlighting during incremental search.
260 261 262 263 264 265 266
When non-nil, all text in the buffer matching the current search
string is highlighted lazily (see `lazy-highlight-initial-delay'
and `lazy-highlight-interval')."
  :type 'boolean
  :group 'lazy-highlight
  :group 'isearch)

267
;;; Lazy highlight customization.
268

269 270 271 272 273
(defgroup lazy-highlight nil
  "Lazy highlighting feature for matching strings."
  :prefix "lazy-highlight-"
  :version "21.1"
  :group 'isearch
274
  :group 'matching)
275

276 277 278 279
(define-obsolete-variable-alias 'isearch-lazy-highlight-cleanup
                                'lazy-highlight-cleanup
                                "22.1")

280
(defcustom lazy-highlight-cleanup t
281
  "Controls whether to remove extra highlighting after a search.
282
If this is nil, extra highlighting can be \"manually\" removed with
283
\\[lazy-highlight-cleanup]."
284 285
  :type 'boolean
  :group 'lazy-highlight)
286 287 288

(define-obsolete-variable-alias 'isearch-lazy-highlight-initial-delay
                                'lazy-highlight-initial-delay
289
                                "22.1")
290 291

(defcustom lazy-highlight-initial-delay 0.25
292
  "Seconds to wait before beginning to lazily highlight all matches."
293 294
  :type 'number
  :group 'lazy-highlight)
295 296 297

(define-obsolete-variable-alias 'isearch-lazy-highlight-interval
                                'lazy-highlight-interval
298
                                "22.1")
299 300

(defcustom lazy-highlight-interval 0 ; 0.0625
301
  "Seconds between lazily highlighting successive matches."
302 303
  :type 'number
  :group 'lazy-highlight)
304 305 306

(define-obsolete-variable-alias 'isearch-lazy-highlight-max-at-a-time
                                'lazy-highlight-max-at-a-time
307
                                "22.1")
308 309

(defcustom lazy-highlight-max-at-a-time 20
310 311
  "Maximum matches to highlight at a time (for `lazy-highlight').
Larger values may reduce Isearch's responsiveness to user input;
312 313 314 315 316 317
smaller values make matches highlight slowly.
A value of nil means highlight all matches."
  :type '(choice (const :tag "All" nil)
		 (integer :tag "Some"))
  :group 'lazy-highlight)

318
(defface lazy-highlight
319 320 321 322 323 324 325 326 327 328
  '((((class color) (min-colors 88) (background light))
     (:background "paleturquoise"))
    (((class color) (min-colors 88) (background dark))
     (:background "paleturquoise4"))
    (((class color) (min-colors 16))
     (:background "turquoise3"))
    (((class color) (min-colors 8))
     (:background "turquoise3"))
    (t (:underline t)))
  "Face for lazy highlighting of matches other than the current one."
329 330
  :group 'lazy-highlight
  :group 'basic-faces)
331
(define-obsolete-face-alias 'isearch-lazy-highlight-face 'lazy-highlight "22.1")
332 333 334
(define-obsolete-variable-alias 'isearch-lazy-highlight-face
                                'lazy-highlight-face
                                "22.1")
335
(defvar lazy-highlight-face 'lazy-highlight)
336 337 338 339

;; Define isearch help map.

(defvar isearch-help-map
340
  (let ((map (make-sparse-keymap)))
341 342 343 344 345 346 347 348 349 350
    (define-key map [t] 'isearch-other-control-char)
    (define-key map (char-to-string help-char) 'isearch-help-for-help)
    (define-key map [help] 'isearch-help-for-help)
    (define-key map [f1] 'isearch-help-for-help)
    (define-key map "?" 'isearch-help-for-help)
    (define-key map "b" 'isearch-describe-bindings)
    (define-key map "k" 'isearch-describe-key)
    (define-key map "m" 'isearch-describe-mode)
    (define-key map "q" 'help-quit)
    map)
351
  "Keymap for characters following the Help key for Isearch mode.")
352 353 354 355

(eval-when-compile (require 'help-macro))

(make-help-screen isearch-help-for-help-internal
356
  (purecopy "Type a help option: [bkm] or ?")
357 358 359
  "You have typed %THIS-KEY%, the help character.  Type a Help option:
\(Type \\<help-map>\\[help-quit] to exit the Help command.)

360 361 362
b           Display all Isearch key bindings.
k KEYS      Display full documentation of Isearch key sequence.
m           Display documentation of Isearch mode.
363 364

You can't type here other help keys available in the global help map,
365 366
but outside of this help window when you type them in Isearch mode,
they exit Isearch mode before displaying global help."
367 368 369
  isearch-help-map)

(defun isearch-help-for-help ()
370
  "Display Isearch help menu."
371 372 373 374 375 376
  (interactive)
  (let (same-window-buffer-names same-window-regexps)
    (isearch-help-for-help-internal))
  (isearch-update))

(defun isearch-describe-bindings ()
377 378
  "Show a list of all keys defined in Isearch mode, and their definitions.
This is like `describe-bindings', but displays only Isearch keys."
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
  (interactive)
  (let (same-window-buffer-names same-window-regexps)
    (with-help-window "*Help*"
      (with-current-buffer standard-output
	(princ "Isearch Mode Bindings:\n")
	(princ (substitute-command-keys "\\{isearch-mode-map}"))))))

(defun isearch-describe-key ()
  "Display documentation of the function invoked by isearch key."
  (interactive)
  (let (same-window-buffer-names same-window-regexps)
    (call-interactively 'describe-key))
  (isearch-update))

(defun isearch-describe-mode ()
394
  "Display documentation of Isearch mode."
395 396 397 398 399 400 401
  (interactive)
  (let (same-window-buffer-names same-window-regexps)
    (describe-function 'isearch-forward))
  (isearch-update))

(defalias 'isearch-mode-help 'isearch-describe-mode)

402

403
;; Define isearch-mode keymap.
Jim Blandy's avatar
Jim Blandy committed
404

405
(defvar isearch-mode-map
406 407
  (let ((i 0)
	(map (make-keymap)))
Kenichi Handa's avatar
Kenichi Handa committed
408
    (or (char-table-p (nth 1 map))
409 410
	(error "The initialization of isearch-mode-map must be updated"))
    ;; Make all multibyte characters search for themselves.
Kenichi Handa's avatar
Kenichi Handa committed
411
    (set-char-table-range (nth 1 map) (cons #x100 (max-char))
412
			  'isearch-printing-char)
Kenichi Handa's avatar
Kenichi Handa committed
413 414
    ;; Make function keys, etc, which aren't bound to a scrolling-function
    ;; exit the search.
415 416
    (define-key map [t] 'isearch-other-control-char)
    ;; Control chars, by default, end isearch mode transparently.
417
    ;; We need these explicit definitions because, in a dense keymap,
418 419
    ;; the binding for t does not affect characters.
    ;; We use a dense keymap to save space.
420
    (while (< i ?\s)
421 422 423 424
      (define-key map (make-string 1 i) 'isearch-other-control-char)
      (setq i (1+ i)))

    ;; Single-byte printing chars extend the search string by default.
425
    (setq i ?\s)
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
    (while (< i 256)
      (define-key map (vector i) 'isearch-printing-char)
      (setq i (1+ i)))

    ;; 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.
    (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)

    ;; Several non-printing chars change the searching behavior.
    (define-key map "\C-s" 'isearch-repeat-forward)
    (define-key map "\C-r" 'isearch-repeat-backward)
    ;; Define M-C-s and M-C-r like C-s and C-r so that the same key
    ;; combinations can be used to repeat regexp isearches that can
    ;; be used to start these searches.
    (define-key map "\M-\C-s" 'isearch-repeat-forward)
    (define-key map "\M-\C-r" 'isearch-repeat-backward)
    (define-key map "\177" 'isearch-delete-char)
    (define-key map "\C-g" 'isearch-abort)
450

451 452 453 454 455
    ;; This assumes \e is the meta-prefix-char.
    (or (= ?\e meta-prefix-char)
	(error "Inconsistency in isearch.el"))
    (define-key map "\e\e\e" 'isearch-cancel)
    (define-key map  [escape escape escape] 'isearch-cancel)
456

457
    (define-key map "\C-q" 'isearch-quote-char)
458

459 460 461
    (define-key map "\r" 'isearch-exit)
    (define-key map "\C-j" 'isearch-printing-char)
    (define-key map "\t" 'isearch-printing-char)
462
    (define-key map [?\S-\ ] 'isearch-printing-char)
463

464 465 466
    (define-key map    "\C-w" 'isearch-yank-word-or-char)
    (define-key map "\M-\C-w" 'isearch-del-char)
    (define-key map "\M-\C-y" 'isearch-yank-char)
467 468
    (define-key map    "\C-y" 'isearch-yank-kill)
    (define-key map "\M-s\C-e" 'isearch-yank-line)
469

470 471 472
    (define-key map (char-to-string help-char) isearch-help-map)
    (define-key map [help] isearch-help-map)
    (define-key map [f1] isearch-help-map)
473

474 475
    (define-key map "\M-n" 'isearch-ring-advance)
    (define-key map "\M-p" 'isearch-ring-retreat)
476
    (define-key map "\M-y" 'isearch-yank-pop)
477 478 479 480 481 482 483 484 485 486

    (define-key map "\M-\t" 'isearch-complete)

    ;; Pass frame events transparently so they won't exit the search.
    ;; In particular, if we have more than one display open, then a
    ;; switch-frame might be generated by someone typing at another keyboard.
    (define-key map [switch-frame] nil)
    (define-key map [delete-frame] nil)
    (define-key map [iconify-frame] nil)
    (define-key map [make-frame-visible] nil)
487
    (define-key map [mouse-movement] nil)
488 489
    (define-key map [language-change] nil)

490 491 492 493 494
    ;; For searching multilingual text.
    (define-key map "\C-\\" 'isearch-toggle-input-method)
    (define-key map "\C-^" 'isearch-toggle-specified-input-method)

    ;; People expect to be able to paste with the mouse.
495
    (define-key map [mouse-2] #'isearch-mouse-2)
496 497 498 499 500 501 502 503
    (define-key map [down-mouse-2] nil)

    ;; Some bindings you may want to put in your isearch-mode-hook.
    ;; Suggest some alternates...
    (define-key map "\M-c" 'isearch-toggle-case-fold)
    (define-key map "\M-r" 'isearch-toggle-regexp)
    (define-key map "\M-e" 'isearch-edit-string)

504 505 506
    (define-key map "\M-sr" 'isearch-toggle-regexp)
    (define-key map "\M-sw" 'isearch-toggle-word)

507 508
    (define-key map [?\M-%] 'isearch-query-replace)
    (define-key map [?\C-\M-%] 'isearch-query-replace-regexp)
Juri Linkov's avatar
Juri Linkov committed
509
    (define-key map "\M-so" 'isearch-occur)
510
    (define-key map "\M-shr" 'isearch-highlight-regexp)
511

512 513 514 515 516 517
    map)
  "Keymap for `isearch-mode'.")

(defvar minibuffer-local-isearch-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map minibuffer-local-map)
518
    (define-key map "\r"    'isearch-nonincremental-exit-minibuffer)
519
    (define-key map "\M-\t" 'isearch-complete-edit)
520 521 522 523
    (define-key map "\C-s"  'isearch-forward-exit-minibuffer)
    (define-key map "\C-r"  'isearch-reverse-exit-minibuffer)
    (define-key map "\C-f"  'isearch-yank-char-in-minibuffer)
    (define-key map [right] 'isearch-yank-char-in-minibuffer)
524
    map)
525
  "Keymap for editing Isearch strings in the minibuffer.")
Jim Blandy's avatar
Jim Blandy committed
526 527

;; Internal variables declared globally for byte-compiler.
528 529 530 531 532 533
;; These are all set with setq while isearching
;; and bound locally while editing the search string.

(defvar isearch-forward nil)	; Searching in the forward direction.
(defvar isearch-regexp nil)	; Searching for a regexp.
(defvar isearch-word nil)	; Searching for words.
Stefan Monnier's avatar
Stefan Monnier committed
534
(defvar isearch-hidden nil) ; Non-nil if the string exists but is invisible.
535

536 537
(defvar isearch-cmds nil
  "Stack of search status sets.
538 539 540
Each set is a vector of the form:
 [STRING MESSAGE POINT SUCCESS FORWARD OTHER-END WORD
  INVALID-REGEXP WRAPPED BARRIER WITHIN-BRACKETS CASE-FOLD-SEARCH]")
541

542 543 544
(defvar isearch-string "")  ; The current search string.
(defvar isearch-message "") ; text-char-description version of isearch-string

Juanma Barranquero's avatar
Juanma Barranquero committed
545 546
(defvar isearch-message-prefix-add nil) ; Additional text for the message prefix
(defvar isearch-message-suffix-add nil) ; Additional text for the message suffix
Juri Linkov's avatar
Juri Linkov committed
547

Juri Linkov's avatar
Juri Linkov committed
548 549
(defvar isearch-success t)	; Searching is currently successful.
(defvar isearch-error nil)	; Error message for failed search.
550 551
(defvar isearch-other-end nil)	; Start (end) of match if forward (backward).
(defvar isearch-wrapped nil)	; Searching restarted from the top (bottom).
Lars Magne Ingebrigtsen's avatar
Lars Magne Ingebrigtsen committed
552 553
(defvar isearch-barrier 0
  "Recorded minimum/maximal point for the current search.")
554
(defvar isearch-just-started nil)
555
(defvar isearch-start-hscroll 0)	; hscroll when starting the search.
Jim Blandy's avatar
Jim Blandy committed
556

557 558 559
;; 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.
560
(defvar isearch-case-fold-search nil)
Jim Blandy's avatar
Jim Blandy committed
561

562 563
(defvar isearch-last-case-fold-search nil)

564 565 566
;; Used to save default value while isearch is active
(defvar isearch-original-minibuffer-message-timeout nil)

Jim Blandy's avatar
Jim Blandy committed
567 568
(defvar isearch-adjusted nil)
(defvar isearch-slow-terminal-mode nil)
569
;; If t, using a small window.
570
(defvar isearch-small-window nil)
Jim Blandy's avatar
Jim Blandy committed
571
(defvar isearch-opoint 0)
572
;; The window configuration active at the beginning of the search.
573
(defvar isearch-window-configuration nil)
Jim Blandy's avatar
Jim Blandy committed
574

575 576
;; Flag to indicate a yank occurred, so don't move the cursor.
(defvar isearch-yank-flag nil)
Jim Blandy's avatar
Jim Blandy committed
577

578 579 580
;; A function to be called after each input character is processed.
;; (It is not called after characters that exit the search.)
;; It is only set from an optional argument to `isearch-mode'.
581
(defvar isearch-op-fun nil)
Jim Blandy's avatar
Jim Blandy committed
582

583
;;  Is isearch-mode in a recursive edit for modal searching.
584
(defvar isearch-recursive-edit nil)
Jim Blandy's avatar
Jim Blandy committed
585

586
;; Should isearch be terminated after doing one search?
587 588 589 590
(defvar isearch-nonincremental nil)

;; New value of isearch-forward after isearch-edit-string.
(defvar isearch-new-forward nil)
Jim Blandy's avatar
Jim Blandy committed
591

592 593
;; Accumulate here the overlays opened during searching.
(defvar isearch-opened-overlays nil)
Jim Blandy's avatar
Jim Blandy committed
594

595 596 597 598 599 600 601
;; The value of input-method-function when isearch is invoked.
(defvar isearch-input-method-function nil)

;; A flag to tell if input-method-function is locally bound when
;; isearch is invoked.
(defvar isearch-input-method-local-p nil)

Jim Blandy's avatar
Jim Blandy committed
602 603 604 605 606 607 608
;; Minor-mode-alist changes - kind of redundant with the
;; echo area, but if isearching in multiple windows, it can be useful.

(or (assq 'isearch-mode minor-mode-alist)
    (nconc minor-mode-alist
	   (list '(isearch-mode isearch-mode))))

609
(defvar isearch-mode nil) ;; Name of the minor mode, if non-nil.
Jim Blandy's avatar
Jim Blandy committed
610 611
(make-variable-buffer-local 'isearch-mode)

612 613 614 615
(define-key global-map "\C-s" 'isearch-forward)
(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)
616
(define-key search-map "w" 'isearch-forward-word)
617

618
;; Entry points to isearch-mode.
Jim Blandy's avatar
Jim Blandy committed
619

620
(defun isearch-forward (&optional regexp-p no-recursive-edit)
Jim Blandy's avatar
Jim Blandy committed
621 622
  "\
Do incremental search forward.
623 624
With a prefix argument, do an incremental regular expression search instead.
\\<isearch-mode-map>
Jim Blandy's avatar
Jim Blandy committed
625
As you type characters, they add to the search string and are found.
626
The following non-printing keys are bound in `isearch-mode-map'.
Jim Blandy's avatar
Jim Blandy committed
627

628
Type \\[isearch-delete-char] to cancel last input item from end of search string.
Jim Blandy's avatar
Jim Blandy committed
629
Type \\[isearch-exit] to exit, leaving point at location found.
630 631 632
Type LFD (C-j) to match end of line.
Type \\[isearch-repeat-forward] to search again forward,\
 \\[isearch-repeat-backward] to search again backward.
633 634
Type \\[isearch-yank-word-or-char] to yank next word or character in buffer
  onto the end of the search string, and search for it.
635 636
Type \\[isearch-del-char] to delete character from end of search string.
Type \\[isearch-yank-char] to yank char from buffer onto end of search\
637 638 639
 string and search for it.
Type \\[isearch-yank-line] to yank rest of line onto end of search string\
 and search for it.
640
Type \\[isearch-yank-kill] to yank the last string of killed text.
641 642
Type \\[isearch-yank-pop] to replace string just yanked into search prompt
 with string killed before it.
Jim Blandy's avatar
Jim Blandy committed
643
Type \\[isearch-quote-char] to quote control character to search for it.
644 645 646 647 648
\\[isearch-abort] while searching or when search has failed cancels input\
 back to what has
 been found successfully.
\\[isearch-abort] when search is successful aborts and moves point to\
 starting point.
Jim Blandy's avatar
Jim Blandy committed
649

650 651 652
If you try to exit with the search string still empty, it invokes
 nonincremental search.

653 654
Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity.
Type \\[isearch-toggle-regexp] to toggle regular-expression mode.
655
Type \\[isearch-toggle-word] to toggle word mode.
656 657
Type \\[isearch-edit-string] to edit the search string in the minibuffer.

Jim Blandy's avatar
Jim Blandy committed
658 659
Also supported is a search ring of the previous 16 search strings.
Type \\[isearch-ring-advance] to search for the next item in the search ring.
660 661 662
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.
Jim Blandy's avatar
Jim Blandy committed
663

664 665 666 667 668 669 670 671 672
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.

673 674 675
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.
676

Eli Zaretskii's avatar
Eli Zaretskii committed
677
If an input method is turned on in the current buffer, that input
678 679 680 681
method is also active while you are typing characters to search.
To toggle the input method, type \\[isearch-toggle-input-method].  \
It also toggles the input
method in the current buffer.
682

683 684 685
To use a different input method for searching, type \
\\[isearch-toggle-specified-input-method],
and specify an input method you want to use.
686

687
The above keys, bound in `isearch-mode-map', are often controlled by
688
 options; do \\[apropos] on search-.* to find them.
Jim Blandy's avatar
Jim Blandy committed
689
Other control and meta characters terminate the search
690
 and are then executed normally (depending on `search-exit-option').
691
Likewise for function keys and mouse button events.
Jim Blandy's avatar
Jim Blandy committed
692

693 694
If this function is called non-interactively, it does not return to
the calling function until the search is done."
Jim Blandy's avatar
Jim Blandy committed
695

696
  (interactive "P\np")
697
  (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit)))
Jim Blandy's avatar
Jim Blandy committed
698

699
(defun isearch-forward-regexp (&optional not-regexp no-recursive-edit)
Jim Blandy's avatar
Jim Blandy committed
700 701
  "\
Do incremental search forward for regular expression.
702
With a prefix argument, do a regular string search instead.
703 704
Like ordinary incremental search except that your input is treated
as a regexp.  See the command `isearch-forward' for more information.
705 706 707 708

In regexp incremental searches, a space or spaces normally matches
any whitespace (the variable `search-whitespace-regexp' controls
precisely what that means).  If you want to search for a literal space
709
and nothing else, enter C-q SPC."
710
  (interactive "P\np")
711
  (isearch-mode t (null not-regexp) nil (not no-recursive-edit)))
Jim Blandy's avatar
Jim Blandy committed
712

713 714 715 716
(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.
717 718 719
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."
720 721 722
  (interactive "P\np")
  (isearch-mode t nil nil (not no-recursive-edit) (null not-word)))

723
(defun isearch-backward (&optional regexp-p no-recursive-edit)
Jim Blandy's avatar
Jim Blandy committed
724 725
  "\
Do incremental search backward.
726
With a prefix argument, do a regular expression search instead.
727
See the command `isearch-forward' for more information."
728
  (interactive "P\np")
729
  (isearch-mode nil (not (null regexp-p)) nil (not no-recursive-edit)))
Jim Blandy's avatar
Jim Blandy committed
730

731
(defun isearch-backward-regexp (&optional not-regexp no-recursive-edit)
Jim Blandy's avatar
Jim Blandy committed
732 733
  "\
Do incremental search backward for regular expression.
734
With a prefix argument, do a regular string search instead.
735 736
Like ordinary incremental search except that your input is treated
as a regexp.  See the command `isearch-forward' for more information."
737
  (interactive "P\np")
738
  (isearch-mode nil (null not-regexp) nil (not no-recursive-edit)))
739

Jim Blandy's avatar
Jim Blandy committed
740 741 742 743

;; isearch-mode only sets up incremental search for the minor mode.
;; All the work is done by the isearch-mode commands.

744
;; Not used yet:
745
;;(defvar isearch-commands '(isearch-forward isearch-backward
746 747
;;			     isearch-forward-regexp isearch-backward-regexp)
;;  "List of commands for which isearch-mode does not recursive-edit.")
748

749 750

(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p)
751
  "Start Isearch minor mode.
752
It is called by the function `isearch-forward' and other related functions."
Jim Blandy's avatar
Jim Blandy committed
753 754 755 756

  ;; Initialize global vars.
  (setq isearch-forward forward
	isearch-regexp regexp
757
	isearch-word word-p
Jim Blandy's avatar
Jim Blandy committed
758
	isearch-op-fun op-fun
759
	isearch-last-case-fold-search isearch-case-fold-search
Jim Blandy's avatar
Jim Blandy committed
760 761 762 763 764 765 766 767 768
	isearch-case-fold-search case-fold-search
	isearch-string ""
	isearch-message ""
	isearch-cmds nil
	isearch-success t
	isearch-wrapped nil
	isearch-barrier (point)
	isearch-adjusted nil
	isearch-yank-flag nil
Juri Linkov's avatar
Juri Linkov committed
769
	isearch-error nil
770
	isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
Jim Blandy's avatar
Jim Blandy committed
771
					(> (window-height)
772 773
					   (* 4
					      (abs search-slow-window-lines))))
Jim Blandy's avatar
Jim Blandy committed
774 775
	isearch-other-end nil
	isearch-small-window nil
776
	isearch-just-started t
777
	isearch-start-hscroll (window-hscroll)
Jim Blandy's avatar
Jim Blandy committed
778 779

	isearch-opoint (point)
780
	search-ring-yank-pointer nil
781
	isearch-opened-overlays nil
782 783
	isearch-input-method-function input-method-function
	isearch-input-method-local-p (local-variable-p 'input-method-function)
784 785 786 787 788 789
	regexp-search-ring-yank-pointer nil

	;; Save the original value of `minibuffer-message-timeout', and
	;; set it to nil so that isearch's messages don't get timed out.
	isearch-original-minibuffer-message-timeout minibuffer-message-timeout
	minibuffer-message-timeout nil)
790 791 792

  ;; We must bypass input method while reading key.  When a user type
  ;; printable character, appropriate input method is turned on in
793
  ;; minibuffer to read multibyte characters.
794 795 796 797
  (or isearch-input-method-local-p
      (make-local-variable 'input-method-function))
  (setq input-method-function nil)

798
  (looking-at "")
799 800
  (setq isearch-window-configuration
	(if isearch-slow-terminal-mode (current-window-configuration) nil))
801

802 803
  ;; Maybe make minibuffer frame visible and/or raise it.
  (let ((frame (window-frame (minibuffer-window))))
804 805 806 807 808
    (unless (memq (frame-live-p frame) '(nil t))
      (unless (frame-visible-p frame)
	(make-frame-visible frame))
      (if minibuffer-auto-raise
	  (raise-frame frame))))
809

Jim Blandy's avatar
Jim Blandy committed
810
  (setq	isearch-mode " Isearch")  ;; forward? regexp?
811
  (force-mode-line-update)
Jim Blandy's avatar
Jim Blandy committed
812

813
  (setq overriding-terminal-local-map isearch-mode-map)
Jim Blandy's avatar
Jim Blandy committed
814
  (run-hooks 'isearch-mode-hook)
815 816 817 818 819 820

  ;; Pushing the initial state used to be before running isearch-mode-hook,
  ;; but a hook might set `isearch-push-state-function' used in
  ;; `isearch-push-state' to save mode-specific initial state.  (Bug#4994)
  (isearch-push-state)

821
  (isearch-update)
822

823
  (add-hook 'mouse-leave-buffer-hook 'isearch-done)
824
  (add-hook 'kbd-macro-termination-hook 'isearch-done)
825

826 827
  ;; isearch-mode can be made modal (in the sense of not returning to
  ;; the calling function until searching is completed) by entering
828
  ;; a recursive-edit and exiting it when done isearching.
829 830 831
  (if recursive-edit
      (let ((isearch-recursive-edit t))
	(recursive-edit)))
832
  isearch-success)
Jim Blandy's avatar
Jim Blandy committed
833 834 835 836 837


;; Some high level utilities.  Others below.

(defun isearch-update ()
838 839
  "This is called after every isearch command to update the display.
The last thing it does is to run `isearch-update-post-hook'."
840 841
  (if (and (null unread-command-events)
	   (null executing-kbd-macro))
Jim Blandy's avatar
Jim Blandy committed
842
      (progn
843
        (if (not (input-pending-p))
844 845 846
	    (if isearch-message-function
		(funcall isearch-message-function)
	      (isearch-message)))
847
        (if (and isearch-slow-terminal-mode
848
                 (not (or isearch-small-window