summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-20 22:23:29 -0400
committerCraig Jennings <c@cjennings.net>2026-05-20 22:23:29 -0400
commit4ac1b8161f7206592fa3d8efbf7eabb5c51b7bc6 (patch)
treec49ca9f4497ac387ce27794c34fe6a5fef723095
parentfeedb78a517a1e86f6bb467756aa2605c7477223 (diff)
downloaddotemacs-4ac1b8161f7206592fa3d8efbf7eabb5c51b7bc6.tar.gz
dotemacs-4ac1b8161f7206592fa3d8efbf7eabb5c51b7bc6.zip
fix(dashboard): trim padding newlines and reset window-start on open
The dashboard often opened already scrolled: content sat partly above the visible window with empty lines stranded at the bottom. There were two causes. The startupify list inserted five padding newlines that pushed the content past one screenful, and cj/dashboard-only moved point to point-min without resetting window-start, so a previously-scrolled view leaked into the next display. I trimmed the padding to one newline after the banner title and one before the items, and added a set-window-start to point-min in cj/dashboard-only so the view always starts at the top. A characterization test locks the window-start reset.
-rw-r--r--modules/dashboard-config.el13
-rw-r--r--tests/test-dashboard-config.el60
2 files changed, 67 insertions, 6 deletions
diff --git a/modules/dashboard-config.el b/modules/dashboard-config.el
index 93477b48..cb97a076 100644
--- a/modules/dashboard-config.el
+++ b/modules/dashboard-config.el
@@ -60,7 +60,10 @@ Adjust this if the title doesn't appear centered under the banner image.")
;; convenience function to redisplay dashboard and kill all other windows
(defun cj/dashboard-only ()
- "Switch to *dashboard* buffer, kill other buffers and windows, go to top."
+ "Switch to *dashboard* buffer, kill other buffers and windows, go to top.
+Reset `window-start' alongside point so a previously-scrolled view
+doesn't leak into this display when the buffer is taller than the
+window."
(interactive)
(if (get-buffer "*dashboard*")
(progn
@@ -68,7 +71,8 @@ Adjust this if the title doesn't appear centered under the banner image.")
(cj/kill-all-other-buffers-and-windows))
(when (fboundp 'dashboard-open)
(dashboard-open)))
- (goto-char (point-min)))
+ (goto-char (point-min))
+ (set-window-start (selected-window) (point-min)))
;; --------------------------------- Dashboard ---------------------------------
;; a useful startup screen for Emacs
@@ -93,13 +97,10 @@ Adjust this if the title doesn't appear centered under the banner image.")
'(dashboard-insert-banner
dashboard-insert-banner-title
dashboard-insert-newline
- dashboard-insert-newline
dashboard-insert-navigator
;; dashboard-insert-init-info ; Disabled: package count and startup time
dashboard-insert-newline
- dashboard-insert-newline
- dashboard-insert-items
- dashboard-insert-newline))
+ dashboard-insert-items))
:config
;; == general
diff --git a/tests/test-dashboard-config.el b/tests/test-dashboard-config.el
new file mode 100644
index 00000000..2dbcd4f4
--- /dev/null
+++ b/tests/test-dashboard-config.el
@@ -0,0 +1,60 @@
+;;; test-dashboard-config.el --- Tests for dashboard-config -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Exercises `cj/dashboard-only', the F1-bound entry point that displays the
+;; *dashboard* buffer and resets the view to the top. The fix this test
+;; locks in: window-start is forced to point-min, not left wherever a prior
+;; view had scrolled to. Without that, a dashboard buffer taller than the
+;; window opens with content above the visible area.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(add-to-list 'load-path (expand-file-name "tests" user-emacs-directory))
+(setq load-prefer-newer t)
+
+;; Stub package-level deps that dashboard-config pulls transitively.
+(declare-function cj/kill-all-other-buffers-and-windows "undead-buffers")
+(unless (fboundp 'cj/kill-all-other-buffers-and-windows)
+ (defun cj/kill-all-other-buffers-and-windows () nil))
+(unless (fboundp 'cj/make-buffer-undead)
+ (defun cj/make-buffer-undead (_name) nil))
+
+(require 'dashboard-config)
+
+(ert-deftest test-dashboard-only-resets-window-start-to-point-min ()
+ "Normal: `cj/dashboard-only' forces `window-start' to `point-min'.
+
+The dashboard buffer can be taller than the selected window's height
+(banner + 3 navigator rows + sections). A prior call that left the
+window scrolled into the buffer's middle must not leak into the next
+display -- point should land at the top AND the window's view should
+start at the top. Without `set-window-start', batch redisplay leaves
+`window-start' wherever it was set."
+ (let ((dash (get-buffer-create "*dashboard*")))
+ (unwind-protect
+ (progn
+ (with-current-buffer dash
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (insert (make-string 5000 ?x))
+ (insert "\n")))
+ (save-window-excursion
+ (switch-to-buffer dash)
+ (let ((win (selected-window)))
+ ;; Simulate a prior view that scrolled into the middle.
+ (set-window-start win 1000)
+ (should (= (window-start win) 1000))
+ (cl-letf (((symbol-function 'cj/kill-all-other-buffers-and-windows)
+ #'ignore))
+ (cj/dashboard-only))
+ (should (= (window-start win) (point-min)))
+ (should (= (point) (point-min))))))
+ (when (buffer-live-p dash)
+ (kill-buffer dash)))))
+
+(provide 'test-dashboard-config)
+;;; test-dashboard-config.el ends here