bug-gnu-emacs
[Top][All Lists]
Advanced

[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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]