diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-01 14:07:26 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-01 14:07:26 -0400 |
| commit | 0e306183e814659798f24573389a46b0d2b8e29a (patch) | |
| tree | 6534ba9b252072b7c571aa91f36d846a33af8201 | |
| parent | f2d3f6c6586ede7f757ca74ea699982562f069a7 (diff) | |
| download | emacs-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.el | 64 | ||||
| -rw-r--r-- | wttrin.el | 28 |
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 @@ -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) |
