aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-01 14:07:26 -0400
committerCraig Jennings <c@cjennings.net>2026-07-01 14:07:26 -0400
commit0e306183e814659798f24573389a46b0d2b8e29a (patch)
tree6534ba9b252072b7c571aa91f36d846a33af8201
parentf2d3f6c6586ede7f757ca74ea699982562f069a7 (diff)
downloademacs-wttrin-0e306183e814659798f24573389a46b0d2b8e29a.tar.gz
emacs-wttrin-0e306183e814659798f24573389a46b0d2b8e29a.zip
fix: center the loading placeholder on an a switch
wttrin-query inserted the "Loading weather for ..." placeholder but never centered it, leaving that to window-configuration-change-hook. On an `a` switch the *wttr.in* buffer is already displayed, so the hook doesn't fire. The placeholder kept the previous weather block's window margin and rendered off-center until the new weather arrived. I moved the placeholder rendering into wttrin--render-loading-placeholder, which centers it explicitly via wttrin--update-layout. It no longer depends on the hook, so the placeholder is centered on the first open and through every switch.
-rw-r--r--tests/test-wttrin--render-loading-placeholder.el64
-rw-r--r--wttrin.el28
2 files changed, 84 insertions, 8 deletions
diff --git a/tests/test-wttrin--render-loading-placeholder.el b/tests/test-wttrin--render-loading-placeholder.el
new file mode 100644
index 0000000..5c27557
--- /dev/null
+++ b/tests/test-wttrin--render-loading-placeholder.el
@@ -0,0 +1,64 @@
+;;; test-wttrin--render-loading-placeholder.el --- Loading placeholder centering -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2026 Craig Jennings
+
+;;; Commentary:
+;; The loading placeholder must be centered every time it is shown, including on
+;; an `a' switch where the *wttr.in* buffer is already displayed. In that case
+;; `window-configuration-change-hook' does not fire, so `wttrin-query' relied on
+;; a stale window margin from the previous weather and the placeholder rendered
+;; off-center. `wttrin--render-loading-placeholder' centers it explicitly.
+
+;;; Code:
+
+(require 'ert)
+(require 'cl-lib)
+(require 'wttrin)
+
+(ert-deftest test-wttrin--render-loading-placeholder-normal-shows-display-name ()
+ "Normal: the placeholder text names the display string, not the raw query."
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'wttrin--update-layout) #'ignore))
+ (wttrin--render-loading-placeholder "1500 Sugar Bowl Dr" "Superdome")
+ (should (string-match-p "Loading weather for Superdome\\.\\.\\."
+ (buffer-string)))
+ (should-not wttrin--weather-rendered))))
+
+(ert-deftest test-wttrin--render-loading-placeholder-boundary-nil-display-uses-query ()
+ "Boundary: with no display name, the placeholder falls back to the query."
+ (with-temp-buffer
+ (cl-letf (((symbol-function 'wttrin--update-layout) #'ignore))
+ (wttrin--render-loading-placeholder "Reykjavik" nil)
+ (should (string-match-p "Loading weather for Reykjavik" (buffer-string))))))
+
+(ert-deftest test-wttrin--render-loading-placeholder-normal-centers-via-layout ()
+ "Normal: rendering the placeholder runs the layout pass, so it is centered by
+the same path weather uses rather than left to the hook (which does not fire on
+a reused, already-displayed buffer)."
+ (with-temp-buffer
+ (let ((layout-calls 0))
+ (cl-letf (((symbol-function 'wttrin--update-layout)
+ (lambda (&rest _) (setq layout-calls (1+ layout-calls)))))
+ (wttrin--render-loading-placeholder "Reykjavik" "Reykjavik")
+ (should (= 1 layout-calls))))))
+
+(ert-deftest test-wttrin--render-loading-placeholder-regression-replaces-stale-margin ()
+ "Regression: a stale window margin left by the previous weather block is
+recomputed for the placeholder, so it no longer renders at the old margin after
+an `a' switch."
+ (let ((buf (get-buffer-create "*wttrin-ph-test*")))
+ (unwind-protect
+ (save-window-excursion
+ (set-window-buffer (selected-window) buf)
+ ;; A wide margin as if left over from a previous (wide) weather block.
+ (set-window-margins (selected-window) 40)
+ (with-current-buffer buf
+ (let ((wttrin-auto-fit-font nil))
+ (wttrin--render-loading-placeholder "Reykjavik" "Reykjavik")
+ ;; The placeholder path must have recomputed the margin, not left
+ ;; the stale 40 in place.
+ (should-not (equal 40 (car (window-margins (selected-window))))))))
+ (kill-buffer buf))))
+
+(provide 'test-wttrin--render-loading-placeholder)
+;;; test-wttrin--render-loading-placeholder.el ends here
diff --git a/wttrin.el b/wttrin.el
index 8bfa74e..dd821b6 100644
--- a/wttrin.el
+++ b/wttrin.el
@@ -1310,6 +1310,25 @@ coordinates but can name the place)."
(defvar-local wttrin--current-request-id nil
"Request id of the most recent query for this weather buffer.")
+(defun wttrin--render-loading-placeholder (query display)
+ "Show the loading placeholder for QUERY in the current buffer.
+DISPLAY is the name to show (a saved-location name); when nil it falls back to
+QUERY. Erases the buffer, inserts the one-line placeholder, resets the font to
+the base height (dropping any auto-fit remap from the previous weather), and
+centers it via `wttrin--update-layout'. The explicit centering matters on an
+`a' switch: the *wttr.in* buffer is already displayed, so
+`window-configuration-change-hook' does not fire and the placeholder would
+otherwise keep the previous weather block's window margin."
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (insert "Loading weather for " (or display query) "..."))
+ (setq buffer-read-only t)
+ ;; The placeholder is one line; keep auto-fit off it (weather not yet rendered)
+ ;; and show it at the base font rather than the previous weather's size.
+ (setq-local wttrin--weather-rendered nil)
+ (wttrin--reset-font-height)
+ (wttrin--update-layout))
+
(defun wttrin-query (query &optional display address)
"Asynchronously query weather for QUERY, display the result when ready.
QUERY is what weather is fetched by (and the cache key). Optional DISPLAY is
@@ -1319,15 +1338,8 @@ coordinates from a geolocation command."
(let ((buffer (get-buffer-create (format "*wttr.in*")))
(request-id (setq wttrin--request-counter (1+ wttrin--request-counter))))
(switch-to-buffer buffer)
- (setq buffer-read-only nil)
- (erase-buffer)
- (insert "Loading weather for " (or display query) "...")
- (setq buffer-read-only t)
(setq-local wttrin--current-request-id request-id)
- ;; The placeholder is one line; keep auto-fit off it and show it at the base
- ;; font rather than the previous weather's auto-fitted (possibly capped) size.
- (setq-local wttrin--weather-rendered nil)
- (wttrin--reset-font-height)
+ (wttrin--render-loading-placeholder query display)
(wttrin--get-cached-or-fetch
query
(lambda (raw-string &optional error-msg)