From 2a9257006fcde777e217708b4593461a9e6c07a8 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 10 May 2026 13:27:51 -0500 Subject: refactor(dirvish): extract cj/--duplicate-file-name helper The name-mangling logic in `cj/dirvish-duplicate-file' was inline -- inseparable from the dired side effects (existence check, copy, revert). Extract to `cj/--duplicate-file-name', a pure function from FILE to FILE-WITH-COPY-SUFFIX. Seven Normal/Boundary tests cover the cases I care about: typical extension, elisp file, no extension, multi-dot extensions (only the last dot counts), leading-dot dotfiles, relative paths, spaces in the base name. The wrapper retains the dired-mode interactive shape and now reads as a thin shell over the pure helper. --- modules/dirvish-config.el | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) (limited to 'modules') diff --git a/modules/dirvish-config.el b/modules/dirvish-config.el index fadf09ca..fa5567ad 100644 --- a/modules/dirvish-config.el +++ b/modules/dirvish-config.el @@ -154,33 +154,43 @@ Filters for audio files, prompts for the playlist name, and saves the resulting ;;; ------------------------ Dirvish Duplicate File Copy ------------------------ +(defun cj/--duplicate-file-name (file) + "Return FILE's path with `-copy' inserted before the extension. + +Pure helper used by `cj/dirvish-duplicate-file'. Examples: + /tmp/report.pdf -> /tmp/report-copy.pdf + /home/foo/.bashrc -> /home/foo/.bashrc-copy + doc.txt -> doc-copy.txt + /tmp/archive.tar.gz -> /tmp/archive.tar-copy.gz" + (let* ((dir (file-name-directory file)) + (base (file-name-base file)) + (ext (or (file-name-extension file t) "")) + (new-name (concat base "-copy" ext))) + (if dir + (expand-file-name new-name dir) + new-name))) + (defun cj/dirvish-duplicate-file () - "Duplicate the file at point with '-copy' suffix before the extension. + "Duplicate the file at point with `-copy' suffix before the extension. Examples: report.pdf → report-copy.pdf script.el → script-copy.el README → README-copy" (interactive) - (let* ((file (dired-get-filename nil t)) - (dir (file-name-directory file)) - (base (file-name-base file)) - (ext (file-name-extension file t)) ; includes the dot - (new-name (concat base "-copy" ext)) - (new-path (expand-file-name new-name dir))) + (let ((file (dired-get-filename nil t))) (unless file (user-error "No file at point")) (when (file-directory-p file) (user-error "Cannot duplicate directories, only files")) - - ;; Check if target already exists - (when (file-exists-p new-path) - (unless (y-or-n-p (format "File '%s' already exists. Overwrite? " new-name)) - (user-error "Cancelled"))) - - ;; Copy the file - (copy-file file new-path t) - (revert-buffer) - (message "Duplicated: %s → %s" (file-name-nondirectory file) new-name))) + (let* ((new-path (cj/--duplicate-file-name file)) + (new-name (file-name-nondirectory new-path))) + (when (file-exists-p new-path) + (unless (y-or-n-p (format "File '%s' already exists. Overwrite? " new-name)) + (user-error "Cancelled"))) + (copy-file file new-path t) + (revert-buffer) + (message "Duplicated: %s → %s" + (file-name-nondirectory file) new-name)))) ;;; ----------------------- Dirvish Open File Manager Here ---------------------- -- cgit v1.2.3