Subject: Re: bug#14013: 24.3.50; dired-isearch-filenames-regexp is matching text outside filenames

From: Juri Linkov <[email-masked]>
Date: Sun, 13 Feb 2022 20:59:30 +0200

> Why not (add-function :around (local isearch-search-fun-function)
>                       #'dired--isearch-filenames)
> and then
>
>    (defun dired--isearch-filenames (iiff &rest args)
>      (let ((fun (apply iiff args)))
>        (lambda (&rest args)
>          (unless (get-text-property (point) 'dired-filename)
>            (if isearch-forward
>    	       (goto-char (or (next-single-property-change
>                                (point) 'dired-filename)
>                               (point-max)))
>              (goto-char (or (previous-single-property-change
>                             (point) 'dired-filename)
>                         (point-min)))))
>          (apply fun args))))

After a short delay, this has been implemented now:

diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 41c45b4e51..f1d0f9e225 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -3140,11 +3140,11 @@ dired-isearch-filenames-mode
 When off, it uses the original predicate."
   :lighter nil
   (if dired-isearch-filenames-mode
-      (add-function :before-while (local 'isearch-filter-predicate)
-                    #'dired-isearch-filter-filenames
+      (add-function :around (local 'isearch-search-fun-function)
+                    #'dired-isearch-search-filenames
                     '((isearch-message-prefix . "filename ")))
-    (remove-function (local 'isearch-filter-predicate)
-                     #'dired-isearch-filter-filenames))
+    (remove-function (local 'isearch-search-fun-function)
+                     #'dired-isearch-search-filenames))
   (when isearch-mode
     (setq isearch-success t isearch-adjusted t)
     (isearch-update)))
@@ -3168,12 +3168,34 @@ dired-isearch-filenames-end
   (unless isearch-suspended
     (kill-local-variable 'dired-isearch-filenames)))
 
-(defun dired-isearch-filter-filenames (beg end)
+(defun dired-isearch-search-filenames (orig-fun)
   "Test whether some part of the current search match is inside a file name.
 This function returns non-nil if some part of the text between BEG and END
 is part of a file name (i.e., has the text property `dired-filename')."
-  (text-property-not-all (min beg end) (max beg end)
-			 'dired-filename nil))
+  (let ((search-fun (funcall orig-fun)))
+    (lambda (string &optional bound noerror count)
+      (let ((beg (and (get-text-property (point) 'dired-filename) (point)))
+            end found)
+        (unless beg
+          (setq beg (if isearch-forward
+                        (next-single-property-change (point) 'dired-filename)
+                      (previous-single-property-change (point) 'dired-filename)))
+          (when beg (goto-char beg)))
+        (while (and beg (not found))
+          (setq end (if isearch-forward
+                        (next-single-property-change beg 'dired-filename)
+                      (previous-single-property-change beg 'dired-filename)))
+          (setq found (funcall search-fun string
+                               (if isearch-forward
+                                   (min (or bound (point-max)) end)
+                                 (max (or bound (point-max)) end))
+                               noerror count))
+          (unless found
+            (setq beg (if isearch-forward
+                          (next-single-property-change end 'dired-filename)
+                        (previous-single-property-change end 'dired-filename)))
+            (when beg (goto-char beg))))
+        found))))
 
 ;;;###autoload
 (defun dired-isearch-filenames ()
diff --git a/lisp/wdired.el b/lisp/wdired.el
index ab3b91bbe5..573e125bc8 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -217,6 +217,7 @@ wdired-mode
   (error "This mode can be enabled only by `wdired-change-to-wdired-mode'"))
 (put 'wdired-mode 'mode-class 'special)
 
+(autoload 'dired-isearch-search-filenames "dired-aux")
 
 ;;;###autoload
 (defun wdired-change-to-wdired-mode ()
@@ -238,8 +239,9 @@ wdired-change-to-wdired-mode
   (setq-local wdired--old-point (point))
   (wdired--set-permission-bounds)
   (setq-local query-replace-skip-read-only t)
-  (add-function :after-while (local 'isearch-filter-predicate)
-                #'wdired-isearch-filter-read-only)
+  (add-function :around (local 'isearch-search-fun-function)
+                #'dired-isearch-search-filenames)
+  (setq-local replace-re-search-function #'dired-isearch-search-filenames)
   (use-local-map wdired-mode-map)
   (force-mode-line-update)
   (setq buffer-read-only nil)
@@ -438,8 +440,9 @@ wdired-change-to-dired-mode
     (remove-text-properties
      (point-min) (point-max)
      '(front-sticky nil rear-nonsticky nil read-only nil keymap nil)))
-  (remove-function (local 'isearch-filter-predicate)
-                   #'wdired-isearch-filter-read-only)
+  (remove-function (local 'isearch-search-fun-function)
+                   #'dired-isearch-search-filenames)
+  (kill-local-variable 'replace-re-search-function)
   (use-local-map dired-mode-map)
   (force-mode-line-update)
   (setq buffer-read-only t)