Download
(require 'misc-cmds nil t)
(defvar bidi-display-reordering)
(defvar isearch-error)
(defvar isearch-filter-predicate)
(defvar isearch-invalid-regexp)
(defvar isearch-last-case-fold-search)
(defvar isearch-message-prefix-add)
(defvar isearch-new-message)
(defvar isearch-new-string)
(defvar isearch-original-minibuffer-message-timeout)
(defvar isearch-push-state-function)
(defvar isearch-start-hscroll)
(defvar isearch-within-brackets)
(defvar isearch-wrap-function)
(defvar last-repeatable-command)
(defvar minibuffer-message-timeout)
(defvar multi-isearch-next-buffer-current-function)
(defvar subword-mode)
(defvar isearchp-initiate-edit-commands)
(defgroup isearch-plus nil
"Isearch enhancements."
:prefix "isearchp-" :group 'isearch
:link `(url-link :tag "Send Bug Report"
,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
Isearch+ bug: \
&body=Describe bug here, starting with `emacs -Q'. \
Don't forget to mention your Emacs and library versions."))
:link '(url-link :tag "Download" "http://www.emacswiki.org/isearch+.el")
:link '(url-link :tag "Description" "http://www.emacswiki.org/IsearchPlus")
:link '(emacs-commentary-link :tag "Commentary" "isearch+"))
(when (> emacs-major-version 21)
(defface isearch-fail
'((((class color) (min-colors 88) (background dark))
(:foreground "white" :background "#22225F5F2222"))
(((class color) (min-colors 88) (background light))
(:foreground "Black" :background "Plum"))
(((class color) (min-colors 8)) (:background "red"))
(((type tty) (class mono)) :inverse-video t)
(t :background "gray"))
"*Face for highlighting failed part in Isearch echo-area message."
:group 'isearch-plus)
(defface isearchp-wrapped
'((((class color) (min-colors 88)) (:foreground "DeepPink"))
(t :underline t))
"*Face for highlighting wrapped-search indicator in Isearch echo-area message."
:group 'isearch-plus)
(defface isearchp-regexp
'((((class color) (min-colors 8)) (:foreground "Firebrick"))
(t :underline t))
"*Face for highlighting regexp-search indicator in Isearch echo-area message."
:group 'isearch-plus)
(defface isearchp-word
'((((class color) (min-colors 8)) (:foreground "DarkGreen"))
(t :underline t))
"*Face for highlighting word-search indicator in Isearch echo-area message."
:group 'isearch-plus)
(defface isearchp-multi
'((((class color) (min-colors 8)) (:foreground "DarkViolet"))
(t :underline t))
"*Face for highlighting multi-buffer indicator in Isearch echo-area message."
:group 'isearch-plus))
(when (fboundp 'isearch-unread-key-sequence)
(defun isearchp-init-edit (&rest ignored)
"Invoke current key sequence, but after calling `isearch-edit-string'."
(interactive)
(isearch-unread-key-sequence
(listify-key-sequence (this-command-keys)))
(isearch-edit-string))
(defun isearchp-update-edit-init-commands ()
"Make `isearchp-initiate-edit-commands' edit the search string."
(dolist (cmd isearchp-initiate-edit-commands)
(substitute-key-definition cmd 'isearchp-init-edit isearch-mode-map (current-global-map))))
(defcustom isearchp-initiate-edit-commands
'(backward-char
left-char
backward-sexp
backward-word
left-word
)
"*Commands whose key bindings initiate Isearch edit.
When invoked by a key sequence, Isearch edits the search string,
applying the command to it immediately.
Commands you might want to include here are typically commands that
move point to the left, possibly deleting text along the way.
Set this to `nil' if you always want all such commands to exit Isearch
and act on the buffer text."
:set #'(lambda (sym defs)
(custom-set-default sym defs)
(isearchp-update-edit-init-commands))
:type '(repeat (restricted-sexp :tag "Command"
:match-alternatives (symbolp) :value ignore))
:group 'isearch-plus))
(defcustom isearchp-drop-mismatch nil
"*Non-nil means remove or replace a search-string mismatch.
There are three possible values:
`replace-last' - Replace the last mismatch in the search string with
the latest input (e.g., replace the last typed char
or last yanked text).
nil - Never remove mismatched text from the search string.
anything else - Always remove mismatched text from the search string.
* Vanilla Isearch has the behavior of a nil value.
* Non-nil, non-`replace-last' means the search string never contains
mismatched characters.
* `replace-last' means you see only the latest mismatched input, and
it is available for editing, using \\<isearch-mode-map>`\\[isearch-edit-string]'.
You can cycle among the three possible values using \
`\\[isearchp-cycle-mismatch-removal]'."
:type '(choice
(const :tag "Replace last mismatch" 'replace-last)
(const :tag "Never remove mismatch" nil)
(other :tag "Always remove mismatch" t))
:group 'isearch-plus)
(defcustom isearchp-mouse-2-flag t
"*Non-nil means clicking `mouse-2' during Isearch yanks the selection.
In that case, you can select text with the mouse, then hit `C-s' to
search for it.
If the value is nil, yank only if the `mouse-2' click is in the echo
area. If not in the echo area, invoke whatever `mouse-2' is bound to
outside of Isearch."
:type 'boolean :group 'isearch-plus)
(defcustom isearchp-regexp-quote-yank-flag t
"*Non-nil means escape special chars in text yanked for a regexp isearch.
You can toggle this with `isearchp-toggle-regexp-quote-yank', bound to
`C-`' during isearch."
:type 'boolean :group 'isearch-plus)
(defcustom isearchp-set-region-flag nil
"*Non-nil means set region around search target.
This is used only for Transient Mark mode.
You can toggle this with `isearchp-toggle-set-region', bound to
`C-SPC' during isearch."
:type 'boolean :group 'isearch-plus)
(defvar isearchp-last-non-nil-invisible (or search-invisible 'open)
"Last non-nil value of `search-invisible'.")
(defvar isearchp-last-quit-search nil
"Last successful search string when you hit `C-g' to quit Isearch.")
(defvar isearchp-last-quit-regexp-search nil
"Last successful search regexp when you hit `C-g' to quit regexp Isearch.")
(defvar isearchp-win-pt-line nil
"Line number of point before searching, relative to `window-start'.")
(defun isearchp-cycle-mismatch-removal ()
"Cycle option `isearchp-drop-mismatch'."
(interactive)
(setq isearchp-drop-mismatch (case isearchp-drop-mismatch
(replace-last nil)
((nil) t)
(otherwise 'replace-last)))
(if (and isearchp-drop-mismatch (not (eq 'replace-last isearchp-drop-mismatch)))
(add-hook 'isearch-update-post-hook 'isearchp-remove-mismatch)
(remove-hook 'isearch-update-post-hook 'isearchp-remove-mismatch))
(case isearchp-drop-mismatch
(replace-last (message "Automatic REPLACEMENT of last mismatched input is now ON"))
((nil) (message "Automatic removal of mismatched input is now OFF"))
(otherwise (message "Automatic removal of ALL mismatched input is now ON")))
(sit-for 1)
(isearch-update))
(defun isearchp-remove-mismatch ()
"Remove the mismatched portion of the search string."
(while (or (not isearch-success) (if (boundp 'isearch-error)
isearch-error
isearch-invalid-regexp))
(isearch-pop-state))
(remove-hook 'isearch-update-post-hook 'isearchp-remove-mismatch)
(isearch-update)
(add-hook 'isearch-update-post-hook 'isearchp-remove-mismatch))
(defun isearchp-toggle-invisible ()
"Toggle `search-invisible'."
(interactive)
(when search-invisible (setq isearchp-last-non-nil-invisible search-invisible))
(setq search-invisible (if search-invisible nil isearchp-last-non-nil-invisible))
(if search-invisible
(message "Searching invisible text is now ON")
(message "Searching invisible text is now OFF"))
(sit-for 1)
(isearch-update))
(defun isearchp-toggle-regexp-quote-yank ()
"Toggle `isearchp-regexp-quote-yank-flag'."
(interactive)
(setq isearchp-regexp-quote-yank-flag (not isearchp-regexp-quote-yank-flag))
(if isearchp-regexp-quote-yank-flag
(message "Escaping regexp special chars for yank is now ON")
(message "Escaping regexp special chars for yank is now OFF"))
(sit-for 1)
(isearch-update))
(defun isearchp-toggle-set-region ()
"Toggle `isearchp-set-region-flag'."
(interactive)
(setq isearchp-set-region-flag (not isearchp-set-region-flag))
(if isearchp-set-region-flag
(message "Setting region around search target is now ON")
(message "Setting region around search target is now OFF"))
(sit-for 1)
(isearch-update))
(defun isearch-toggle-word ()
"Toggle word searching on or off."
(interactive)
(setq isearch-word (not isearch-word))
(when isearch-word (setq isearch-regexp nil))
(setq isearch-success t
isearch-adjusted t)
(if isearch-word (message "Whole word search is now ON") (message "Whole word search is now OFF"))
(sit-for 1)
(isearch-update))
(defun isearchp-set-region-around-search-target ()
"Set the region around the last search or query-replace target."
(interactive)
(case last-command
((isearch-forward isearch-backward isearch-forward-regexp isearch-backward-regexp)
(push-mark isearch-other-end t 'activate))
(t (push-mark (match-beginning 0) t 'activate)))
(setq deactivate-mark nil))
(defun isearchp-message-prefix (&optional arg1 arg2 arg3)
"Version of `isearch-message-prefix' that works for all Emacs releases."
(if (or (< emacs-major-version 24)
(and (= emacs-major-version 24) (< emacs-minor-version 3)
(not (string-match "^[0-9]+\\.[0-9]+\\.[0-9]+" emacs-version))))
(isearch-message-prefix arg1 arg2 arg3)
(isearch-message-prefix arg1 arg2)))
(defun isearchp-message-suffix (&optional arg1 arg2)
"Version of `isearch-message-suffix' that works for all Emacs releases."
(if (or (< emacs-major-version 24)
(and (= emacs-major-version 24) (< emacs-minor-version 3)
(not (string-match "^[0-9]+\\.[0-9]+\\.[0-9]+" emacs-version))))
(isearch-message-suffix arg1 arg2)
(isearch-message-suffix arg1)))
(defun isearch-toggle-case-fold ()
"Toggle case folding in searching on or off.
The minor-mode lighter is `ISEARCH' for case-insensitive, `Isearch'
for case-sensitive."
(interactive)
(setq isearch-case-fold-search (if isearch-case-fold-search nil 'yes)
isearch-success t
isearch-adjusted t)
(isearchp-highlight-lighter)
(let ((message-log-max nil))
(message "%s%s [case %ssensitive]" (isearchp-message-prefix nil nil isearch-nonincremental)
isearch-message (if isearch-case-fold-search "in" "")))
(sit-for 1)
(isearch-update))
(defun isearch-mode-help ()
"Display information on interactive search in buffer *Help*."
(interactive)
(describe-function 'isearch-forward)
(isearch-done)
(isearch-clean-overlays)
(with-current-buffer "*Help*"
(goto-char (point-max))
(let ((buffer-read-only nil))
(insert (substitute-command-keys "
Bindings in Isearch minor mode:
------------------------------
\\{isearch-mode-map}")))))
(when (and (> emacs-major-version 21)
(or (< emacs-major-version 24) (and (= emacs-major-version 24) (< emacs-minor-version 4))))
(defmacro with-isearch-suspended (&rest body)
"Exit Isearch mode, run BODY, and reinvoke the pending search.
BODY can involve use of the minibuffer, including recursive minibuffers.
You can update the global isearch variables by setting new values to
`isearch-new-string', `isearch-new-message', `isearch-new-forward',
`isearch-new-word', `isearch-new-case-fold'."
`(condition-case nil
(progn
(let ((enable-recursive-minibuffers t)
(isearch-nonincremental isearch-nonincremental)
(isearch-new-string isearch-string)
(isearch-new-message isearch-message)
(isearch-new-forward isearch-forward)
(isearch-new-word isearch-word)
(isearch-new-case-fold isearch-case-fold-search)
(isearch-regexp isearch-regexp)
(isearch-op-fun isearch-op-fun)
(isearch-cmds isearch-cmds)
(isearch-success isearch-success)
(isearch-wrapped isearch-wrapped)
(isearch-barrier isearch-barrier)
(isearch-adjusted isearch-adjusted)
(isearch-yank-flag isearch-yank-flag)
(isearch-error isearch-error)
(isearch-opoint isearch-opoint)
(isearch-slow-terminal-mode isearch-slow-terminal-mode)
(isearch-small-window isearch-small-window)
(isearch-recursive-edit isearch-recursive-edit)
(isearch-window-configuration (current-window-configuration))
(minibuffer-message-timeout isearch-original-minibuffer-message-timeout)
(isearch-original-minibuffer-message-timeout
isearch-original-minibuffer-message-timeout)
old-point old-other-end)
(condition-case nil (isearch-done t t) (exit nil))
(setq old-point (point)
old-other-end isearch-other-end)
(unwind-protect (progn ,@body)
(if (and old-other-end (eq old-point (point)) (eq isearch-forward
isearch-new-forward))
(goto-char old-other-end))
(isearch-mode isearch-forward isearch-regexp isearch-op-fun nil isearch-word)
(setq isearch-string isearch-new-string
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-word isearch-new-word
isearch-case-fold-search isearch-new-case-fold))
(when (= 0 (length isearch-string))
(setq isearch-string (or (car (if isearch-regexp regexp-search-ring search-ring))
"")
isearch-message (mapconcat 'isearch-text-char-description
isearch-string ""))
(isearch-ring-adjust1 nil)))
(isearch-search)
(isearch-push-state)
(isearch-update)
(when isearch-nonincremental
(isearch-done)
(when (equal isearch-string "") (message ""))))
(quit (isearch-abort)))))
(when (> emacs-major-version 21)
(defun isearch-edit-string ()
"Edit the search string in the minibuffer.
The following additional command keys are active while editing.
\\<minibuffer-local-isearch-map>
\\[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-reverse-exit-minibuffer] to resume isearching backward.
\\[isearch-complete-edit] to complete the search string using the search ring.
\\[insert-char] to insert a Unicode character by name (with completion)."
(interactive)
(with-isearch-suspended
(let* ((message-log-max nil)
(history-add-new-input nil)
(minibuffer-history-symbol nil))
(setq isearch-new-string (read-from-minibuffer
(isearchp-message-prefix nil nil isearch-nonincremental)
(cons isearch-string (1+ (or (isearch-fail-pos)
(length isearch-string))))
minibuffer-local-isearch-map nil
(if isearch-regexp
(cons 'regexp-search-ring
(1+ (or regexp-search-ring-yank-pointer -1)))
(cons 'search-ring (1+ (or search-ring-yank-pointer -1))))
nil t)
isearch-new-message (mapconcat 'isearch-text-char-description isearch-new-string
"")))))
(defun isearchp-open-recursive-edit ()
"Invoke the editor command loop recursively, during Isearch.
Use `\\[exit-recursive-edit]' to end the recursive edit and resume searching from there.
Or use `abort-recursive-edit' to exit the recursive edit and cancel the previous search."
(interactive)
(with-isearch-suspended (recursive-edit))))
(when (< emacs-major-version 22)
(defun isearch-edit-string ()
"Edit the search string in the minibuffer.
The following additional command keys are active while editing.
\\<minibuffer-local-isearch-map>
\\[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-reverse-exit-minibuffer] to resume isearching backward.
\\[isearch-complete-edit] to complete the search string using the search ring.
\\<isearch-mode-map>
If first char entered is \\[isearch-yank-word], then do word search instead."
(interactive)
(condition-case nil
(progn (let ((isearch-nonincremental isearch-nonincremental)
(isearch-new-string isearch-string)
(isearch-new-message isearch-message)
(isearch-new-forward isearch-forward)
(isearch-new-word isearch-word)
(isearch-regexp isearch-regexp)
(isearch-op-fun isearch-op-fun)
(isearch-cmds isearch-cmds)
(isearch-success isearch-success)
(isearch-wrapped isearch-wrapped)
(isearch-barrier isearch-barrier)
(isearch-adjusted isearch-adjusted)
(isearch-yank-flag isearch-yank-flag)
(isearch-invalid-regexp isearch-invalid-regexp)
(isearch-within-brackets isearch-within-brackets)
(isearch-opoint isearch-opoint)
(isearch-slow-terminal-mode isearch-slow-terminal-mode)
(isearch-small-window isearch-small-window)
(isearch-recursive-edit isearch-recursive-edit)
(isearch-window-configuration (current-window-configuration))
old-point old-other-end)
(condition-case nil (isearch-done t t) (exit nil))
(setq old-point (point)
old-other-end isearch-other-end)
(unwind-protect
(let* ((message-log-max nil)
(minibuffer-history-symbol nil))
(setq isearch-new-string (read-from-minibuffer
(isearchp-message-prefix nil nil
isearch-nonincremental)
(cons isearch-string
(1+ (length isearch-string)))
minibuffer-local-isearch-map nil
(if isearch-regexp
(cons
'regexp-search-ring
(1+ (or regexp-search-ring-yank-pointer
-1)))
(cons 'search-ring
(1+ (or search-ring-yank-pointer -1))))
nil t)
isearch-new-message (mapconcat 'isearch-text-char-description
isearch-new-string "")))
(if (and old-other-end (eq old-point (point)) (eq isearch-forward
isearch-new-forward))
(goto-char old-other-end))
(isearch-mode isearch-forward isearch-regexp isearch-op-fun nil isearch-word)
(setq isearch-string isearch-new-string
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-word isearch-new-word))
(if (= 0 (length isearch-string))
(setq isearch-string (or (car (if isearch-regexp
regexp-search-ring
search-ring))
"")
isearch-message (mapconcat 'isearch-text-char-description
isearch-string ""))
))
(isearch-search)
(isearch-push-state)
(isearch-update)
(when isearch-nonincremental
(isearch-done)
(if (equal isearch-string "")
(message ""))))
(quit (isearch-abort)))))
(when (and (> emacs-major-version 22)
(or (< emacs-major-version 24) (and (= emacs-major-version 24) (< emacs-minor-version 3))))
(defun isearch-insert-char-by-name ()
"Read a character by its Unicode name and insert it into search string."
(interactive)
(with-isearch-suspended
(let ((char (read-char-by-name "Insert character (Unicode name or hex): ")))
(when char
(setq isearch-new-string (concat isearch-string (string char))
isearch-new-message (concat isearch-message
(mapconcat 'isearch-text-char-description (string char)
""))))))))
(when (fboundp 'isearch-yank-internal)
(defun isearchp-yank-char ()
"Yank next character from buffer onto search string.
You can repeat this by hitting the last key again..."
(interactive)
(require 'repeat nil t)
(isearchp-repeat-command 'isearch-yank-char))
(defun isearchp-yank-word-or-char ()
"Yank next word or character from buffer onto search string.
You can repeat this by hitting the last key again..."
(interactive)
(require 'repeat nil t)
(isearchp-repeat-command 'isearch-yank-word-or-char))
(defun isearchp-yank-line ()
"Yank text from buffer up to end of line onto search string.
You can repeat this by hitting the last key again..."
(interactive)
(require 'repeat nil t)
(isearchp-repeat-command 'isearch-yank-line))
(defun isearchp-yank-symbol-or-char-1 ()
"Helper for `isearchp-yank-symbol-or-char'.
Not intended/needed as a user command."
(interactive)
(isearch-yank-internal
(lambda ()
(if (or (memq (char-syntax (or (char-after) 0)) '(?w ?_))
(memq (char-syntax (or (char-after (1+ (point))) 0)) '(?w ?_)))
(if (and (boundp 'subword-mode) subword-mode) (subword-forward 1) (forward-symbol 1))
(forward-char 1))
(point))))
(defun isearchp-yank-symbol-or-char ()
"Yank char, subword, word, or symbol from buffer into search string.
You can repeat this by hitting the last key again..."
(interactive)
(require 'repeat nil t)
(isearchp-repeat-command 'isearchp-yank-symbol-or-char-1))
(defun isearchp-yank-sexp-symbol-or-char-1 ()
"Helper function for `isearchp-yank-sexp-symbol-or-char'.
Not intended/needed as a user command."
(interactive)
(isearch-yank-internal
(lambda ()
(if (or (= (char-syntax (or (char-after) 0)) ?\( )
(= (char-syntax (or (char-after (1+ (point))) 0)) ?\( ))
(forward-sexp 1)
(if (or (memq (char-syntax (or (char-after) 0)) '(?w ?_))
(memq (char-syntax (or (char-after (1+ (point))) 0)) '(?w ?_)))
(if (and (boundp 'subword-mode) subword-mode) (subword-forward 1) (forward-symbol 1))
(forward-char 1)))
(point))))
(defun isearchp-yank-sexp-symbol-or-char ()
"Yank sexp, symbol, subword, word, or char into search string.
You can repeat this by hitting the last key again..."
(interactive)
(require 'repeat nil t)
(isearchp-repeat-command 'isearchp-yank-sexp-symbol-or-char-1)))
(defun isearchp-kill-ring-save ()
"Copy the current search string to the kill ring.
For example, you can then use `C-s M-y' to search for the same thing
in another Emacs session."
(interactive)
(kill-new isearch-string)
(let ((message-log-max nil)) (message "Copied search string as kill"))
(sit-for 1)
(isearch-update))
(defun isearchp-retrieve-last-quit-search ()
"Insert last successful search string from when you hit `C-g' in Isearch.
Bound to `\\<isearch-mode-map>\\[isearchp-retrieve-last-quit-search]' during Isearch."
(interactive)
(cond ((and isearch-regexp isearchp-last-quit-regexp-search)
(let ((isearchp-regexp-quote-yank-flag nil))
(isearch-yank-string isearchp-last-quit-regexp-search)))
(isearchp-last-quit-search
(isearch-yank-string isearchp-last-quit-search))))
(when (> emacs-major-version 20)
(defun isearchp-fontify-buffer-now ()
"Fontify buffer completely, right now.
This differs from `font-lock-fontify-buffer', which is lazy and does
not necessarily fontify the whole buffer."
(interactive)
(jit-lock-fontify-now)))
(defun isearch-mode (forward &optional regexp op-fun recursive-edit word)
"Start Isearch minor mode.
It is called by the function `isearch-forward' and other related functions."
(setq isearch-forward forward
isearch-regexp regexp
isearch-word word
isearch-op-fun op-fun
isearch-last-case-fold-search isearch-case-fold-search
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
isearch-invalid-regexp nil
isearch-within-brackets nil
isearch-error nil
isearch-slow-terminal-mode (and (<= baud-rate search-slow-speed)
(> (window-height)
(* 4
(abs search-slow-window-lines))))
isearch-other-end nil
isearch-small-window nil
isearch-just-started t
isearch-start-hscroll (window-hscroll)
isearch-opoint (point)
isearchp-win-pt-line (- (line-number-at-pos)
(line-number-at-pos (window-start)))
search-ring-yank-pointer nil
isearch-opened-overlays nil
isearch-input-method-function input-method-function
isearch-input-method-local-p (local-variable-p 'input-method-function)
regexp-search-ring-yank-pointer nil
isearch-original-minibuffer-message-timeout (and (boundp 'minibuffer-message-timeout)
minibuffer-message-timeout)
minibuffer-message-timeout nil)
(unless isearch-input-method-local-p (make-local-variable 'input-method-function))
(setq input-method-function nil)
(looking-at "")
(setq isearch-window-configuration
(if isearch-slow-terminal-mode (current-window-configuration) nil))
(let ((frame (window-frame (minibuffer-window))))
(unless (memq (frame-live-p frame) '(nil t))
(unless (frame-visible-p frame)
(make-frame-visible frame))
(if minibuffer-auto-raise
(raise-frame frame))))
(setq isearch-mode " Isearch")
(force-mode-line-update)
(setq overriding-terminal-local-map isearch-mode-map)
(run-hooks 'isearch-mode-hook)
(isearch-push-state)
(isearch-update)
(add-hook 'mouse-leave-buffer-hook 'isearch-done)
(add-hook 'kbd-macro-termination-hook 'isearch-done)
(if recursive-edit
(let ((isearch-recursive-edit t))
(recursive-edit)))
isearch-success)
(cond ((or (> emacs-major-version 23)
(and (= emacs-major-version 23) (> emacs-minor-version 1)))
(defun isearch-cancel ()
"Terminate the search and go back to the starting point."
(interactive)
(if (and isearch-push-state-function isearch-cmds)
(let ((isearch-cmds (last isearch-cmds)))
(if (fboundp 'isearch--set-state)
(isearch--set-state (car isearch-cmds))
(isearch-top-state))
(when isearchp-win-pt-line (recenter isearchp-win-pt-line)))
(goto-char isearch-opoint)
(when isearchp-win-pt-line (recenter isearchp-win-pt-line)))
(isearch-done t)
(isearch-clean-overlays)
(signal 'quit nil)))
(t
(defun isearch-cancel ()
"Terminate the search and go back to the starting point."
(interactive)
(when (and (fboundp 'isearch-pop-fun-state)
(functionp (isearch-pop-fun-state (car (last isearch-cmds)))))
(funcall (isearch-pop-fun-state (car (last isearch-cmds))) (car (last isearch-cmds))))
(goto-char isearch-opoint)
(when isearchp-win-pt-line (recenter isearchp-win-pt-line))
(isearch-done t)
(isearch-clean-overlays)
(signal 'quit nil))))
(defun isearch-abort ()
"Abort incremental search mode if searching is successful, signaling quit.
Otherwise, revert to previous successful search and continue searching.
Use `isearch-exit' to quit without signaling."
(interactive)
(discard-input)
(if (and isearch-success
(or (not (boundp 'isearch-error)) (not isearch-error)))
(progn (setq isearch-success nil)
(set (if isearch-regexp 'isearchp-last-quit-regexp-search 'isearchp-last-quit-search)
isearch-string)
(if (fboundp 'isearch-cancel)
(isearch-cancel)
(goto-char isearch-opoint)
(isearch-done t)
(isearch-clean-overlays)
(signal 'quit nil)))
(while (or (not isearch-success) (if (boundp 'isearch-error)
isearch-error
isearch-invalid-regexp))
(isearch-pop-state))
(isearch-update)))
(defun isearch-yank-string (string)
"Yank STRING into Isearch search string."
(if (and isearch-case-fold-search (eq 'not-yanks search-upper-case))
(setq string (downcase string)))
(when (and isearch-regexp isearchp-regexp-quote-yank-flag) (setq string (regexp-quote string)))
(setq isearch-yank-flag t)
(if (fboundp 'isearch-process-search-string)
(isearch-process-search-string string (mapconcat 'isearch-text-char-description string ""))
(setq isearch-string (concat isearch-string string)
isearch-message (concat isearch-message (mapconcat 'isearch-text-char-description string
"")))
(isearch-search-and-update)))
(defun isearch-mouse-2 (click)
"Handle `mouse-2' in Isearch mode.
If `isearchp-mouse-2-flag' is non-nil, yank the X selection.
If `isearchp-mouse-2-flag' is nil, yank it only if the `mouse-2' click
is in the echo area. Otherwise, invoke whatever `mouse-2' is bound to
outside of Isearch."
(interactive "e")
(if isearchp-mouse-2-flag
(when (/= (region-beginning) (region-end)) (isearchp-set-sel-and-yank))
(let ((win (posn-window (event-start click)))
(overriding-terminal-local-map nil)
(binding (key-binding (this-command-keys-vector) t)))
(if (and (window-minibuffer-p win) (not (minibuffer-window-active-p win)))
(isearchp-set-sel-and-yank)
(when (functionp binding) (call-interactively binding))))))
(defun isearchp-set-sel-and-yank ()
"Set X selection and yank it into echo area."
(x-set-selection 'PRIMARY (buffer-substring-no-properties (region-beginning) (region-end)))
(deactivate-mark)
(isearch-yank-x-selection))
(defun isearch-printing-char ()
"Add this ordinary printing character to the search string and search."
(interactive)
(when (eq isearchp-drop-mismatch 'replace-last)
(while (or (not isearch-success) (if (boundp 'isearch-error)
isearch-error
isearch-invalid-regexp))
(isearch-pop-state)))
(let ((char last-command-event))
(if (= char ?\S-\ )
(setq char ?\ ))
(if current-input-method
(isearch-process-search-multibyte-characters char)
(isearch-process-search-char char))))
(when (or (= emacs-major-version 22) (= emacs-major-version 23))
(defun isearch-message (&optional c-q-hack ellipsis)
(let ((cursor-in-echo-area ellipsis)
(msg isearch-message)
(fail-pos (isearch-fail-pos t)))
(when fail-pos
(setq msg (copy-sequence msg))
(add-text-properties fail-pos (length msg) '(face isearch-fail) msg)
(when (string-match " +$" msg)
(add-text-properties (match-beginning 0) (match-end 0) '(face trailing-whitespace) msg)))
(setq msg (concat (isearch-message-prefix c-q-hack ellipsis isearch-nonincremental)
msg
(isearch-message-suffix c-q-hack ellipsis)))
(if c-q-hack msg (let ((message-log-max nil)) (message "%s" msg)))))
(defun isearch-fail-pos (&optional msg)
"Return position of first mismatch in search string, or nil if none.
If MSG is non-nil, use `isearch-message', otherwise `isearch-string'."
(let ((cmds isearch-cmds)
(curr-msg (if msg isearch-message isearch-string))
succ-msg)
(when (or (not isearch-success) isearch-error)
(while (or (not (isearch-success-state (car cmds))) (isearch-error-state (car cmds)))
(pop cmds))
(setq succ-msg (and cmds (if msg
(isearch-message-state (car cmds))
(isearch-string-state (car cmds)))))
(if (and (stringp succ-msg)
(< (length succ-msg) (length curr-msg))
(equal succ-msg (substring curr-msg 0 (length succ-msg))))
(length succ-msg)
0)))))
(when (and (> emacs-major-version 21)
(or (< emacs-major-version 24) (and (= emacs-major-version 24) (< emacs-minor-version 3))))
(defun isearch-message-prefix (&optional _c-q-hack ellipsis nonincremental)
(and isearch-error ellipsis (condition-case ()
(progn (re-search-forward isearch-string (point) t)
(setq isearch-error nil))
(error nil)))
(unless isearch-success (setq ellipsis nil))
(let ((m (concat (and (not isearch-success) (propertize "failing " 'face 'minibuffer-prompt))
(and isearch-adjusted (propertize "pending " 'face 'minibuffer-prompt))
(and isearch-wrapped
(not isearch-wrap-function)
(if isearch-forward (> (point) isearch-opoint) (< (point) isearch-opoint))
(propertize "over" 'face 'isearchp-wrapped))
(and isearch-wrapped (propertize "wrapped " 'face 'isearchp-wrapped))
(and isearch-word (propertize "word " 'face 'isearchp-word))
(and isearch-regexp (propertize "regexp " 'face 'isearchp-regexp))
(and (boundp 'multi-isearch-next-buffer-current-function)
multi-isearch-next-buffer-current-function
(propertize "multi " 'face 'isearchp-multi))
(and (boundp 'isearch-message-prefix-add)
isearch-message-prefix-add
(propertize isearch-message-prefix-add 'face 'minibuffer-prompt))
(propertize (if nonincremental "search" "I-search") 'face 'minibuffer-prompt)
(and (not isearch-forward) (propertize " backward" 'face 'minibuffer-prompt))
(propertize (if (and (boundp 'bidi-display-reordering)
current-input-method)
(bidi-string-mark-left-to-right
(concat " [" current-input-method-title "]: "))
": ")
'face 'minibuffer-prompt))))
(concat (upcase (substring m 0 1)) (substring m 1)))))
(when (and (> emacs-major-version 23)
(or (> emacs-major-version 24) (and (= emacs-major-version 24) (> emacs-minor-version 2))))
(defun isearch-message-prefix (&optional ellipsis nonincremental)
(and isearch-error ellipsis (condition-case ()
(progn (re-search-forward isearch-string (point) t)
(setq isearch-error nil))
(error nil)))
(unless isearch-success (setq ellipsis nil))
(let ((m (concat (and (not isearch-success) (propertize "failing " 'face 'minibuffer-prompt))
(and isearch-adjusted (propertize "pending " 'face 'minibuffer-prompt))
(and isearch-wrapped
(not isearch-wrap-function)
(if isearch-forward (> (point) isearch-opoint) (< (point) isearch-opoint))
(propertize "over" 'face 'isearchp-wrapped))
(and isearch-wrapped (propertize "wrapped " 'face 'isearchp-wrapped))
(and isearch-word
(propertize (or (and (symbolp isearch-word)
(get isearch-word 'isearch-message-prefix))
"word ")
'face 'isearchp-word))
(and isearch-regexp (propertize "regexp " 'face 'isearchp-regexp))
(and multi-isearch-next-buffer-current-function
(propertize "multi " 'face 'isearchp-multi))
(and isearch-message-prefix-add
(propertize isearch-message-prefix-add 'face 'minibuffer-prompt))
(propertize (if nonincremental "search" "I-search") 'face 'minibuffer-prompt)
(and (not isearch-forward) (propertize " backward" 'face 'minibuffer-prompt))
(propertize (if current-input-method
(bidi-string-mark-left-to-right
(concat " [" current-input-method-title "]: "))
": ")
'face 'minibuffer-prompt))))
(concat (upcase (substring m 0 1)) (substring m 1)))))
(defun isearchp-read-face-names (&optional empty-means-none-p only-one-p)
"Read face names with completion, and return a list of their symbols.
If user hits `RET' with empty input immediately, then include all
faces. Otherwise, read faces one by one, until user hits `RET' twice
consecutively.
Non-nil optional arg EMPTY-MEANS-NONE-P means return nil (no face
names) for empty user input.
Non-nil optional arg ONLY-ONE-P means read only one face name and
return its symbol."
(let ((icicle-multi-completing-p t)
(icicle-list-nth-parts-join-string ": ")
(icicle-list-join-string ": ")
(icicle-list-use-nth-parts '(1))
(icicle-proxy-candidates
(and (boundp 'icicle-add-proxy-candidates-flag) icicle-add-proxy-candidates-flag
(append (and (fboundp 'eyedrop-face-at-point) (list "*point face name*"))
(let ((ipc ()))
(mapatoms
(lambda (cand)
(when (and (user-variable-p cand) (eq (get cand 'custom-type) 'face))
(push `,(concat "'" (symbol-name cand) "'") ipc))))
ipc))))
(face-cands (mapcar
(if (and (boundp 'icicle-mode) icicle-mode)
#'icicle-make-face-candidate
(lambda (face) (list (symbol-name face))))
(face-list)))
(faces ())
(prompt1 "Face (RET for each, empty input to finish): ")
(prompt2 "Face: ")
(icicle-unpropertize-completion-result-flag t)
face)
(when (and (boundp 'icicle-mode) icicle-mode)
(put-text-property 0 1 'icicle-fancy-candidates t prompt1)
(put-text-property 0 1 'icicle-fancy-candidates t prompt2))
(setq face (isearchp-read-face-names--read prompt1 face-cands))
(if (and empty-means-none-p (string= "" face))
()
(if only-one-p
face
(if (string= "" face)
(setq faces (face-list))
(setq face-cands (delete (assoc face face-cands) face-cands))
(while (not (string= "" face))
(add-to-list 'faces (intern face))
(setq face (isearchp-read-face-names--read prompt2 face-cands)
face-cands (delete (assoc face face-cands) face-cands)))
(nreverse faces))))))
(defun isearchp-read-face-names--read (prompt candidates)
"Read a face name using PROMPT and face-name completion CANDIDATES."
(if (and (boundp 'icicle-mode) icicle-mode)
(icicle-transform-multi-completion
(completing-read
prompt candidates nil (not (stringp icicle-WYSIWYG-Completions-flag)) nil
(if (boundp 'face-name-history) 'face-name-history 'icicle-face-name-history)))
(completing-read prompt candidates nil t nil 'face-name-history)))
(defun isearchp-read-sexps (&optional only-one-p)
"Read sexps with completion, and return them as a list.
Read sexps one by one, until user hits `RET' twice consecutively.
Non-nil ONLY-ONE-P means read only one sexp and return it."
(let ((sexp-cands (mapcar #'list (isearchp-remove-duplicates
read-expression-history)))
(sexps ())
(prompt1 "Sexp (RET for each, empty input to finish): ")
(prompt2 "Sexp: ")
sexp)
(setq sexp (completing-read (if only-one-p prompt2 prompt1) sexp-cands
nil nil nil 'read-expression-history)
sexp-cands (delete (assoc sexp sexp-cands) sexp-cands))
(if only-one-p
(car (read-from-string sexp))
(while (not (string= "" sexp))
(add-to-list 'sexps sexp)
(setq sexp (completing-read prompt2 sexp-cands nil nil nil 'read-expression-history)
sexp-cands (delete (assoc sexp sexp-cands) sexp-cands)))
(prog1 (setq sexps (nreverse (delete "" sexps))
sexps (mapcar (lambda (sx) (car (read-from-string sx))) sexps))
(when (interactive-p) (message "Sexps: %S" sexps))))))
(when (and (fboundp 'cl-puthash) (not (fboundp 'puthash)))
(defalias 'puthash 'cl-puthash))
(if (fboundp 'puthash)
(defun isearchp-remove-duplicates (sequence &optional test)
"Copy of SEQUENCE with duplicate elements removed.
Optional arg TEST is the test function. If nil, test with `equal'.
See `make-hash-table' for possible values of TEST."
(setq test (or test #'equal))
(let ((htable (make-hash-table :test test)))
(loop for elt in sequence
unless (gethash elt htable)
do (puthash elt elt htable)
finally return (loop for i being the hash-values in htable collect i))))
(defun isearchp-remove-duplicates (list &optional use-eq)
"Copy of LIST with duplicate elements removed.
Test using `equal' by default, or `eq' if optional USE-EQ is non-nil."
(let ((tail list)
new)
(while tail
(unless (if use-eq (memq (car tail) new) (member (car tail) new))
(push (car tail) new))
(pop tail))
(nreverse new))))
(defun isearchp-repeat-command (command)
"Repeat COMMAND."
(let ((repeat-message-function 'ignore))
(setq last-repeatable-command command)
(repeat nil)))
(when (boundp 'isearch-filter-predicate)
(define-key isearch-mode-map "\C-t" 'isearchp-char-prop-forward)
(define-key isearch-mode-map "\C-\M-t" 'isearchp-char-prop-forward-regexp)
(defvar isearchp-filter-predicate-orig nil
"Original value of `isearch-filter-predicate'.")
(defvar isearchp-char-prop-type nil
"Last property type used for `isearchp-char-prop-*' commands.")
(defvar isearchp-char-prop-prop nil
"Last property used for `isearchp-char-prop-*' commands.")
(defvar isearchp-char-prop-values nil
"Last property values used for `isearchp-char-prop-*' commands.")
(defun isearchp-char-prop-forward (arg)
"Isearch forward for a character (overlay or text) property.
If you have not previously used an `isearch-char-prop-*' command, you
are prompted for:
* the property type (`text', `overlay', or `text and overlay')
* the property (e.g., `face', `mumamo-major-mode')
* the property values (e.g., a list of faces, for property `face')
Otherwise:
With no prefix arg, use the settings (property type, property,
property values) from the last time you invoked an
`isearch-char-prop-*' command.
With a prefix arg you are prompted for the property and property
values to use. The particular prefix arg determines the property
type to search, as follows:
* plain prefix arg (`C-u'): both overlay and text property zones
* negative prefix arg (e.g., `C--'): overlay property zones
* non-negative prefix arg (e.g., `C-9'): text property zones
By default, an actual value of the property matches the value
you specify if it is `equal'. Properties `mumamo-major-mode' and
`face' (or `font-lock-face') are exceptions.
For `mumamo-major-mode' you specify the major mode whose zones of text
you want to search. The actual property value is a list whose car is
the major mode symbol.
For properties `face' and `font-lock-face', you can pick multiple
faces, using completion (hit `RET' with empty input to finish
choosing). Text is searched that has a face property that includes
any of the faces you choose. If you choose no face (empty input at
the outset), then text with any face at all is searched.
NOTE: If you search zones of property `face', and the property values
include `font-lock' faces, then you might want to first make
sure the entire buffer has been fontified. You can do that
using command `isearchp-fontify-buffer-now'.
NOTE: This command is available during normal Isearch, on key `C-t'.
However, in order to be able to use a prefix arg with this
command from within Isearch, you must set `isearch-allow-scroll'
to non-nil. Otherwise, a prefix arg during Isearch exits
Isearch."
(interactive "P")
(isearchp-char-prop-1 'isearch-forward arg))
(defun isearchp-char-prop-backward (arg)
"Isearch backward for a character (overlay or text) property.
See `isearchp-char-prop-forward'."
(interactive "P")
(isearchp-char-prop-1 'isearch-backward arg))
(defun isearchp-char-prop-forward-regexp (arg)
"Regexp Isearch forward for a character (overlay or text) property.
NOTE: This command is available during normal Isearch, on key `C-M-t'.
However, in order to be able to use a prefix arg with this
command, you must set `isearch-allow-scroll' to non-nil.
Otherwise, a prefix arg during Isearch exits Isearch.
See `isearchp-char-prop-forward'."
(interactive "P")
(isearchp-char-prop-1 'isearch-forward-regexp arg))
(defun isearchp-char-prop-backward-regexp (arg)
"Regexp Isearch backward for a character (overlay or text) property.
See `isearchp-char-prop-backward'."
(interactive "P")
(isearchp-char-prop-1 'isearch-backward-regexp arg))
(defun isearchp-char-prop-1 (search-fn arg)
"Helper for `isearchp-char-prop-(forward|backward)(-regexp)'."
(isearch-done)
(let ((message-log-max nil))
(message "CHAR PROP %s%s" (isearchp-message-prefix nil nil isearch-nonincremental)
isearch-message))
(sit-for 1)
(setq isearch-success t
isearch-adjusted t)
(let* ((enable-recursive-minibuffers t)
(search-nonincremental-instead nil)
(type (if (or arg (not isearchp-char-prop-prop))
(if (not isearchp-char-prop-prop)
(let ((typname
(completing-read
"Type: " '(("text") ("overlay") ("text and overlay"))
nil t nil nil "text and overlay")))
(and (not (string= "text and overlay" typname)) (intern typname)))
(and (atom arg)
(if (wholenump (prefix-numeric-value arg)) 'text 'overlay)))
isearchp-char-prop-type))
(props (and (or arg (not isearchp-char-prop-prop))
(mapcar #'(lambda (prop) (list (symbol-name prop)))
(isearchp-char-properties-in-buffer
(current-buffer) (point-min) (point-max) type))))
(prop (if (or arg (not isearchp-char-prop-prop))
(intern (completing-read
(format "%s property to search: "
(if type (capitalize (symbol-name type)) "Character"))
props nil nil nil nil "face"))
isearchp-char-prop-prop))
(values (if (or arg (not isearchp-char-prop-values))
(if (memq prop '(face font-lock-face))
(isearchp-read-face-names)
(isearchp-read-sexps))
isearchp-char-prop-values)))
(setq isearchp-filter-predicate-orig isearch-filter-predicate
isearch-filter-predicate (isearchp-char-prop-filter-pred type prop values)
isearchp-char-prop-type type
isearchp-char-prop-prop prop
isearchp-char-prop-values values))
(add-hook 'isearch-mode-end-hook 'isearchp-char-prop-end)
(funcall search-fn))
(defun isearchp-char-properties-in-buffer (&optional buffer beg end type)
"List of all character properties in BUFFER between BEG and END.
Only the character properties are included, not their values.
TYPE can be `overlay', `text', or nil, meaning overlay properties,
text properties, or both, respectively."
(unless buffer (setq buffer (current-buffer)))
(let ((props ())
ovrlays curr-props)
(when (bufferp buffer)
(with-current-buffer buffer
(unless (and beg end)
(setq beg (point-min)
end (point-max)))
(when (or (not type) (eq type 'overlay))
(setq ovrlays (overlays-in beg end))
(dolist (ovrly ovrlays)
(setq curr-props (overlay-properties ovrly))
(while curr-props
(unless (memq (car curr-props) props) (push (car curr-props) props))
(setq curr-props (cddr curr-props)))))
(when (or (not type) (eq type 'text))
(while (< beg end)
(setq beg (or (next-property-change beg nil end) end)
curr-props (text-properties-at beg))
(while curr-props
(unless (memq (car curr-props) props) (push (car curr-props) props))
(setq curr-props (cddr curr-props)))))))
props))
(defun isearchp-char-prop-filter-pred (type prop values)
"Return a predicate that uses `isearchp-char-prop-matches-p'.
TYPE, PROP, and VALUES are used by that function.
The predicate is suitable as a value of `isearch-filter-predicate'."
(let ((tag (make-symbol "isearchp-char-prop-filter-pred")))
`(lambda (beg end)
(and (isearch-filter-visible beg end) (catch ',tag
(while (< beg end)
(unless (isearchp-char-prop-matches-p
',type ',prop ',values
(isearchp-char-prop-default-match-fn
',prop)
beg)
(throw ',tag nil))
(setq beg (1+ beg)))
t)))))
(defun isearchp-char-prop-matches-p (type property values match-fn position)
"Return non-nil if POSITION has PROPERTY with a value matching VALUES.
TYPE is `overlay', `text', or nil, and specifies the type of character
property - nil means look for both overlay and text properties.
Find text with a PROPERTY value that overlaps with VALUES: If the
value of PROPERTY is an atom, then it must be a member of VALUES. If
it is a list, then at least one list element must be a member of
VALUES.
MATCH-FN is a binary predicate that is applied to each item of VALUES
and a zone of text with property PROP. If it returns non-nil then the
zone is a search hit."
(let* ((ovlyval (and (or (not type) (eq type 'overlay))
(get-char-property position property)))
(textval (and (or (not type) (eq type 'text))
(get-text-property position property))))
(or (and ovlyval (isearchp-some values ovlyval match-fn))
(and textval (isearchp-some values textval match-fn)))))
(defun isearchp-some (list arg2 predicate)
"Apply binary PREDICATE successively to an item of LIST and ARG2.
Return the first non-nil value returned by PREDICATE, or nil if none.
PREDICATE must be a function with two required arguments."
(let ((result nil))
(catch 'isearchp-some
(dolist (arg1 list)
(when (setq result (funcall predicate arg1 arg2)) (throw 'isearchp-some result))))
result))
(defun isearchp-char-prop-default-match-fn (prop)
"Return the default match function for text or overlay property PROP.
Properties `face' and `mumamo-major-mode' are handled specially.
For other properties the values are matched using `equal'."
(case prop
((face font-lock-face) (lambda (val rprop)
(if (consp rprop)
(condition-case nil
(member val rprop)
(error nil))
(eq val rprop))))
((mumamo-major-mode) (lambda (val rprop) (equal val (car rprop))))
(t #'equal)))
(defun isearchp-char-prop-end ()
"End Isearch for a character property."
(setq isearch-filter-predicate isearchp-filter-predicate-orig)
(remove-hook 'isearch-mode-end-hook 'isearchp-char-prop-end))
(defun isearchp-put-prop-on-region (property value beg end)
"Add text PROPERTY with VALUE to the region from BEG to END.
If you have already used any of the commands `isearchp-char-prop-*'
and you do not use a prefix argument, then use the property and (the
first of) its values that you last specified for such searching.
Otherwise, you are prompted for the property and its value.
If the property is not `face' or `font-lock-face', then you enter a
sexp, which is read as the Lisp value to use. E.g., if the property
is `mumamo-major-mode' then you might enter `(emacs-lisp-mode)' as the
value.
If the property is `face' or `font-lock-face' then you can specify
more than one face - their union is used as the property value. If
you specify none (empty input immediately) then *all* faces are
*removed* from the region."
(interactive
(if (and (not current-prefix-arg) isearchp-char-prop-prop (car isearchp-char-prop-values))
(list isearchp-char-prop-prop isearchp-char-prop-values (region-beginning) (region-end))
(let* ((props (and (or current-prefix-arg (not isearchp-char-prop-prop))
(mapcar #'(lambda (prop) (list (symbol-name prop)))
(isearchp-char-properties-in-buffer
(current-buffer) (point-min) (point-max) 'text))))
(prop (intern (completing-read "Text property: " props nil nil nil nil "face")))
(vals (if (memq prop '(face font-lock-face))
(isearchp-read-face-names 'EMPTY-MEANS-NONE-P)
(isearchp-read-sexps 'ONLY-ONE-P))))
(list prop vals (region-beginning) (region-end)))))
(add-text-properties beg end (list property value)))
)
(defadvice isearch-forward (before isearch+-doc activate)
"
Isearch Plus
============
Commands
--------
Type \\<isearch-mode-map>\\[isearchp-char-prop-forward] to search for a character (overlay or text) property
Type \\[isearchp-char-prop-forward-regexp] to regexp-search for a character (overlay or text) property
Type \\[isearchp-cycle-mismatch-removal] to cycle option `isearchp-drop-mismatch'
Type \\[isearch-insert-char-by-name] to add a Unicode char to search string by Unicode name
Type \\[isearchp-open-recursive-edit] to invoke Emacs command loop recursively
Type \\[isearchp-toggle-set-region] to toggle setting region around search target
Type \\[isearchp-toggle-invisible] to toggle invisible-text sensitivity (`search-invisible')
Type \\[isearchp-toggle-regexp-quote-yank] to toggle quoting (escaping) of regexp special characters
Type \\[isearchp-retrieve-last-quit-search] to insert successful search string from when you hit `C-g'
Type \\[isearchp-yank-symbol-or-char] to yank a symbol or char from buffer onto search string
Type \\[isearchp-yank-sexp-symbol-or-char] to yank sexp, symbol, or char from buffer onto search string
Type \\[isearchp-put-prop-on-region] to add a text property to region
Type \\[isearchp-set-region-around-search-target] to select search hit
Options
-------
`isearchp-drop-mismatch' - how to handle input after a search mismatch
`isearchp-initiate-edit-commands' - keys that edit instead of exiting
`isearchp-mouse-2-flag' - `mouse-2' anywhere yanks the selection?
`isearchp-regexp-quote-yank-flag' - regexp-quote yanked text?
`isearchp-set-region-flag' - select last search target?")
(define-key isearch-mode-map [mouse-2] 'isearch-mouse-2)
(define-key isearch-mode-map [down-mouse-2] 'ignore)
(define-key isearch-mode-map [switch-frame] 'ignore)
(define-key isearch-mode-map [(control ?+)] 'isearchp-toggle-invisible)
(define-key isearch-mode-map [(control ?`)] 'isearchp-toggle-regexp-quote-yank)
(define-key isearch-mode-map [(control ? )] 'isearchp-toggle-set-region)
(define-key isearch-mode-map "\C-h" 'isearch-mode-help)
(define-key isearch-mode-map "\M-c" 'isearch-toggle-case-fold)
(define-key isearch-mode-map "\M-e" 'isearch-edit-string)
(define-key isearch-mode-map "\M-g" 'isearchp-retrieve-last-quit-search)
(define-key isearch-mode-map "\M-k" 'isearchp-cycle-mismatch-removal)
(define-key isearch-mode-map "\M-r" 'isearch-toggle-regexp)
(when (< emacs-major-version 23)
(define-key isearch-mode-map "\M-sw" 'isearch-toggle-word))
(define-key isearch-mode-map "\M-w" 'isearchp-kill-ring-save)
(when (fboundp 'isearch-yank-internal)
(define-key isearch-mode-map "\C-c" 'isearchp-yank-char)
(define-key isearch-mode-map "\C-_" 'isearchp-yank-symbol-or-char)
(define-key isearch-mode-map [(control ?\()] 'isearchp-yank-sexp-symbol-or-char))
(when (and (fboundp 'goto-longest-line) window-system)
(define-key isearch-mode-map [(control end)] 'goto-longest-line))
(define-key isearch-mode-map [next] 'isearch-repeat-forward)
(define-key isearch-mode-map [prior] 'isearch-repeat-backward)
(when (and (eq system-type 'windows-nt)
(not (lookup-key isearch-mode-map [C-M-tab])))
(define-key isearch-mode-map [C-M-tab] 'isearch-complete))
(when (> emacs-major-version 21)
(define-key isearch-mode-map "\C-x" nil)
(define-key isearch-mode-map "\C-xo" 'isearchp-open-recursive-edit)
(when (and (> emacs-major-version 22)
(or (< emacs-major-version 24) (and (= emacs-major-version 24) (< emacs-minor-version 3))))
(define-key isearch-mode-map "\C-x8" nil)
(define-key isearch-mode-map "\C-x8\r" 'isearch-insert-char-by-name)))
(define-key isearch-mode-map "\C-y" nil)
(when (fboundp 'isearch-yank-internal)
(define-key isearch-mode-map (kbd "C-y C-c") 'isearchp-yank-char)
(define-key isearch-mode-map (kbd "C-y C-e") 'isearchp-yank-line)
(define-key isearch-mode-map (kbd "C-y C-w") 'isearchp-yank-word-or-char)
(define-key isearch-mode-map (kbd "C-y C-_") 'isearchp-yank-symbol-or-char)
(define-key isearch-mode-map (kbd "C-y C-(") 'isearchp-yank-sexp-symbol-or-char))
(eval-after-load "second-sel"
'(progn
(define-key isearch-mode-map (kbd "C-y C-2") 'isearch-yank-secondary)
(define-key isearch-mode-map (kbd "C-M-y") 'isearch-yank-secondary)))
(define-key isearch-mode-map "\C-y\C-y" 'isearch-yank-kill)
(define-key isearch-mode-map "\C-y\M-g" 'isearchp-retrieve-last-quit-search)
(when (fboundp 'isearch-yank-pop)
(define-key isearch-mode-map "\C-y\M-y" 'isearch-yank-pop))
(when (and (eq system-type 'windows-nt)
(not (lookup-key minibuffer-local-isearch-map [C-M-tab])))
(define-key minibuffer-local-isearch-map [C-M-tab] 'isearch-complete-edit))
(when (> emacs-major-version 22)
(define-key minibuffer-local-isearch-map "\C-x8\r" 'insert-char))
(defun isearchp-set-region ()
"Set the region around the search target, if `isearchp-set-region-flag'.
This is used only for Transient Mark mode."
(when (and isearchp-set-region-flag transient-mark-mode)
(push-mark isearch-other-end t 'activate)))
(add-hook 'isearch-mode-end-hook 'isearchp-set-region)
(unless (boundp 'isearch-update-post-hook)
(defadvice isearch-update (after run-isearch-update-post-hook activate)
"Run `isearch-update-post-hook' at the end."
(run-hooks 'isearch-update-post-hook)))
(defun isearchp-highlight-lighter ()
"Update minor-mode mode-line lighter to reflect case sensitivity."
(let ((case-fold-search isearch-case-fold-search))
(when (and (eq case-fold-search t) search-upper-case)
(setq case-fold-search (isearch-no-upper-case-p isearch-string isearch-regexp)))
(setq minor-mode-alist (delete '(isearch-mode isearch-mode) minor-mode-alist)
minor-mode-alist (delete '(isearch-mode " ISEARCH") minor-mode-alist)
minor-mode-alist (delete '(isearch-mode " Isearch") minor-mode-alist))
(let ((lighter (if case-fold-search " ISEARCH" " Isearch")))
(add-to-list
'minor-mode-alist
`(isearch-mode ,(if (and isearch-wrapped (facep 'isearchp-wrapped))
(propertize lighter 'face 'isearchp-wrapped)
lighter)))))
(condition-case nil
(if (fboundp 'redisplay) (redisplay t) (force-mode-line-update t))
(error nil)))
(add-hook 'isearch-update-post-hook 'isearchp-highlight-lighter)
(provide 'isearch+)