emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master b07265f8eed 1/2: * lisp/dired.el (dired--move-to-next-line): Impr


From: Juri Linkov
Subject: master b07265f8eed 1/2: * lisp/dired.el (dired--move-to-next-line): Improve to avoid an infinite loop.
Date: Thu, 25 Jan 2024 12:55:42 -0500 (EST)

branch: master
commit b07265f8eed74dda792e13062baae94319484b4b
Author: Juri Linkov <juri@linkov.net>
Commit: Juri Linkov <juri@linkov.net>

    * lisp/dired.el (dired--move-to-next-line): Improve to avoid an infinite 
loop.
    
    An infinite loop is possible in a directory without files and 
subdirectories,
    where even lines with . and .. are omitted, so 'dired-between-files' is true
    for all Dired lines.  For the case of dired-movement-style=cycle
    a guard is triggered when the loop wraps twice while the value 'arg'
    is not changing.  And for the case of dired-movement-style=bounded
    a guard is triggered when point doesn't move while trying to
    go back to the last non-empty line.
---
 lisp/dired.el | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/lisp/dired.el b/lisp/dired.el
index 69fa15dde73..cef93ab757c 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -2817,7 +2817,9 @@ is controlled by `dired-movement-style'."
     (dired--trivial-next-line arg)))
 
 (defun dired--move-to-next-line (arg jumpfun)
-  (let ((old-position (progn
+  (let ((wrapped nil)
+        (old-arg arg)
+        (old-position (progn
                         ;; It's always true that we should move
                         ;; to the filename when possible.
                         (dired-move-to-filename)
@@ -2832,16 +2834,27 @@ is controlled by `dired-movement-style'."
       (when (= old-position (point))
         ;; Now point is at beginning/end of movable area,
         ;; but it still wants to move farther.
-        (if (eq dired-movement-style 'cycle)
-            ;; `cycle': go to the other end.
+        (cond
+         ;; `cycle': go to the other end.
+         ((eq dired-movement-style 'cycle)
+          ;; Argument not changing on the second wrap
+          ;; means infinite loop with no files found.
+          (if (and wrapped (eq old-arg arg))
+              (setq arg 0)
             (goto-char (if (cl-plusp moving-down)
                            (point-min)
-                         (point-max)))
-          ;; `bounded': go back to the last non-empty line.
-          (while (dired-between-files)
-            (funcall jumpfun (- moving-down)))
+                         (point-max))))
+          (setq wrapped t))
+         ;; `bounded': go back to the last non-empty line.
+         ((eq dired-movement-style 'bounded)
+          (while (and (dired-between-files) (not (zerop arg)))
+            (funcall jumpfun (- moving-down))
+            ;; Point not moving means infinite loop.
+            (if (= old-position (point))
+                (setq arg 0)
+              (setq old-position (point))))
           ;; Encountered a boundary, so let's stop movement.
-          (setq arg moving-down)))
+          (setq arg (if (dired-between-files) 0 moving-down)))))
       (unless (dired-between-files)
         ;; Has moved to a non-empty line.  This movement does
         ;; make sense.



reply via email to

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