X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/d0cfb71f2e0a5a4cd231b3139f013a1908bfaefa..e26aac1f938d517a0c5826ac89e7be3649f02b1b:/lisp/isearch.el diff --git a/lisp/isearch.el b/lisp/isearch.el index b13881b208..e82627616c 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -47,7 +47,7 @@ ;; 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. +;; exits and searches in the last search direction. ;; Exiting immediately from isearch uses isearch-edit-string instead ;; of nonincremental-search, if search-nonincremental-instead is non-nil. @@ -176,7 +176,7 @@ is non-nil if the user quits the search.") (defvar isearch-message-function nil "Function to call to display the search prompt. -If nil, use `isearch-message'.") +If nil, use function `isearch-message'.") (defvar isearch-wrap-function nil "Function to call to wrap the search when search is failed. @@ -187,12 +187,21 @@ or to the end of the buffer for a backward search.") "Function to save a function restoring the mode-specific Isearch state to the search status stack.") -(defvar isearch-filter-predicate 'isearch-filter-visible - "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.") +(defvar isearch-filter-predicates nil + "Predicates that filter the search hits that would normally be available. +Search hits that dissatisfy the list of predicates are skipped. +Each function in this list has two arguments: the positions of +start and end of text matched by the search. +The search loop uses `run-hook-with-args-until-failure' to call +each predicate in order, and when one of the predicates returns nil, +skips this match and continues searching for the next match. +When the list of predicates is empty, `run-hook-with-args-until-failure' +returns non-nil that means that the found match is accepted. +The property `isearch-message-prefix' put on the predicate's symbol +specifies the prefix string displyed in the search message.") +(define-obsolete-variable-alias 'isearch-filter-predicate + 'isearch-filter-predicates + "24.4") ;; Search ring. @@ -505,6 +514,7 @@ This is like `describe-bindings', but displays only Isearch keys." (define-key map "\M-e" 'isearch-edit-string) (define-key map "\M-sc" 'isearch-toggle-case-fold) + (define-key map "\M-si" 'isearch-toggle-invisible) (define-key map "\M-sr" 'isearch-toggle-regexp) (define-key map "\M-sw" 'isearch-toggle-word) (define-key map "\M-s_" 'isearch-toggle-symbol) @@ -515,12 +525,12 @@ This is like `describe-bindings', but displays only Isearch keys." (define-key map "\M-so" 'isearch-occur) (define-key map "\M-shr" 'isearch-highlight-regexp) - ;; The key translations defined in the C-x 8 prefix should insert - ;; characters into the search string. See iso-transl.el. + ;; The key translations defined in the C-x 8 prefix should add + ;; characters to the search string. See iso-transl.el. (define-key map "\C-x" nil) (define-key map [?\C-x t] 'isearch-other-control-char) (define-key map "\C-x8" nil) - (define-key map "\C-x8\r" 'isearch-insert-char-by-name) + (define-key map "\C-x8\r" 'isearch-char-by-name) map) "Keymap for `isearch-mode'.") @@ -528,7 +538,7 @@ This is like `describe-bindings', but displays only Isearch keys." (defvar minibuffer-local-isearch-map (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) - (define-key map "\r" 'isearch-nonincremental-exit-minibuffer) + (define-key map "\r" 'exit-minibuffer) (define-key map "\M-\t" 'isearch-complete-edit) (define-key map "\C-s" 'isearch-forward-exit-minibuffer) (define-key map "\C-r" 'isearch-reverse-exit-minibuffer) @@ -593,6 +603,11 @@ Each set is a vector of the form: ;; case in the search string is ignored. (defvar isearch-case-fold-search nil) +;; search-invisible while searching. +;; either nil, t, or 'open. 'open means the same as t except that +;; opens hidden overlays. +(defvar isearch-invisible search-invisible) + (defvar isearch-last-case-fold-search nil) ;; Used to save default value while isearch is active @@ -679,6 +694,8 @@ Type \\[isearch-yank-kill] to yank the last string of killed text. Type \\[isearch-yank-pop] to replace string just yanked into search prompt with string killed before it. Type \\[isearch-quote-char] to quote control character to search for it. +Type \\[isearch-char-by-name] to add a character to search by Unicode name,\ + with completion. \\[isearch-abort] while searching or when search has failed cancels input\ back to what has been found successfully. @@ -689,6 +706,7 @@ If you try to exit with the search string still empty, it invokes nonincremental search. Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity. +Type \\[isearch-toggle-invisible] to toggle search in invisible text. Type \\[isearch-toggle-regexp] to toggle regular-expression mode. Type \\[isearch-toggle-word] to toggle word mode. Type \\[isearch-toggle-symbol] to toggle symbol mode. @@ -735,8 +753,9 @@ Other control and meta characters terminate the search and are then executed normally (depending on `search-exit-option'). Likewise for function keys and mouse button events. -If this function is called non-interactively, it does not return to -the calling function until the search is done." +If this function is called non-interactively with a nil NO-RECURSIVE-EDIT, +it does not return to the calling function until the search is done. +See the function `isearch-mode' for more information." (interactive "P\np") (isearch-mode t (not (null regexp-p)) nil (not no-recursive-edit))) @@ -799,7 +818,23 @@ as a regexp. See the command `isearch-forward' for more information." (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." +It is called by the function `isearch-forward' and other related functions. + +The non-nil arg FORWARD means searching in the forward direction. + +The non-nil arg REGEXP does an incremental regular expression search. + +The arg OP-FUN is a function to be called after each input character +is processed. (It is not called after characters that exit the search.) + +When the arg RECURSIVE-EDIT is non-nil, this function behaves modally and +does not return to the calling function until the search is completed. +To behave this way it enters a recursive-edit and exits it when done +isearching. + +The arg WORD, if t, does incremental search for a sequence of words, +ignoring punctuation. If the value is a function, it is called to +convert the search string to a regexp used by regexp search functions." ;; Initialize global vars. (setq isearch-forward forward @@ -808,6 +843,7 @@ It is called by the function `isearch-forward' and other related functions." isearch-op-fun op-fun isearch-last-case-fold-search isearch-case-fold-search isearch-case-fold-search case-fold-search + isearch-invisible search-invisible isearch-string "" isearch-message "" isearch-cmds nil @@ -1101,13 +1137,14 @@ nonincremental search instead via `isearch-edit-string'." (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'." +If MSG is non-nil, use variable `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--state-success (car cmds))) - (isearch--state-error (car cmds))) + (while (and cmds + (or (not (isearch--state-success (car cmds))) + (isearch--state-error (car cmds)))) (pop cmds)) (setq succ-msg (and cmds (if msg (isearch--state-message (car cmds)) (isearch--state-string (car cmds))))) @@ -1255,7 +1292,6 @@ You can update the global isearch variables by setting new values to The following additional command keys are active while editing. \\ \\[exit-minibuffer] to resume incremental searching with the edited string. -\\[isearch-nonincremental-exit-minibuffer] to do one nonincremental search. \\[isearch-forward-exit-minibuffer] to resume isearching forward. \\[isearch-reverse-exit-minibuffer] to resume isearching backward. \\[isearch-complete-edit] to complete the search string using the search ring." @@ -1289,13 +1325,18 @@ The following additional command keys are active while editing. (interactive) (setq isearch-nonincremental t) (exit-minibuffer)) +;; Changing the value of `isearch-nonincremental' has no effect here, +;; because `isearch-edit-string' ignores this change. Thus marked as obsolete. +(make-obsolete 'isearch-nonincremental-exit-minibuffer 'exit-minibuffer "24.4") (defun isearch-forward-exit-minibuffer () + "Resume isearching forward from the minibuffer that edits the search string." (interactive) (setq isearch-new-forward t) (exit-minibuffer)) (defun isearch-reverse-exit-minibuffer () + "Resume isearching backward from the minibuffer that edits the search string." (interactive) (setq isearch-new-forward nil) (exit-minibuffer)) @@ -1441,7 +1482,8 @@ value of the variable `isearch-regexp-lax-whitespace'." (isearch-update)) (defun isearch-toggle-case-fold () - "Toggle case folding in searching on or off." + "Toggle case folding in searching on or off. +Toggles the value of the variable `isearch-case-fold-search'." (interactive) (setq isearch-case-fold-search (if isearch-case-fold-search nil 'yes)) @@ -1454,6 +1496,23 @@ value of the variable `isearch-regexp-lax-whitespace'." (sit-for 1) (isearch-update)) +(defun isearch-toggle-invisible () + "Toggle searching in invisible text on or off. +Toggles the variable `isearch-invisible' between values +nil and a non-nil value of the option `search-invisible' +\(or `open' if `search-invisible' is nil)." + (interactive) + (setq isearch-invisible + (if isearch-invisible nil (or search-invisible 'open))) + (let ((message-log-max nil)) + (message "%s%s [match %svisible text]" + (isearch-message-prefix nil isearch-nonincremental) + isearch-message + (if isearch-invisible "in" ""))) + (setq isearch-success t isearch-adjusted t) + (sit-for 1) + (isearch-update)) + ;; Word search @@ -1589,6 +1648,7 @@ way to run word replacements from Isearch is `M-s w ... M-%'." ;; set `search-upper-case' to nil to not call ;; `isearch-no-upper-case-p' in `perform-replace' (search-upper-case nil) + (search-invisible isearch-invisible) (replace-lax-whitespace isearch-lax-whitespace) (replace-regexp-lax-whitespace @@ -1848,11 +1908,12 @@ Subword is used when `subword-mode' is activated. " (lambda () (let ((inhibit-field-text-motion t)) (line-end-position (if (eolp) 2 1)))))) -(defun isearch-insert-char-by-name () - "Read a character by its Unicode name and insert it into search string." +(defun isearch-char-by-name () + "Read a character by its Unicode name and add it to the search string. +Completion is available like in `read-char-by-name' used by `insert-char'." (interactive) (with-isearch-suspended - (let ((char (read-char-by-name "Insert character (Unicode name or hex): "))) + (let ((char (read-char-by-name "Add character to search (Unicode name or hex): "))) (when char (setq isearch-new-string (concat isearch-string (string char)) isearch-new-message (concat isearch-message @@ -2466,6 +2527,13 @@ If there is no completion possible, say so and continue searching." (< (point) isearch-opoint))) "over") (if isearch-wrapped "wrapped ") + (mapconcat (lambda (s) + (and (symbolp s) + (get s 'isearch-message-prefix))) + (if (consp isearch-filter-predicates) + isearch-filter-predicates + (list isearch-filter-predicates)) + "") (if isearch-word (or (and (symbolp isearch-word) (get isearch-word 'isearch-message-prefix)) @@ -2520,6 +2588,7 @@ Can be changed via `isearch-search-fun-function' for special needs." ;; the user adds and removes characters in the search string ;; (or when using nonincremental word isearch) (let ((lax (not (or isearch-nonincremental + (null (car isearch-cmds)) (eq (length isearch-string) (length (isearch--state-string (car isearch-cmds)))))))) @@ -2596,12 +2665,10 @@ update the match data, and return point." (setq isearch-case-fold-search (isearch-no-upper-case-p isearch-string isearch-regexp))) (condition-case lossage - (let ((inhibit-point-motion-hooks - ;; FIXME: equality comparisons on functions is asking for trouble. - (and (eq isearch-filter-predicate 'isearch-filter-visible) - search-invisible)) + (let ((inhibit-point-motion-hooks isearch-invisible) (inhibit-quit nil) (case-fold-search isearch-case-fold-search) + (search-invisible isearch-invisible) (retry t)) (setq isearch-error nil) (while retry @@ -2612,8 +2679,15 @@ update the match data, and return point." (if (or (not isearch-success) (bobp) (eobp) (= (match-beginning 0) (match-end 0)) - (funcall isearch-filter-predicate - (match-beginning 0) (match-end 0))) + ;; When one of filter predicates returns nil, + ;; retry the search. Otherwise, act according + ;; to search-invisible (open overlays, etc.) + (and (run-hook-with-args-until-failure + 'isearch-filter-predicates + (match-beginning 0) (match-end 0)) + (or (eq search-invisible t) + (not (isearch-range-invisible + (match-beginning 0) (match-end 0)))))) (setq retry nil))) (setq isearch-just-started nil) (if isearch-success @@ -2790,6 +2864,7 @@ determined by `isearch-range-invisible' unless invisible text can be searched too when `search-invisible' is t." (or (eq search-invisible t) (not (isearch-range-invisible beg end)))) +(make-obsolete 'isearch-filter-visible 'isearch-invisible "24.4") ;; General utilities @@ -2960,8 +3035,15 @@ by other Emacs features." (setq isearch-lazy-highlight-window (selected-window) isearch-lazy-highlight-window-start (window-start) isearch-lazy-highlight-window-end (window-end) - isearch-lazy-highlight-start (point) - isearch-lazy-highlight-end (point) + ;; Start lazy-highlighting at the beginning of the found + ;; match (`isearch-other-end'). If no match, use point. + ;; One of the next two variables (depending on search direction) + ;; is used to define the starting position of lazy-highlighting + ;; and also to remember the current position of point between + ;; calls of `isearch-lazy-highlight-update', and another variable + ;; is used to define where the wrapped search must stop. + isearch-lazy-highlight-start (or isearch-other-end (point)) + isearch-lazy-highlight-end (or isearch-other-end (point)) isearch-lazy-highlight-wrapped nil isearch-lazy-highlight-last-string isearch-string isearch-lazy-highlight-case-fold-search isearch-case-fold-search @@ -3008,8 +3090,11 @@ Attempt to do the search exactly the way the pending Isearch would." (if (or (not success) (= (point) bound) ; like (bobp) (eobp) in `isearch-search'. (= (match-beginning 0) (match-end 0)) - (funcall isearch-filter-predicate - (match-beginning 0) (match-end 0))) + (and (run-hook-with-args-until-failure + 'isearch-filter-predicates + (match-beginning 0) (match-end 0)) + (not (isearch-range-invisible + (match-beginning 0) (match-end 0))))) (setq retry nil))) success) (error nil))) @@ -3059,6 +3144,9 @@ Attempt to do the search exactly the way the pending Isearch would." (overlay-put ov 'priority 1000) (overlay-put ov 'face lazy-highlight-face) (overlay-put ov 'window (selected-window)))) + ;; Remember the current position of point for + ;; the next call of `isearch-lazy-highlight-update' + ;; when `lazy-highlight-max-at-a-time' is too small. (if isearch-lazy-highlight-forward (setq isearch-lazy-highlight-end (point)) (setq isearch-lazy-highlight-start (point)))))