Package: emacs;
Reported by: michael_heerdegen <at> web.de
Date: Tue, 19 Jun 2012 17:59:01 UTC
Severity: wishlist
Merged with 14566
Found in version 24.3
Done: Juri Linkov <juri <at> jurta.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Juri Linkov <juri <at> jurta.org> To: Michael Heerdegen <michael_heerdegen <at> web.de> Cc: 11746 <at> debbugs.gnu.org Subject: bug#11746: feature request: `isearch-query-replace' should open invisible text Date: Thu, 14 Feb 2013 21:02:15 +0200
> if you have `search-invisible' non-nil, isearch "opens" invisible > text. But when you hit M-% or C-M-% while searching, you loose this > ability: point will just be put inside invisible areas, and you don't > see what you're doing. The recent adaptation of isearch functions to `perform-replace' makes it easy to implement this now. Depending on the value of `search-invisible', if `open' then M-% or C-M-% will open invisible overlays, if `nil' then they will skip invisible text, and if `t' they will match replacements inside invisible areas like now. The key point is using a search loop like in `isearch-search' that either opens invisible overlays or skips them. BTW, a similar loop could be later added to occur and hi-lock too, but since in occur and hi-lock it makes no sense to open overlays, they should just skip invisible areas like in `isearch-lazy-highlight-search'. The patch below moves the search related part of code from `perform-replace' to a new function `replace-search', adds a loop like in `isearch-search', and moves handling of `query-replace-skip-read-only' to this loop. It's worth to note that `wdired-isearch-filter-read-only' already has exactly the same condition that checks for read-only-ness, so the same condition is duplicated for modes that set both a read-only-skipping isearch filter and `query-replace-skip-read-only', but this is not a problem. === modified file 'lisp/replace.el' --- lisp/replace.el 2013-02-01 23:38:41 +0000 +++ lisp/replace.el 2013-02-14 18:55:14 +0000 @@ -1794,6 +1796,54 @@ (defvar replace-re-search-function nil It is called with three arguments, as if it were `re-search-forward'.") +(defun replace-search (search-string limit regexp-flag delimited-flag + case-fold-search) + "Search the next occurence of SEARCH-STRING to replace." + ;; Let-bind global isearch-* variables to values used + ;; to search the next replacement. These let-bindings + ;; should be effective both at the time of calling + ;; `isearch-search-fun-default' and also at the + ;; time of funcalling `search-function'. + ;; These isearch-* bindings can't be placed higher + ;; outside of this function because then another I-search + ;; used after `recursive-edit' might override them. + (let* ((isearch-regexp regexp-flag) + (isearch-word delimited-flag) + (isearch-lax-whitespace + replace-lax-whitespace) + (isearch-regexp-lax-whitespace + replace-regexp-lax-whitespace) + (isearch-case-fold-search case-fold-search) + (isearch-adjusted nil) + (isearch-nonincremental t) ; don't use lax word mode + (isearch-forward t) + (search-function + (or (if regexp-flag + replace-re-search-function + replace-search-function) + (isearch-search-fun-default))) + (retry t) + (success nil)) + ;; Use a loop like in `isearch-search'. + (while retry + (setq success (funcall search-function search-string limit t)) + ;; Clear RETRY unless the search predicate says + ;; to skip this search hit. + (if (or (not success) + (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)))) + ;; Optionally ignore matches that have a read-only property. + (or (not query-replace-skip-read-only) + (not (text-property-not-all + (match-beginning 0) (match-end 0) + 'read-only nil))))) + (setq retry nil))) + success)) + (defun perform-replace (from-string replacements query-flag regexp-flag delimited-flag &optional repeat-count map start end) @@ -1881,29 +1931,6 @@ (defun perform-replace (from-string repl ;; Loop finding occurrences that perhaps should be replaced. (while (and keep-going (not (or (eobp) (and limit (>= (point) limit)))) - ;; Let-bind global isearch-* variables to values used - ;; to search the next replacement. These let-bindings - ;; should be effective both at the time of calling - ;; `isearch-search-fun-default' and also at the - ;; time of funcalling `search-function'. - ;; These isearch-* bindings can't be placed higher - ;; outside of this loop because then another I-search - ;; used after `recursive-edit' might override them. - (let* ((isearch-regexp regexp-flag) - (isearch-word delimited-flag) - (isearch-lax-whitespace - replace-lax-whitespace) - (isearch-regexp-lax-whitespace - replace-regexp-lax-whitespace) - (isearch-case-fold-search case-fold-search) - (isearch-adjusted nil) - (isearch-nonincremental t) ; don't use lax word mode - (isearch-forward t) - (search-function - (or (if regexp-flag - replace-re-search-function - replace-search-function) - (isearch-search-fun-default)))) ;; Use the next match if it is already known; ;; otherwise, search for a match after moving forward ;; one char if progress is required. @@ -1916,8 +1943,9 @@ (defun perform-replace (from-string repl ;; adjacent match. (match-again (and - (funcall search-function search-string - limit t) + (replace-search search-string limit + regexp-flag delimited-flag + case-fold-search) ;; For speed, use only integers and ;; reuse the list used last time. (replace-match-data t real-match-data))) @@ -1930,13 +1958,12 @@ (defun perform-replace (from-string repl ;; if the search fails. (let ((opoint (point))) (forward-char 1) - (if (funcall - search-function search-string - limit t) - (replace-match-data - t real-match-data) + (if (replace-search search-string limit + regexp-flag delimited-flag + case-fold-search) + (replace-match-data t real-match-data) (goto-char opoint) - nil))))))) + nil)))))) ;; Record whether the match is nonempty, to avoid an infinite loop ;; repeatedly matching the same empty string. @@ -1957,13 +1984,6 @@ (defun perform-replace (from-string repl (let ((match (match-data))) (and (/= (nth 0 match) (nth 1 match)) match)))))) - - ;; Optionally ignore matches that have a read-only property. - (unless (and query-replace-skip-read-only - (text-property-not-all - (nth 0 real-match-data) (nth 1 real-match-data) - 'read-only nil)) - ;; Calculate the replacement string, if necessary. (when replacements (set-match-data real-match-data) @@ -2168,7 +2188,7 @@ (defun perform-replace (from-string repl (match-end 0) (current-buffer)) (match-data t))) - stack))))) + stack)))) (replace-dehighlight)) (or unread-command-events
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.