diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-10 13:31:04 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-10 13:31:04 -0500 |
| commit | 32e57be15a48aa24470e9f3bc6a206c7624bd6b0 (patch) | |
| tree | 02756fd3a3353e509fee2c4c96aa31c68e939b4e | |
| parent | 6545605fa965d649defc0bb01e8c040afbbcc529 (diff) | |
| download | dotemacs-32e57be15a48aa24470e9f3bc6a206c7624bd6b0.tar.gz dotemacs-32e57be15a48aa24470e9f3bc6a206c7624bd6b0.zip | |
refactor(dirvish): extract cj/--file-manager-program-for helper
`cj/dirvish-open-file-manager-here' had its platform-dispatch -- xdg-open / open / explorer / shell fallback -- inline as a four-arm cond branching on `executable-find' and `system-type'. Lift the choice into `cj/--file-manager-program-for', a pure function from (HAS-XDG-OPEN-P SYSTEM-TYPE) to a program-name string or nil. The wrapper resolves the live values, asks the helper, and either calls the program or falls back to a shell-command.
Six Normal/Boundary tests cover the four return shapes (xdg-open across system types, darwin/windows-nt without xdg-open, the nil fallback for plain Linux without xdg-open and for unknown system-types like Haiku).
| -rw-r--r-- | modules/dirvish-config.el | 37 | ||||
| -rw-r--r-- | tests/test-dirvish-config-file-manager-program.el | 54 |
2 files changed, 76 insertions, 15 deletions
diff --git a/modules/dirvish-config.el b/modules/dirvish-config.el index 3fce616e..22d3f07c 100644 --- a/modules/dirvish-config.el +++ b/modules/dirvish-config.el @@ -194,6 +194,21 @@ Examples: ;;; ----------------------- Dirvish Open File Manager Here ---------------------- +(defun cj/--file-manager-program-for (has-xdg-open-p system-type) + "Return the file-manager command for HAS-XDG-OPEN-P + SYSTEM-TYPE, or nil. + +Pure helper used by `cj/dirvish-open-file-manager-here'. When +HAS-XDG-OPEN-P is non-nil, returns \"xdg-open\" regardless of +SYSTEM-TYPE -- xdg-open works on Linux and many ported environments. +Without xdg-open, falls back to `darwin' -> \"open\", `windows-nt' -> +\"explorer\", everything else -> nil so the caller can shell-command +its way out." + (cond + (has-xdg-open-p "xdg-open") + ((eq system-type 'darwin) "open") + ((eq system-type 'windows-nt) "explorer") + (t nil))) + (defun cj/dirvish-open-file-manager-here () "Open system's default file manager in the current dired/dirvish directory. Always opens the file manager in the directory currently being displayed, @@ -203,22 +218,14 @@ regardless of what file or subdirectory the point is on." (if (and current-dir (file-exists-p current-dir)) (progn (message "Opening file manager in %s..." current-dir) - ;; Use shell-command with & to run asynchronously and detached - (let ((process-connection-type nil)) ; Use pipe instead of pty - (cond - ;; Linux/Unix with xdg-open - ((executable-find "xdg-open") - (call-process "xdg-open" nil 0 nil current-dir)) - ;; macOS - ((eq system-type 'darwin) - (call-process "open" nil 0 nil current-dir)) - ;; Windows - ((eq system-type 'windows-nt) - (call-process "explorer" nil 0 nil current-dir)) - ;; Fallback to shell-command - (t + ;; Use pipe instead of pty for the async call-process below. + (let* ((process-connection-type nil) + (program (cj/--file-manager-program-for + (executable-find "xdg-open") system-type))) + (if program + (call-process program nil 0 nil current-dir) (shell-command (format "xdg-open %s &" - (shell-quote-argument current-dir))))))) + (shell-quote-argument current-dir)))))) (message "Could not determine current directory.")))) (defun cj/--wallpaper-program-for (env) diff --git a/tests/test-dirvish-config-file-manager-program.el b/tests/test-dirvish-config-file-manager-program.el new file mode 100644 index 00000000..bfd4cad9 --- /dev/null +++ b/tests/test-dirvish-config-file-manager-program.el @@ -0,0 +1,54 @@ +;;; test-dirvish-config-file-manager-program.el --- Tests for the file-manager dispatch -*- lexical-binding: t; -*- + +;;; Commentary: +;; `cj/--file-manager-program-for' is the pure dispatch behind +;; `cj/dirvish-open-file-manager-here'. Given whether xdg-open is +;; present and the running `system-type', it returns the program name +;; the wrapper should call -- or nil to signal the wrapper should fall +;; back to a shell-command. Keeping `executable-find' and `system-type' +;; outside lets the helper be tested without faking the live machine. + +;;; 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--file-manager-program-for-xdg-open-on-linux () + "Normal: xdg-open present on Linux returns xdg-open." + (should (equal (cj/--file-manager-program-for t 'gnu/linux) + "xdg-open"))) + +(ert-deftest test-cj--file-manager-program-for-xdg-open-wins-on-macos () + "Boundary: xdg-open present even on macOS returns xdg-open (Linux-isms ported)." + (should (equal (cj/--file-manager-program-for t 'darwin) + "xdg-open"))) + +(ert-deftest test-cj--file-manager-program-for-darwin-no-xdg () + "Normal: macOS without xdg-open returns open." + (should (equal (cj/--file-manager-program-for nil 'darwin) + "open"))) + +(ert-deftest test-cj--file-manager-program-for-windows-no-xdg () + "Normal: Windows without xdg-open returns explorer." + (should (equal (cj/--file-manager-program-for nil 'windows-nt) + "explorer"))) + +(ert-deftest test-cj--file-manager-program-for-linux-without-xdg-falls-back () + "Boundary: Linux without xdg-open returns nil so the wrapper shells out." + (should-not (cj/--file-manager-program-for nil 'gnu/linux))) + +(ert-deftest test-cj--file-manager-program-for-unknown-system-falls-back () + "Boundary: an unknown `system-type' with no xdg-open returns nil." + (should-not (cj/--file-manager-program-for nil 'haiku))) + +(provide 'test-dirvish-config-file-manager-program) +;;; test-dirvish-config-file-manager-program.el ends here |
