aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-15 21:48:10 -0500
committerCraig Jennings <c@cjennings.net>2026-06-15 21:48:10 -0500
commit12fad985f6e08b4544521844ba6968ee2c1b6526 (patch)
tree82a9455bfcb1ccfccda72f159803d8b82df64e81
parentde32ffbe0d501f9dc61bc3a8889df3e207459535 (diff)
downloaddotemacs-12fad985f6e08b4544521844ba6968ee2c1b6526.tar.gz
dotemacs-12fad985f6e08b4544521844ba6968ee2c1b6526.zip
feat(ui-navigation): C-x 2/3 show the dashboard in the new window
Splitting with C-x 2 or C-x 3 now shows *dashboard* in the freshly created window and keeps point in the original, instead of mirroring the current buffer. cj/--split-show-buffer does the placement; cj/--dashboard-buffer fetches or opens the dashboard without disturbing windows.
-rw-r--r--modules/ui-navigation.el28
-rw-r--r--tests/test-ui-navigation--split-dashboard.el69
2 files changed, 97 insertions, 0 deletions
diff --git a/modules/ui-navigation.el b/modules/ui-navigation.el
index f2181d97e..fba9153c2 100644
--- a/modules/ui-navigation.el
+++ b/modules/ui-navigation.el
@@ -103,6 +103,34 @@ nudging until any other key. Bound to `C-; b <left>/<right>/<up>/<down>'."
(consult-buffer))
(keymap-global-set "M-S-h" #'cj/split-and-follow-below) ;; was M-H
+(defun cj/--dashboard-buffer ()
+ "Return the *dashboard* buffer, creating it if needed, without changing windows."
+ (or (get-buffer "*dashboard*")
+ (save-window-excursion
+ (when (fboundp 'dashboard-open) (dashboard-open))
+ (get-buffer "*dashboard*"))))
+
+(defun cj/--split-show-buffer (split-fn buffer)
+ "Split with SPLIT-FN, show BUFFER in the new window, keep point in the current
+window. Return the new window."
+ (let ((new (funcall split-fn)))
+ (when (and (window-live-p new) buffer)
+ (set-window-buffer new buffer))
+ new))
+
+(defun cj/split-below-with-dashboard ()
+ "Split below and show the dashboard in the new window; stay in this one."
+ (interactive)
+ (cj/--split-show-buffer #'split-window-below (cj/--dashboard-buffer)))
+
+(defun cj/split-right-with-dashboard ()
+ "Split right and show the dashboard in the new window; stay in this one."
+ (interactive)
+ (cj/--split-show-buffer #'split-window-right (cj/--dashboard-buffer)))
+
+(keymap-global-set "C-x 2" #'cj/split-below-with-dashboard)
+(keymap-global-set "C-x 3" #'cj/split-right-with-dashboard)
+
;; ------------------------- Split Window Reorientation ------------------------
(defun toggle-window-split ()
diff --git a/tests/test-ui-navigation--split-dashboard.el b/tests/test-ui-navigation--split-dashboard.el
new file mode 100644
index 000000000..b815a4c59
--- /dev/null
+++ b/tests/test-ui-navigation--split-dashboard.el
@@ -0,0 +1,69 @@
+;;; test-ui-navigation--split-dashboard.el --- Tests for split-with-dashboard -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; C-x 2 / C-x 3 split and show the *dashboard* in the new window while point
+;; stays in the original. cj/--split-show-buffer does the placement;
+;; cj/split-below/right-with-dashboard wire it to the two split directions.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'ui-navigation)
+
+(ert-deftest test-ui-navigation-split-dashboard-keybindings ()
+ "Normal: C-x 2 / C-x 3 are bound to the dashboard-split commands."
+ (should (eq (key-binding (kbd "C-x 2")) #'cj/split-below-with-dashboard))
+ (should (eq (key-binding (kbd "C-x 3")) #'cj/split-right-with-dashboard)))
+
+(ert-deftest test-ui-navigation-split-show-buffer-displays-and-keeps-point ()
+ "Normal: the new window shows the buffer; the original stays selected."
+ (let ((buf (get-buffer-create " *split-dash-test*"))
+ (config (current-window-configuration)))
+ (unwind-protect
+ (progn
+ (delete-other-windows)
+ (let* ((orig (selected-window))
+ (new (cj/--split-show-buffer #'split-window-below buf)))
+ (should (window-live-p new))
+ (should (not (eq new orig)))
+ (should (eq (window-buffer new) buf))
+ (should (eq (selected-window) orig)))) ; point stays put
+ (set-window-configuration config)
+ (kill-buffer buf))))
+
+(ert-deftest test-ui-navigation-split-below-routes-to-split-window-below ()
+ "Normal: cj/split-below-with-dashboard splits below with the dashboard buffer."
+ (let (captured)
+ (cl-letf (((symbol-function 'cj/--dashboard-buffer) (lambda () 'dashboard))
+ ((symbol-function 'cj/--split-show-buffer)
+ (lambda (fn buf) (setq captured (list fn buf)) nil)))
+ (cj/split-below-with-dashboard))
+ (should (eq (car captured) #'split-window-below))
+ (should (eq (cadr captured) 'dashboard))))
+
+(ert-deftest test-ui-navigation-split-right-routes-to-split-window-right ()
+ "Normal: cj/split-right-with-dashboard splits right with the dashboard buffer."
+ (let (captured)
+ (cl-letf (((symbol-function 'cj/--dashboard-buffer) (lambda () 'dashboard))
+ ((symbol-function 'cj/--split-show-buffer)
+ (lambda (fn buf) (setq captured (list fn buf)) nil)))
+ (cj/split-right-with-dashboard))
+ (should (eq (car captured) #'split-window-right))
+ (should (eq (cadr captured) 'dashboard))))
+
+(ert-deftest test-ui-navigation-dashboard-buffer-returns-existing ()
+ "Boundary: cj/--dashboard-buffer returns an existing *dashboard* without opening."
+ (let ((db (get-buffer-create "*dashboard*"))
+ (opened nil))
+ (unwind-protect
+ (cl-letf (((symbol-function 'dashboard-open)
+ (lambda (&rest _) (setq opened t))))
+ (should (eq (cj/--dashboard-buffer) db))
+ (should-not opened))
+ (kill-buffer db))))
+
+(provide 'test-ui-navigation--split-dashboard)
+;;; test-ui-navigation--split-dashboard.el ends here