From 16be44154cf823332332d1df995ae1ed50ff43c4 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Sun, 28 Jun 2026 06:42:00 -0400 Subject: fix: don't auto-fit the loading placeholder to a huge font With auto-fit on, the one-line "Loading..." placeholder was sized to fill the window height (capped huge), and a reused buffer kept the previous weather's auto-fitted font while loading. Auto-fit now runs only once real weather has rendered, and the placeholder resets to the base font. --- tests/test-wttrin--update-layout.el | 39 +++++++++++++++++++++++++++++++++++++ wttrin.el | 29 ++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 tests/test-wttrin--update-layout.el diff --git a/tests/test-wttrin--update-layout.el b/tests/test-wttrin--update-layout.el new file mode 100644 index 0000000..b8df665 --- /dev/null +++ b/tests/test-wttrin--update-layout.el @@ -0,0 +1,39 @@ +;;; test-wttrin--update-layout.el --- Auto-fit gating -*- lexical-binding: t; -*- + +;; Copyright (C) 2024-2026 Craig Jennings + +;;; Commentary: +;; Auto-fit must not size the transient "Loading..." placeholder to fill the +;; window; it runs only once real weather has rendered. + +;;; Code: + +(require 'ert) +(require 'cl-lib) +(require 'wttrin) +(require 'testutil-wttrin) + +(ert-deftest test-wttrin--update-layout-error-skips-fit-on-placeholder () + "Error: with auto-fit on, the loading placeholder (weather not rendered) is +not auto-fitted; the fit runs only after weather renders." + (let ((buf (get-buffer-create "*wttrin-layout-test*")) + (fit-calls 0)) + (unwind-protect + (save-window-excursion + (cl-letf (((symbol-function 'wttrin--apply-fit-font) + (lambda (&rest _) (setq fit-calls (1+ fit-calls)))) + ((symbol-function 'wttrin--center-buffer) #'ignore)) + (with-current-buffer buf (insert "Loading...")) + (set-window-buffer (selected-window) buf) + (with-current-buffer buf + (let ((wttrin-auto-fit-font t)) + (setq-local wttrin--weather-rendered nil) + (wttrin--update-layout) + (should (= 0 fit-calls)) + (setq-local wttrin--weather-rendered t) + (wttrin--update-layout) + (should (= 1 fit-calls)))))) + (kill-buffer buf)))) + +(provide 'test-wttrin--update-layout) +;;; test-wttrin--update-layout.el ends here diff --git a/wttrin.el b/wttrin.el index c0359d9..ef83b45 100644 --- a/wttrin.el +++ b/wttrin.el @@ -927,6 +927,11 @@ When NAME is the favorite, it is left as a literal query with a warning." (defvar-local wttrin--current-font-height nil "The font height (1/10 pt) currently applied via `wttrin--face-remap-cookie'.") +(defvar-local wttrin--weather-rendered nil + "Non-nil once real weather has rendered in this buffer. +Auto-fit keys on this so the transient \"Loading...\" placeholder is not sized +to fill the window.") + (define-derived-mode wttrin-mode special-mode "Wttrin" "Major mode for displaying wttr.in weather information. @@ -1148,13 +1153,28 @@ height is unchanged." :height height)) (setq wttrin--current-font-height height)))) +(defun wttrin--reset-font-height () + "Re-apply the base `wttrin-font-height', discarding any auto-fit remap. +Used for the loading placeholder so it shows at the base size rather than the +previous weather's auto-fitted (possibly capped) height. No-op when the buffer +has no remap cookie yet." + (when wttrin--face-remap-cookie + (face-remap-remove-relative wttrin--face-remap-cookie) + (setq wttrin--face-remap-cookie + (face-remap-add-relative 'default + :family wttrin-font-name + :height wttrin-font-height)) + (setq wttrin--current-font-height wttrin-font-height))) + (defun wttrin--update-layout (&rest _) "Auto-fit the font (when enabled), then center the block in the buffer's window. +Auto-fit runs only once real weather has rendered (`wttrin--weather-rendered'), +so the one-line \"Loading...\" placeholder is not sized to fill the window. Accepts and ignores hook arguments, so it is safe on `window-configuration-change-hook'. No-op when the buffer has no window." (let ((win (get-buffer-window (current-buffer)))) (when win - (when wttrin-auto-fit-font + (when (and wttrin-auto-fit-font wttrin--weather-rendered) (wttrin--apply-fit-font win)) (wttrin--center-buffer win)))) @@ -1207,6 +1227,9 @@ coordinates but can name the place)." (wttrin--add-buffer-instructions) (goto-char (point-min))) + ;; Real weather is now in the buffer, so auto-fit may size to it. + (setq-local wttrin--weather-rendered t) + ;; Anchor the window to the top. Point is at point-min, but when the ;; buffer is taller than the window a reused window can keep an old ;; mid-buffer window-start, hiding the weather above the fold. @@ -1240,6 +1263,10 @@ coordinates from a geolocation command." (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--get-cached-or-fetch query (lambda (raw-string &optional error-msg) -- cgit v1.2.3