=== modified file 'lisp/isearch.el' --- lisp/isearch.el 2011-07-04 12:15:16 +0000 +++ lisp/isearch.el 2011-07-07 14:17:08 +0000 @@ -57,6 +57,9 @@ ;;; Code: +(eval-when-compile + (require 'cl)) + ;; Some additional options and constants. @@ -74,6 +77,11 @@ :type 'boolean :group 'isearch) +(defcustom search-one-ring nil + "Non-nil means to use one ring for both normal and regular expression searches." + :type 'boolean + :group 'isearch) + (defcustom search-slow-window-lines 1 "Number of lines in slow search display windows. These are the short windows used during incremental search on slow terminals. @@ -399,6 +407,18 @@ (defalias 'isearch-mode-help 'isearch-describe-mode) +(defun* isearch-get-ring (&optional (regexp isearch-regexp)) + "Return the symbol holding the appropriate search ring to use." + (if (and regexp (not search-one-ring)) + 'regexp-search-ring + 'search-ring)) + +(defun* isearch-get-yank-pointer (&optional (regexp isearch-regexp)) + "Return the symbol holding the appropriate search ring yank pointer." + (if (and regexp (not search-one-ring)) + 'regexp-search-ring-yank-pointer + 'search-ring-update)) + ;; Define isearch-mode keymap. @@ -502,7 +522,15 @@ (define-key map "\M-e" 'isearch-edit-string) (define-key map "\M-sr" 'isearch-toggle-regexp) - (define-key map "\M-sw" 'isearch-toggle-word) + (define-key map "\M-sw" 'isearch-cycle-word-mode) + + ;; Shortcuts for useful programming language modes. + (define-key map "\M-_" 'isearch-toggle-identifier-mode) + (define-key map "\M-#" 'isearch-toggle-match-text) + + (define-key map "\M-sc" 'isearch-toggle-match-comments) + (define-key map "\M-ss" 'isearch-toggle-match-strings) + (define-key map "\M-st" 'isearch-toggle-match-text) (define-key map [?\M-%] 'isearch-query-replace) (define-key map [?\C-\M-%] 'isearch-query-replace-regexp) @@ -530,14 +558,14 @@ (defvar isearch-forward nil) ; Searching in the forward direction. (defvar isearch-regexp nil) ; Searching for a regexp. -(defvar isearch-word nil) ; Searching for words. -(defvar isearch-hidden nil) ; Non-nil if the string exists but is invisible. +(defvar isearch-word nil) ; Searching for words or symbols. +(defvar isearch-context-filter nil) ; Where to find matches. +(defvar isearch-hidden nil) ; Non-nil if the string exists but is invisible. (defvar isearch-cmds nil "Stack of search status sets. -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]") +Each set is a plist containg isearch variables to restore and +miscellaneous other information.") (defvar isearch-string "") ; The current search string. (defvar isearch-message "") ; text-char-description version of isearch-string @@ -558,8 +586,6 @@ ;; case in the search string is ignored. (defvar isearch-case-fold-search nil) -(defvar isearch-last-case-fold-search nil) - ;; Used to save default value while isearch is active (defvar isearch-original-minibuffer-message-timeout nil) @@ -651,7 +677,7 @@ Type \\[isearch-toggle-case-fold] to toggle search case-sensitivity. Type \\[isearch-toggle-regexp] to toggle regular-expression mode. -Type \\[isearch-toggle-word] to toggle word mode. +Type \\[isearch-cycle-word-mode] to cycle between normal, word, and symbol mode. Type \\[isearch-edit-string] to edit the search string in the minibuffer. Also supported is a search ring of the previous 16 search strings. @@ -660,6 +686,11 @@ ring. Type \\[isearch-complete] to complete the search string using the search ring. +Type \\[isearch-toggle-match-comments] to toggle matching inside comments. +Type \\[isearch-toggle-match-strings] to toggle matching inside strings. +Type \\[isearch-toggle-match-text] to toggle matching outside comments\ + and strings. + 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'\ @@ -746,7 +777,10 @@ ;; "List of commands for which isearch-mode does not recursive-edit.") -(defun isearch-mode (forward &optional regexp op-fun recursive-edit word-p) +(defun* isearch-mode (forward &optional regexp op-fun recursive-edit word-p + &key (regexp regexp) (op-fun op-fun) + (recursive-edit recursive-edit) (word-p word-p) + context-filter) "Start Isearch minor mode. It is called by the function `isearch-forward' and other related functions." @@ -754,8 +788,8 @@ (setq isearch-forward forward isearch-regexp regexp isearch-word word-p + isearch-context-filter context-filter 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 "" @@ -834,7 +868,8 @@ ;; Some high level utilities. Others below. (defun isearch-update () - ;; Called after each command to update the display. + ;; Called after each command to update the display and save + ;; isearch settings to the top of the stack. (if (and (null unread-command-events) (null executing-kbd-macro)) (progn @@ -875,6 +910,8 @@ (setq ;; quit-flag nil not for isearch-mode isearch-adjusted nil isearch-yank-flag nil) + (pop isearch-cmds) + (isearch-push-state) (when isearch-lazy-highlight (isearch-lazy-highlight-new-loop)) ;; We must prevent the point moving to the end of composition when a @@ -890,10 +927,12 @@ NOPUSH is t and EDIT is t." (if isearch-resume-in-command-history - (let ((command `(isearch-resume ,isearch-string ,isearch-regexp - ,isearch-word ,isearch-forward - ,isearch-message - ',isearch-case-fold-search))) + (let ((command + `(isearch-resume ,isearch-string ,isearch-regexp + ,isearch-word ,isearch-forward + ,isearch-message + ',isearch-case-fold-search + :context-filter ',isearch-context-filter))) (unless (equal (car command-history) command) (setq command-history (cons command command-history))))) @@ -959,10 +998,28 @@ (defun isearch-update-ring (string &optional regexp) "Add STRING to the beginning of the search ring. REGEXP if non-nil says use the regexp search ring." - (add-to-history - (if regexp 'regexp-search-ring 'search-ring) - string - (if regexp regexp-search-ring-max search-ring-max))) + (let ((ring (isearch-get-ring regexp))) + (unless (zerop (length string)) + (setq string (copy-sequence string)) + (set-text-properties + 0 (length string) + (list 'isearch-saved-state + (loop for var in isearch-persistent-state-variables + collect (cons var (symbol-value var)))) + string) + (unless (and (symbol-value ring) + (equal string (car (symbol-value ring))) + (equal (isearch-saved-state-from-string string) + (isearch-saved-state-from-string + (car (symbol-value ring))))) + (let (history-delete-duplicates) + (add-to-history + ring + string + (if (and regexp (not search-one-ring)) + regexp-search-ring-max + search-ring-max) + t)))))) ;; Switching buffers should first terminate isearch-mode. ;; ;; For Emacs 19, the frame switch event is handled. @@ -976,74 +1033,64 @@ ;; The search status structure and stack. -(defsubst isearch-string-state (frame) - "Return the search string in FRAME." - (aref frame 0)) -(defsubst isearch-message-state (frame) - "Return the search string to display to the user in FRAME." - (aref frame 1)) -(defsubst isearch-point-state (frame) - "Return the point in FRAME." - (aref frame 2)) -(defsubst isearch-success-state (frame) - "Return the success flag in FRAME." - (aref frame 3)) -(defsubst isearch-forward-state (frame) - "Return the searching-forward flag in FRAME." - (aref frame 4)) -(defsubst isearch-other-end-state (frame) - "Return the other end of the match in FRAME." - (aref frame 5)) -(defsubst isearch-word-state (frame) - "Return the search-by-word flag in FRAME." - (aref frame 6)) -(defsubst isearch-error-state (frame) - "Return the regexp error message in FRAME, or nil if its regexp is valid." - (aref frame 7)) -(defsubst isearch-wrapped-state (frame) - "Return the search-wrapped flag in FRAME." - (aref frame 8)) -(defsubst isearch-barrier-state (frame) - "Return the barrier value in FRAME." - (aref frame 9)) -(defsubst isearch-case-fold-search-state (frame) - "Return the case-folding flag in FRAME." - (aref frame 10)) -(defsubst isearch-pop-fun-state (frame) - "Return the function restoring the mode-specific Isearch state in FRAME." - (aref frame 11)) +(eval-and-compile + (defconst isearch-persistent-state-variables + '(isearch-word + isearch-context-filter + isearch-case-fold-search + isearch-regexp) + "List of isearch variables saved between searches.") + + (defconst isearch-state-variables + (append + isearch-persistent-state-variables + '(isearch-string + isearch-message + isearch-success + isearch-forward + isearch-other-end + isearch-word + isearch-error + isearch-wrapped + isearch-barrier + isearch-context-filter + isearch-case-fold-search)) + "List of isearch variables saved during searches.")) + +(eval-when-compile + (loop for var in (list* + 'isearch-pop-fun + 'isearch-point + isearch-state-variables) + for accessor = (intern (format "%s-state" var)) + do (eval + `(defun ,accessor (cmd) + (cdr (assq ',var cmd)))))) (defun isearch-top-state () - (let ((cmd (car isearch-cmds))) - (setq isearch-string (isearch-string-state cmd) - isearch-message (isearch-message-state cmd) - isearch-success (isearch-success-state cmd) - isearch-forward (isearch-forward-state cmd) - isearch-other-end (isearch-other-end-state cmd) - isearch-word (isearch-word-state cmd) - isearch-error (isearch-error-state cmd) - isearch-wrapped (isearch-wrapped-state cmd) - isearch-barrier (isearch-barrier-state cmd) - isearch-case-fold-search (isearch-case-fold-search-state cmd)) - (if (functionp (isearch-pop-fun-state cmd)) - (funcall (isearch-pop-fun-state cmd) cmd)) - (goto-char (isearch-point-state cmd)))) + (loop for (var . value) in (car isearch-cmds) + do (cond ((memq var isearch-state-variables) + (set var value)) + ((eq var 'isearch-point) + (goto-char value)) + ((and (eq var 'isearch-pop-fun) + (functionp value)) + (funcall value (car isearch-cmds)))))) + +(defun isearch-push-state () + (push (nreverse + (list* + (cons 'isearch-pop-fun (if isearch-push-state-function + (funcall isearch-push-state-function))) + (cons 'isearch-point (point)) + (loop for var in isearch-state-variables + collect (cons var (symbol-value var))))) + isearch-cmds)) (defun isearch-pop-state () - (setq isearch-cmds (cdr isearch-cmds)) + (pop isearch-cmds) (isearch-top-state)) -(defun isearch-push-state () - (setq isearch-cmds - (cons (vector isearch-string isearch-message (point) - isearch-success isearch-forward isearch-other-end - isearch-word - isearch-error isearch-wrapped isearch-barrier - isearch-case-fold-search - (if isearch-push-state-function - (funcall isearch-push-state-function))) - isearch-cmds))) - ;; Commands active while inside of the isearch minor mode. @@ -1110,6 +1157,7 @@ (isearch-new-word isearch-word) (isearch-regexp isearch-regexp) + (isearch-context-filter isearch-context-filter) (isearch-op-fun isearch-op-fun) (isearch-cmds isearch-cmds) (isearch-success isearch-success) @@ -1150,20 +1198,21 @@ (setq old-point (point) old-other-end isearch-other-end) (unwind-protect - (let* ((message-log-max nil) + (let* (message-log-max + history-add-new-input ; we'll add to history manually + (minibuffer-allow-text-properties t) ;; Binding minibuffer-history-symbol to nil is a work-around ;; for some incompatibility with gmhist. - (minibuffer-history-symbol)) + minibuffer-history-symbol + (ring-name (isearch-get-ring)) + (yank-pointer-name (isearch-get-yank-pointer))) (setq isearch-new-string (read-from-minibuffer (isearch-message-prefix nil nil isearch-nonincremental) (cons isearch-string (1+ (isearch-fail-pos))) 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)))) + (cons ring-name + (1+ (or (symbol-value yank-pointer-name) -1))) nil t) isearch-new-message (mapconcat 'isearch-text-char-description @@ -1181,7 +1230,9 @@ isearch-regexp isearch-op-fun nil - isearch-word) + isearch-word + :context-filter isearch-context-filter + ) ;; Copy new local values to isearch globals (setq isearch-string isearch-new-string @@ -1191,11 +1242,8 @@ ;; Empty isearch-string means use default. (if (= 0 (length isearch-string)) - (setq isearch-string (or (car (if isearch-regexp - regexp-search-ring - search-ring)) - "") - + (setq isearch-string (or (car (symbol-value (isearch-get-ring))) + "") isearch-message (mapconcat 'isearch-text-char-description isearch-string "")) @@ -1204,6 +1252,10 @@ ;; Only the string actually used should be saved. )) + ;; Update isearch variables from the supplied string in case + ;; it came from history. + (isearch-update-state-from-string) + ;; This used to push the state as of before this C-s, but it adds ;; an inconsistent state where part of variables are from the ;; previous search (e.g. `isearch-success'), and part of variables @@ -1213,7 +1265,7 @@ ;; Reinvoke the pending search. (isearch-search) (isearch-push-state) ; this pushes the correct state - (isearch-update) + (isearch-update) (if isearch-nonincremental (progn ;; (sit-for 1) ;; needed if isearch-done does: (message "") @@ -1274,22 +1326,40 @@ (isearch-pop-state)) (isearch-update))) +(put 'isearch-saved-state 'front-sticky t) + +(defun isearch-saved-state-from-string (str) + (or (get-text-property 0 'isearch-saved-state str) + (get-text-property (next-property-change 0 str (1- (length str))) + 'isearch-saved-state str))) + +(defun isearch-update-state-from-string () + "Update isearch state variables from text properties. We set +these properties when adding strings to isearch history. By side +effect, set isearch-string to a copy of the current value with +all text properties removed." + (unless (zerop (length isearch-string)) + (loop for (var . value) in (isearch-saved-state-from-string + isearch-string) + do (set var value)) + (setq isearch-string (copy-sequence isearch-string)) + (set-text-properties 0 (length isearch-string) nil isearch-string))) + (defun isearch-repeat (direction) ;; Utility for isearch-repeat-forward and -backward. (if (eq isearch-forward (eq direction 'forward)) ;; C-s in forward or C-r in reverse. (if (equal isearch-string "") ;; If search string is empty, use last one. - (if (null (if isearch-regexp regexp-search-ring search-ring)) + (if (null (symbol-value (isearch-get-ring))) (setq isearch-error "No previous search string") - (setq isearch-string - (if isearch-regexp - (car regexp-search-ring) - (car search-ring)) - isearch-message - (mapconcat 'isearch-text-char-description - isearch-string "") - isearch-case-fold-search isearch-last-case-fold-search)) + (progn + (setq isearch-string + (car (symbol-value (isearch-get-ring)))) + (isearch-update-state-from-string) + (setq isearch-message + (mapconcat 'isearch-text-char-description + isearch-string "")))) ;; If already have what to search for, repeat it. (or isearch-success (progn @@ -1342,25 +1412,81 @@ (setq isearch-success t isearch-adjusted t) (isearch-update)) -(defun isearch-toggle-word () - "Toggle word searching on or off." - (interactive) - (setq isearch-word (not isearch-word)) - (setq isearch-success t isearch-adjusted t) - (isearch-update)) +(defun* isearch-cycle-word-mode (&optional (mode nil mode-supplied-p)) + "Cycle isearch through normal, word, and symbol searching. If +MODE is supplied, set the word mode directly to the mode. MODE +should be either the symbol `word' for word-matching mode, +`symbol' for symbol-matching mode, or nil for normal mode." + (interactive) + (setq isearch-word (cond + (mode-supplied-p mode) + ((eq isearch-word 'symbol) nil) + (isearch-word 'symbol) + (t 'word))) + (setq isearch-success t isearch-adjusted t) + (isearch-update)) + +(defalias 'isearch-toggle-word 'isearch-cycle-word-mode) + +(defun isearch-toggle-symbol-mode () + (interactive) + (isearch-cycle-word-mode + (if (eq isearch-word 'symbol) + nil + 'symbol))) + +(defun isearch-toggle-context-filter-flags (filter-flags) + "Toggle flags in `isearch-context-filter'. If any flag in +FILTER-FLAGS is present, remove all flags in FILTER-FLAGS. +Otherwise, ensure all flags in FILTER-FLAGS are in +`isearch-context-filter'" + (let ((flag-present (loop for flag in filter-flags + thereis (memq flag isearch-context-filter))) + (stripped-filter (loop for old-flag in isearch-context-filter + unless (memq old-flag filter-flags) + collect old-flag))) + (setq isearch-context-filter + (if flag-present + stripped-filter + (append filter-flags stripped-filter)))) + (setq isearch-success t isearch-adjusted t) + (isearch-update)) + +(defun isearch-toggle-match-comments () + "Toggle matching inside comments on or off." + (interactive) + (isearch-toggle-context-filter-flags '(comment))) + +(defun isearch-toggle-match-strings () + "Toggle matching inside comments on or off." + (interactive) + (isearch-toggle-context-filter-flags '(string))) + +(defun isearch-toggle-match-text () + "Toggle matching inside comments on or off." + (interactive) + (isearch-toggle-context-filter-flags '(text))) + +(defun isearch-toggle-match-comments-and-strings () + "Toggle matching inside comments and strings on or off." + (interactive) + (isearch-toggle-context-filter-flags '(comment string))) + +(defun isearch-toggle-identifier-mode () + "Toggle matching whole symbols outside comments and strings on or off." + (interactive) + (if (or isearch-word isearch-context-filter) + (setq isearch-word nil + isearch-context-filter nil) + (isearch-toggle-symbol-mode) + (isearch-toggle-match-comments-and-strings))) (defun isearch-toggle-case-fold () "Toggle case folding in searching on or off." (interactive) (setq isearch-case-fold-search (if isearch-case-fold-search nil 'yes)) - (let ((message-log-max nil)) - (message "%s%s [case %ssensitive]" - (isearch-message-prefix nil nil isearch-nonincremental) - isearch-message - (if isearch-case-fold-search "in" ""))) (setq isearch-success t isearch-adjusted t) - (sit-for 1) (isearch-update)) (defun isearch-query-replace (&optional delimited regexp-flag) @@ -1382,7 +1508,16 @@ ;; `exit-recursive-edit' in `isearch-done' that terminates ;; the execution of this command when it is non-nil. ;; We call `exit-recursive-edit' explicitly at the end below. - (isearch-recursive-edit nil)) + (isearch-recursive-edit nil) + ;; Make perform-replace respect our contextual filtering. + (replace-search-function + `(lambda (&rest args) + (apply #'isearch-context-filter-search-function + ',replace-search-function args))) + (replace-re-search-function + `(lambda (&rest args) + (apply #'isearch-context-filter-search-function + ',replace-re-search-function args)))) (isearch-done nil t) (isearch-clean-overlays) (if (and isearch-other-end @@ -1398,7 +1533,11 @@ (query-replace-read-to isearch-string (concat "Query replace" - (if (or delimited isearch-word) " word" "") + (cond ((eq isearch-word 'symbol) + " symbol") + ((or delimited isearch-word) + " word ") + (t "")) (if isearch-regexp " regexp" "") (if (and transient-mark-mode mark-active) " in region" "")) isearch-regexp) @@ -1421,12 +1560,14 @@ (interactive (list (cond - (isearch-word (concat "\\b" (replace-regexp-in-string - "\\W+" "\\W+" - (replace-regexp-in-string - "^\\W+\\|\\W+$" "" isearch-string) - nil t) - "\\b")) + (isearch-word + (concat (if (eq isearch-word 'symbol) "\\_<" "\\b") + (replace-regexp-in-string + "\\W+" "\\W+" + (replace-regexp-in-string + "^\\W+\\|\\W+$" "" isearch-string) + nil t) + (if (eq isearch-word 'symbol) "\\_>" "\\b"))) (isearch-regexp isearch-string) (t (regexp-quote isearch-string))) (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) @@ -2060,12 +2201,10 @@ (defun isearch-ring-adjust1 (advance) ;; Helper for isearch-ring-adjust - (let* ((ring (if isearch-regexp regexp-search-ring search-ring)) + (let* ((ring (isearch-get-ring)) (length (length ring)) - (yank-pointer-name (if isearch-regexp - 'regexp-search-ring-yank-pointer - 'search-ring-yank-pointer)) - (yank-pointer (eval yank-pointer-name))) + (yank-pointer-name (isearch-get-yank-pointer)) + (yank-pointer (symbol-value yank-pointer-name))) (if (zerop length) () (set yank-pointer-name @@ -2082,6 +2221,7 @@ (isearch-ring-adjust1 advance) (if search-ring-update (progn + (isearch-update-state-from-string) (isearch-search) (isearch-push-state) (isearch-update)) @@ -2104,7 +2244,7 @@ (defun isearch-complete1 () ;; Helper for isearch-complete and isearch-complete-edit ;; Return t if completion OK, nil if no completion exists. - (let* ((ring (if isearch-regexp regexp-search-ring search-ring)) + (let* ((ring (symbol-value (isearch-get-ring))) (completion-ignore-case case-fold-search) (completion (try-completion isearch-string ring))) (cond @@ -2182,6 +2322,51 @@ (isearch-message-suffix c-q-hack ellipsis))) (if c-q-hack m (let ((message-log-max nil)) (message "%s" m))))) +(defun isearch-context-filter-match-p () + "Return t if the current location satisfies `isearch-context-filter'." + ;; Compute the parse state only when we might not match it. Use + ;; parse-partial-sexp, not syntax-ppss, to avoid confusing match + ;; highlighting. + (loop with parse-state = (if isearch-context-filter + (parse-partial-sexp (point-min) (point))) + for condition in isearch-context-filter + never (case condition + (string (nth 3 parse-state)) + (comment (nth 4 parse-state)) + (text (not (nth 8 parse-state)))))) + +(defun isearch-context-filter-search-function (search-func pat bound noerror) + "Wrap SEARCH-FUNC so as to enforce `isearch-context-filter'. " + + (let (found) + (while (and (setq found (funcall search-func pat bound noerror)) + (not (isearch-context-filter-match-p)))) + found)) + +(defun isearch-describe-context-filter (context-filter) + "Return a string describing isearch context-filter CONTEXT-FILTER." + (let ((want-comments (not (memq 'comment context-filter))) + (want-strings (not (memq 'string context-filter))) + (want-text (not (memq 'text context-filter)))) + (cond ((null context-filter) "everywhere") + ((not (or want-comments want-strings want-text)) + "[no match]") + (want-text + (concat "no-" + (cond (want-strings + "comment") + (want-comments + "string") + (t + "string-or-comment")))) + (t + (cond ((and want-strings want-comments) + "string-and-comment") + (want-strings + "string") + (want-comments + "comment")))))) + (defun isearch-message-prefix (&optional _c-q-hack ellipsis nonincremental) ;; If about to search, and previous search regexp was invalid, ;; check that it still is. If it is valid now, @@ -2194,16 +2379,33 @@ ;; If currently failing, display no ellipsis. (or isearch-success (setq ellipsis nil)) (let ((m (concat (if isearch-success "" "failing ") - (if isearch-adjusted "pending " "") - (if (and isearch-wrapped + (if (and isearch-wrapped (not isearch-wrap-function) (if isearch-forward (> (point) isearch-opoint) (< (point) isearch-opoint))) "over") (if isearch-wrapped "wrapped ") - (if isearch-word "word " "") + (cond ((eq isearch-word 'symbol) "symbol ") + (isearch-word "word ") + (t "")) + + ;; Display a message for whichever option isn't the + ;; default. + (cond ((and isearch-case-fold-search + (not case-fold-search)) + "case-insensitive ") + ((and case-fold-search + (not isearch-case-fold-search)) + "case-sensitive ") + (t "")) + (if isearch-regexp "regexp " "") + (if isearch-context-filter + (concat (isearch-describe-context-filter + isearch-context-filter) + " ") + "") (if multi-isearch-next-buffer-current-function "multi " "") (or isearch-message-prefix-add "") (if nonincremental "search" "I-search") @@ -2234,12 +2436,24 @@ This returned function will be used by `isearch-search-string' to search for the first occurrence of STRING or its translation.") +(defun isearch-symbol-search-forward (string bound noerror) + (re-search-forward + (concat "\\_<" (regexp-quote string) "\\_>") bound noerror)) + +(defun isearch-symbol-search-backward (string bound noerror) + (re-search-backward + (concat "\\_<" (regexp-quote string) "\\_>") bound noerror)) + (defun isearch-search-fun () "Return the function to use for the search. Can be changed via `isearch-search-fun-function' for special needs." (if isearch-search-fun-function (funcall isearch-search-fun-function) (cond + ((eq isearch-word 'symbol) + (if isearch-forward + 'isearch-symbol-search-forward + 'isearch-symbol-search-backward)) (isearch-word ;; Use lax versions to not fail at the end of the word while ;; the user adds and removes characters in the search string @@ -2259,7 +2473,8 @@ If found, move point to the end of the occurrence, update the match data, and return point." (let* ((func (isearch-search-fun)) - (pos1 (save-excursion (funcall func string bound noerror))) + (pos1 (save-excursion (isearch-context-filter-search-function + func string bound noerror))) pos2) (when (and ;; Avoid "obsolete" warnings for translation-table-for-input. @@ -2282,7 +2497,8 @@ (when translated (save-match-data (save-excursion - (if (setq pos2 (funcall func translated bound noerror)) + (if (setq pos2 (isearch-context-filter-search-function + func translated bound noerror)) (setq match-data (match-data t))))) (when (and pos2 (or (not pos1) @@ -2323,8 +2539,8 @@ (if (or (not isearch-success) (bobp) (eobp) (= (match-beginning 0) (match-end 0)) - (funcall isearch-filter-predicate - (match-beginning 0) (match-end 0))) + (funcall isearch-filter-predicate + (match-beginning 0) (match-end 0))) (setq retry nil))) (setq isearch-just-started nil) (if isearch-success @@ -2702,8 +2918,8 @@ (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))) + (funcall isearch-filter-predicate + (match-beginning 0) (match-end 0))) (setq retry nil))) success) (error nil))) @@ -2776,7 +2992,8 @@ (run-at-time lazy-highlight-interval nil 'isearch-lazy-highlight-update))))))))) -(defun isearch-resume (string regexp word forward message case-fold) +(defun* isearch-resume (string regexp word + forward message case-fold &rest args) "Resume an incremental search. STRING is the string or regexp searched for. REGEXP non-nil means the resumed search was a regexp search. @@ -2784,7 +3001,7 @@ FORWARD non-nil means resume a forward search. MESSAGE is the echo-area message recorded for the search resumed. CASE-FOLD non-nil means the search was case-insensitive." - (isearch-mode forward regexp nil nil word) + (apply #'isearch-mode forward regexp nil nil word args) (setq isearch-string string isearch-message message isearch-case-fold-search case-fold) === modified file 'lisp/replace.el' --- lisp/replace.el 2011-07-02 13:53:53 +0000 +++ lisp/replace.el 2011-07-07 05:55:54 +0000 @@ -1797,10 +1797,10 @@ (if delimited-flag (setq search-function 're-search-forward - search-string (concat "\\b" + search-string (concat (if (eq delimited-flag 'symbol) "\\_<" "\\b") (if regexp-flag from-string (regexp-quote from-string)) - "\\b"))) + (if (eq delimited-flag 'symbol) "\\_>" "\\b")))) (when query-replace-lazy-highlight (setq isearch-lazy-highlight-last-string nil)) @@ -1926,7 +1926,9 @@ (with-output-to-temp-buffer "*Help*" (princ (concat "Query replacing " - (if delimited-flag "word " "") + (cond ((eq delimited-flag 'symbol) "symbol ") + (delimited-flag "word ") + (t "")) (if regexp-flag "regexp " "") from-string " with " next-replacement ".\n\n"