all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Shynur Xie <one.last.kiss@outlook.com>
To: Eli Zaretskii <eliz@gnu.org>, Stefan Kangas <stefankangas@gmail.com>
Cc: "65621@debbugs.gnu.org" <65621@debbugs.gnu.org>
Subject: bug#65621: [PATCH] `dired-next-line' go to meaningful line
Date: Sat, 2 Sep 2023 14:40:29 +0000	[thread overview]
Message-ID: <PH0PR11MB74704684AF077E05B8941D56D7EBA@PH0PR11MB7470.namprd11.prod.outlook.com> (raw)
In-Reply-To: <837cp8agwo.fsf@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 412 bytes --]

> We prefer that the documentation accompanies the code changes.  If
> nothing else, this enlarges the group of people who can write good
> documentation for Emacs.  It also lowers the probability that we
> will forget to document changes.

Understood.  This is my first time to write a NEWS entry, so it may
not be considered good documentation.

New patch is attached.  Thanks in advance for reviewing.

[-- Attachment #2: 0001-dired-next-line-movement-style.patch --]
[-- Type: application/octet-stream, Size: 5840 bytes --]

From d2927f014f5fb9eed8bb0fdf7c88c77a269a35d1 Mon Sep 17 00:00:00 2001
From: shynur <one.last.kiss@outlook.com>
Date: Sat, 2 Sep 2023 22:39:00 +0800
Subject: [PATCH] `dired-next-line' movement style

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):
---
 etc/NEWS      |  9 ++++++
 lisp/dired.el | 76 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 9a98db8..962e96c 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -282,6 +282,15 @@ This allows changing which type of whitespace changes are ignored when
 regenerating hunks with 'diff-ignore-whitespace-hunk'.  Defaults to
 the previously hard-coded "-b".
 
+** Dired
+
+---
+*** New user option 'dired-movement-style'.
+When non-nil, make 'dired-next-line' and 'dired-previous-line' skip
+empty lines.  It also controls how to move point when encountering a
+boundary (e.g., if every line is visible, invoking 'dired-next-line'
+at the last line will move to the first line).
+
 ** Ediff
 
 ---
diff --git a/lisp/dired.el b/lisp/dired.el
index e96b85a..88f8563 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."
                  (string :tag "Switches"))
   :version "29.1")
 
+(defcustom dired-movement-style nil
+  "Non-nil means point skips empty lines when moving.
+This affects only `dired-next-line' and `dired-previous-line'.
+
+Possible non-nil values:
+ *   `cycle': the next/previous line of the last/first visible line is
+              the first/last visible line.
+ * `bounded': cannot move up/down if the current line is the
+              first/last visible line."
+  :type '(choice (const :tag "Move to any line" nil)
+                 (const :tag "Loop through non-empty lines" cycle)
+                 (const :tag "Only to non-empty line" bounded))
+  :group 'dired
+  :version "30.1")
+
 (defcustom dired-hide-details-preserved-columns nil
   "List of columns which are not hidden in `dired-hide-details-mode'."
   :type '(repeat integer)
@@ -2666,22 +2681,69 @@ Otherwise, toggle `read-only-mode'."
       (wdired-change-to-wdired-mode)
     (read-only-mode 'toggle)))
 
-(defun dired-next-line (arg)
-  "Move down lines then position at filename.
-Optional prefix ARG says how many lines to move; default is one line."
-  (interactive "^p")
+(defun dired--trivial-next-line (arg)
+  "Move down ARG lines then position at filename."
   (let ((line-move-visual)
-	(goal-column))
+    (goal-column))
     (line-move arg t))
   ;; We never want to move point into an invisible line.
   (while (and (invisible-p (point))
-	      (not (if (and arg (< arg 0)) (bobp) (eobp))))
+          (not (if (and arg (< arg 0)) (bobp) (eobp))))
     (forward-char (if (and arg (< arg 0)) -1 1)))
   (dired-move-to-filename))
 
+(defun dired-next-line (arg)
+  "Move down lines then position at filename.
+Optional prefix ARG says how many lines to move; default is one line.
+
+Whether to skip empty lines and how to move when encountering a
+boundary are controlled by `dired-movement-style'."
+  (interactive "^p")
+  (if dired-movement-style
+      (let ((old-position (progn
+                            ;; It's always true that we should move
+                            ;; to the filename when possible.
+                            (dired-move-to-filename)
+                            (point)))
+            ;; Up/Down indicates the direction.
+            (moving-down (if (cl-plusp arg)
+                             1    ; means Down.
+                           -1)))  ; means Up.
+        ;; Line by line in case we forget to skip empty lines.
+        (while (not (zerop arg))
+          (dired--trivial-next-line moving-down)
+          (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.
+                (goto-char (if (cl-plusp moving-down)
+                               (point-min)
+                             (point-max)))
+              ;; `bounded': go back to the last non-empty line.
+              (while (string-match-p "\\`[[:blank:]]*\\'"
+                                     (buffer-substring-no-properties
+                                      (line-beginning-position)
+                                      (line-end-position)))
+                (dired--trivial-next-line (- moving-down)))
+              ;; Encountered a boundary, so let's stop movement.
+              (setq arg moving-down)))
+          (when (not (string-match-p "\\`[[:blank:]]*\\'"
+                                     (buffer-substring-no-properties
+                                      (line-beginning-position)
+                                      (line-end-position))))
+            ;; Has moved to a non-empty line.  This movement does
+            ;; make sense.
+            (cl-decf arg moving-down))
+          (setq old-position (point))))
+    (dired--trivial-next-line arg)))
+
 (defun dired-previous-line (arg)
   "Move up lines then position at filename.
-Optional prefix ARG says how many lines to move; default is one line."
+Optional prefix ARG says how many lines to move; default is one line.
+
+Whether to skip empty lines and how to move when encountering a
+boundary are controlled by `dired-movement-style'."
   (interactive "^p")
   (dired-next-line (- (or arg 1))))
 
-- 
2.41.0.windows.3


  reply	other threads:[~2023-09-02 14:40 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-08-30 13:02 bug#65621: [PATCH] `dired-next-line' go to meaningful line Shynur Xie
2023-08-30 13:36 ` Eli Zaretskii
2023-08-30 13:50   ` Shynur Xie
2023-08-30 14:20     ` Eli Zaretskii
2023-08-30 19:14       ` Stefan Kangas
2023-08-30 20:58         ` Drew Adams
2023-08-30 21:34           ` Stefan Kangas
2023-08-30 22:36             ` Drew Adams
2023-08-31  5:45         ` Shynur Xie
2023-08-31 15:35           ` Drew Adams
2023-08-31 15:46             ` Shynur Xie
2023-08-31 15:55               ` Drew Adams
2023-08-31 18:15                 ` Shynur Xie
2023-08-31 19:10                   ` Drew Adams
2023-08-31 19:17                     ` Drew Adams
2023-08-31 19:44                     ` Shynur Xie
2023-08-31 21:51                       ` Drew Adams
2023-08-31 21:35                   ` Stefan Kangas
2023-08-31 21:37                     ` Stefan Kangas
2023-09-01 17:29                     ` Shynur Xie
2023-09-01 18:46                       ` Drew Adams
2023-09-01 20:51                         ` Shynur Xie
2023-09-01 21:06                           ` Drew Adams
2023-09-02 12:05                             ` Shynur Xie
2023-09-02 12:13                               ` Eli Zaretskii
2023-09-02 12:18                                 ` Shynur Xie
2023-09-02 12:39                                   ` Eli Zaretskii
2023-09-02 14:40                                     ` Shynur Xie [this message]
2023-09-10  7:45                                       ` Eli Zaretskii
2023-09-03 21:47                               ` Drew Adams
2023-09-07 15:04                                 ` Shynur Xie
2023-08-30 14:54 ` Drew Adams
2023-08-30 15:39   ` Shynur Xie
2023-08-30 15:55     ` Drew Adams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=PH0PR11MB74704684AF077E05B8941D56D7EBA@PH0PR11MB7470.namprd11.prod.outlook.com \
    --to=one.last.kiss@outlook.com \
    --cc=65621@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=stefankangas@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.