diff options
author | Juri Linkov <juri@linkov.net> | 2024-01-25 19:38:03 +0200 |
---|---|---|
committer | Juri Linkov <juri@linkov.net> | 2024-01-25 19:38:03 +0200 |
commit | b07265f8eed74dda792e13062baae94319484b4b (patch) | |
tree | 2fa985819833125548ae37a65a2d8678bf6f4b10 /lisp | |
parent | a8cfe3bda8b8008071818d6ac5e5103002ed6c08 (diff) | |
download | emacs-b07265f8eed74dda792e13062baae94319484b4b.tar.gz emacs-b07265f8eed74dda792e13062baae94319484b4b.tar.bz2 emacs-b07265f8eed74dda792e13062baae94319484b4b.zip |
* 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.
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/dired.el | 29 |
1 files 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. |