[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#11746: feature request: `isearch-query-replace' should open invisibl
From: |
Juri Linkov |
Subject: |
bug#11746: feature request: `isearch-query-replace' should open invisible text |
Date: |
Thu, 14 Feb 2013 21:02:15 +0200 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (x86_64-pc-linux-gnu) |
> 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
- bug#11746: feature request: `isearch-query-replace' should open invisible text,
Juri Linkov <=