From 2b19eb175d0664908f76bf7cc8dcc1eb5c140ce1 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 10 May 2026 13:44:40 -0500 Subject: refactor(dirvish): extract cj/--dired-line-is-directory-p `cj/dired-mark-all-visible-files' classified the current line as a directory via `(looking-at "^. d")' inline. Lift the classification into `cj/--dired-line-is-directory-p', a string predicate that takes a line and returns non-nil when it's a directory listing. The wrapper still walks the dired buffer line by line and calls `dired-mark' -- that iteration is dired-coupled and stays untested -- but the format-aware predicate is now isolated and verified. Six Normal/Boundary tests cover unmarked directories, marked directories (`*' prefix), regular files (`-' instead of `d'), symlinks (`l'), empty lines, and dired header lines (` /path:' and ` total N'). --- modules/dirvish-config.el | 17 ++++++- tests/test-dirvish-config-dired-line-directory.el | 56 +++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 tests/test-dirvish-config-dired-line-directory.el diff --git a/modules/dirvish-config.el b/modules/dirvish-config.el index ad2227e8..f032b1a0 100644 --- a/modules/dirvish-config.el +++ b/modules/dirvish-config.el @@ -180,14 +180,27 @@ used by `cj/dirvish-open-html-in-eww'." ;;; ------------------------ Dired Mark All Visible Files ----------------------- +(defun cj/--dired-line-is-directory-p (line) + "Return non-nil when LINE is a Dired listing of a directory. + +Dired prefixes each file line with a one-character mark column followed +by `ls -l' output, so a directory line reads as ` drwx...' (mark, +space, `d'). Header lines (` /path/to:'), `total N' lines, and empty +lines all fail this match. + +Pure helper used by `cj/dired-mark-all-visible-files'." + (and line (string-match-p "\\`. d" line))) + (defun cj/dired-mark-all-visible-files () "Mark all visible files in Dired mode." (interactive) (save-excursion (goto-char (point-min)) (while (not (eobp)) - (if (not (looking-at "^. d")) - (dired-mark 1)) + (let ((line (buffer-substring-no-properties + (line-beginning-position) (line-end-position)))) + (unless (cj/--dired-line-is-directory-p line) + (dired-mark 1))) (forward-line 1)))) ;;; ------------------------ Dirvish Duplicate File Copy ------------------------ diff --git a/tests/test-dirvish-config-dired-line-directory.el b/tests/test-dirvish-config-dired-line-directory.el new file mode 100644 index 00000000..7f344c7c --- /dev/null +++ b/tests/test-dirvish-config-dired-line-directory.el @@ -0,0 +1,56 @@ +;;; test-dirvish-config-dired-line-directory.el --- Tests for the directory-line predicate -*- lexical-binding: t; -*- + +;;; Commentary: +;; `cj/--dired-line-is-directory-p' is the testable predicate behind +;; `cj/dired-mark-all-visible-files'. Dired buffers prefix each file +;; line with a one-char mark column followed by the `ls -l' output, so +;; column 2 is the file-type letter (`d' for directory, `-' for regular +;; file). The wrapper iterates the buffer and skips lines this +;; predicate returns t for; the iteration stays dired-coupled and +;; untested, but the line-classification logic is now isolated. + +;;; Code: + +(require 'ert) +(require 'package) + +(setq package-user-dir (expand-file-name "elpa" user-emacs-directory)) +(package-initialize) +(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory)) +(add-to-list 'load-path (expand-file-name "elpa/dirvish-2.3.0/extensions" + user-emacs-directory)) +(require 'user-constants) +(require 'keybindings) +(require 'dirvish-config) + +(ert-deftest test-cj--dired-line-is-directory-p-unmarked-directory () + "Normal: an unmarked directory line (` drwx...') matches." + (should (cj/--dired-line-is-directory-p + " drwxr-xr-x 1 me me 4096 May 10 13:00 subdir/"))) + +(ert-deftest test-cj--dired-line-is-directory-p-marked-directory () + "Normal: a star-marked directory line (`* drwx...') matches." + (should (cj/--dired-line-is-directory-p + "* drwxr-xr-x 1 me me 4096 May 10 13:00 subdir/"))) + +(ert-deftest test-cj--dired-line-is-directory-p-regular-file () + "Normal: a regular file line (` -rw...') does not match." + (should-not (cj/--dired-line-is-directory-p + " -rw-r--r-- 1 me me 42 May 10 13:00 notes.txt"))) + +(ert-deftest test-cj--dired-line-is-directory-p-symlink-line () + "Boundary: a symlink line (` lrwx...') does not match -- only `d' is a dir." + (should-not (cj/--dired-line-is-directory-p + " lrwxrwxrwx 1 me me 12 May 10 13:00 link -> target"))) + +(ert-deftest test-cj--dired-line-is-directory-p-empty-line () + "Boundary: an empty string does not match." + (should-not (cj/--dired-line-is-directory-p ""))) + +(ert-deftest test-cj--dired-line-is-directory-p-header-line () + "Boundary: a dired header (` /path/to:') or `total' line does not match." + (should-not (cj/--dired-line-is-directory-p " /home/me/projects:")) + (should-not (cj/--dired-line-is-directory-p " total 24"))) + +(provide 'test-dirvish-config-dired-line-directory) +;;; test-dirvish-config-dired-line-directory.el ends here -- cgit v1.2.3