aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshynur2023-09-02 22:39:00 +0800
committerEli Zaretskii2023-09-10 10:37:43 +0300
commitd04c538e7c331a643c61c4af5070288ce220ebfb (patch)
treeec902722733c1dd4114950b096c4017f5ac1f6f9
parent4101464b4765b67c1b8b5ec099ffccf37385ef9c (diff)
downloademacs-d04c538e7c331a643c61c4af5070288ce220ebfb.tar.gz
emacs-d04c538e7c331a643c61c4af5070288ce220ebfb.zip
`dired-next-line' movement style (bug#65621)
Point will skips empty lines and optionally goto the other end when encountering a boundary. * lisp/dired.el (dired-movement-style): Control whether to skip empty lines and whether to cycle through non-empty lines. * lisp/dired.el (dired-next-line): Add a new movement style controlled by `dired-movement-style'. * etc/NEWS (dired-movement-style):
-rw-r--r--etc/NEWS9
-rw-r--r--lisp/dired.el76
2 files changed, 78 insertions, 7 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 51e89fc96dd..59b8b610276 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -290,6 +290,15 @@ This allows changing which type of whitespace changes are ignored when
290regenerating hunks with 'diff-ignore-whitespace-hunk'. Defaults to 290regenerating hunks with 'diff-ignore-whitespace-hunk'. Defaults to
291the previously hard-coded "-b". 291the previously hard-coded "-b".
292 292
293** Dired
294
295---
296*** New user option 'dired-movement-style'.
297When non-nil, make 'dired-next-line' and 'dired-previous-line' skip
298empty lines. It also controls how to move point when encountering a
299boundary (e.g., if every line is visible, invoking 'dired-next-line'
300at the last line will move to the first line).
301
293** Ediff 302** Ediff
294 303
295--- 304---
diff --git a/lisp/dired.el b/lisp/dired.el
index e96b85a173a..88f856350b0 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -495,6 +495,21 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used."
495 (string :tag "Switches")) 495 (string :tag "Switches"))
496 :version "29.1") 496 :version "29.1")
497 497
498(defcustom dired-movement-style nil
499 "Non-nil means point skips empty lines when moving.
500This affects only `dired-next-line' and `dired-previous-line'.
501
502Possible non-nil values:
503 * `cycle': the next/previous line of the last/first visible line is
504 the first/last visible line.
505 * `bounded': cannot move up/down if the current line is the
506 first/last visible line."
507 :type '(choice (const :tag "Move to any line" nil)
508 (const :tag "Loop through non-empty lines" cycle)
509 (const :tag "Only to non-empty line" bounded))
510 :group 'dired
511 :version "30.1")
512
498(defcustom dired-hide-details-preserved-columns nil 513(defcustom dired-hide-details-preserved-columns nil
499 "List of columns which are not hidden in `dired-hide-details-mode'." 514 "List of columns which are not hidden in `dired-hide-details-mode'."
500 :type '(repeat integer) 515 :type '(repeat integer)
@@ -2666,22 +2681,69 @@ Otherwise, toggle `read-only-mode'."
2666 (wdired-change-to-wdired-mode) 2681 (wdired-change-to-wdired-mode)
2667 (read-only-mode 'toggle))) 2682 (read-only-mode 'toggle)))
2668 2683
2669(defun dired-next-line (arg) 2684(defun dired--trivial-next-line (arg)
2670 "Move down lines then position at filename. 2685 "Move down ARG lines then position at filename."
2671Optional prefix ARG says how many lines to move; default is one line."
2672 (interactive "^p")
2673 (let ((line-move-visual) 2686 (let ((line-move-visual)
2674 (goal-column)) 2687 (goal-column))
2675 (line-move arg t)) 2688 (line-move arg t))
2676 ;; We never want to move point into an invisible line. 2689 ;; We never want to move point into an invisible line.
2677 (while (and (invisible-p (point)) 2690 (while (and (invisible-p (point))
2678 (not (if (and arg (< arg 0)) (bobp) (eobp)))) 2691 (not (if (and arg (< arg 0)) (bobp) (eobp))))
2679 (forward-char (if (and arg (< arg 0)) -1 1))) 2692 (forward-char (if (and arg (< arg 0)) -1 1)))
2680 (dired-move-to-filename)) 2693 (dired-move-to-filename))
2681 2694
2695(defun dired-next-line (arg)
2696 "Move down lines then position at filename.
2697Optional prefix ARG says how many lines to move; default is one line.
2698
2699Whether to skip empty lines and how to move when encountering a
2700boundary are controlled by `dired-movement-style'."
2701 (interactive "^p")
2702 (if dired-movement-style
2703 (let ((old-position (progn
2704 ;; It's always true that we should move
2705 ;; to the filename when possible.
2706 (dired-move-to-filename)
2707 (point)))
2708 ;; Up/Down indicates the direction.
2709 (moving-down (if (cl-plusp arg)
2710 1 ; means Down.
2711 -1))) ; means Up.
2712 ;; Line by line in case we forget to skip empty lines.
2713 (while (not (zerop arg))
2714 (dired--trivial-next-line moving-down)
2715 (when (= old-position (point))
2716 ;; Now point is at beginning/end of movable area,
2717 ;; but it still wants to move farther.
2718 (if (eq dired-movement-style 'cycle)
2719 ;; `cycle': go to the other end.
2720 (goto-char (if (cl-plusp moving-down)
2721 (point-min)
2722 (point-max)))
2723 ;; `bounded': go back to the last non-empty line.
2724 (while (string-match-p "\\`[[:blank:]]*\\'"
2725 (buffer-substring-no-properties
2726 (line-beginning-position)
2727 (line-end-position)))
2728 (dired--trivial-next-line (- moving-down)))
2729 ;; Encountered a boundary, so let's stop movement.
2730 (setq arg moving-down)))
2731 (when (not (string-match-p "\\`[[:blank:]]*\\'"
2732 (buffer-substring-no-properties
2733 (line-beginning-position)
2734 (line-end-position))))
2735 ;; Has moved to a non-empty line. This movement does
2736 ;; make sense.
2737 (cl-decf arg moving-down))
2738 (setq old-position (point))))
2739 (dired--trivial-next-line arg)))
2740
2682(defun dired-previous-line (arg) 2741(defun dired-previous-line (arg)
2683 "Move up lines then position at filename. 2742 "Move up lines then position at filename.
2684Optional prefix ARG says how many lines to move; default is one line." 2743Optional prefix ARG says how many lines to move; default is one line.
2744
2745Whether to skip empty lines and how to move when encountering a
2746boundary are controlled by `dired-movement-style'."
2685 (interactive "^p") 2747 (interactive "^p")
2686 (dired-next-line (- (or arg 1)))) 2748 (dired-next-line (- (or arg 1))))
2687 2749