diff options
| author | Craig Jennings <c@cjennings.net> | 2026-04-26 18:29:27 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-04-26 18:29:27 -0500 |
| commit | eabd510c302b43b0b40ee7b92bf5830d345d058d (patch) | |
| tree | 31a73830e61e14850343a024558610088343bbd1 | |
| parent | fe653a231b186393b02a2723985e61ce97baba1c (diff) | |
| download | emacs-wttrin-eabd510c302b43b0b40ee7b92bf5830d345d058d.tar.gz emacs-wttrin-eabd510c302b43b0b40ee7b92bf5830d345d058d.zip | |
refactor: extract wttrin--mode-line-stale-p helper
The staleness check `(> age (* 2 wttrin-mode-line-refresh-interval))` lived in two places, `wttrin--mode-line-tooltip` and `wttrin--mode-line-update-display`, along with the four-line preamble that read the timestamp out of the cache cons and computed age. Centralizing the rule in a single helper means the threshold lives in one spot. That makes it easy to add a `wttrin-mode-line-staleness-threshold` defcustom later if the magic 2× ever needs to be tunable.
The helper takes a cache entry (or nil) and returns t/nil. Five new tests cover Normal (fresh, stale) and Boundary (just below the threshold, just past, nil entry). The boundary tests use 199s and 201s against a 100s refresh interval to lock the strict `>` semantics with comfortable float-time margins.
In `wttrin--mode-line-update-display` the refactor also drops two locals (`timestamp` and `age`) that were no longer used after the helper call replaced the inline calculation. Behavior is unchanged at both call sites.
| -rw-r--r-- | tests/test-wttrin--mode-line-helpers.el | 36 | ||||
| -rw-r--r-- | wttrin.el | 18 |
2 files changed, 49 insertions, 5 deletions
diff --git a/tests/test-wttrin--mode-line-helpers.el b/tests/test-wttrin--mode-line-helpers.el index 34523a8..6eae822 100644 --- a/tests/test-wttrin--mode-line-helpers.el +++ b/tests/test-wttrin--mode-line-helpers.el @@ -135,5 +135,41 @@ distinguish a missing key from a present key bound to nil." 'mode-line-highlight))) (test-wttrin--mode-line-helpers-teardown))) +;;; -------------------------------------------------------------------------- +;;; wttrin--mode-line-stale-p +;;; -------------------------------------------------------------------------- + +;;; Normal Cases + +(ert-deftest test-wttrin--mode-line-stale-p-normal-fresh-cache-returns-nil () + "Cache entry well within the refresh window is not stale." + (let ((wttrin-mode-line-refresh-interval 100)) + (let ((entry (cons (- (float-time) 50) "data"))) + (should-not (wttrin--mode-line-stale-p entry))))) + +(ert-deftest test-wttrin--mode-line-stale-p-normal-stale-cache-returns-t () + "Cache entry older than 2× refresh-interval is stale." + (let ((wttrin-mode-line-refresh-interval 100)) + (let ((entry (cons (- (float-time) 500) "data"))) + (should (wttrin--mode-line-stale-p entry))))) + +;;; Boundary Cases + +(ert-deftest test-wttrin--mode-line-stale-p-boundary-just-below-threshold () + "Age 1s below the 2× threshold is not stale (strict >)." + (let ((wttrin-mode-line-refresh-interval 100)) + (let ((entry (cons (- (float-time) 199) "data"))) + (should-not (wttrin--mode-line-stale-p entry))))) + +(ert-deftest test-wttrin--mode-line-stale-p-boundary-just-past-threshold () + "Age 1s past the 2× threshold is stale." + (let ((wttrin-mode-line-refresh-interval 100)) + (let ((entry (cons (- (float-time) 201) "data"))) + (should (wttrin--mode-line-stale-p entry))))) + +(ert-deftest test-wttrin--mode-line-stale-p-boundary-nil-cache-returns-nil () + "Nil cache-entry returns nil with no signal." + (should-not (wttrin--mode-line-stale-p nil))) + (provide 'test-wttrin--mode-line-helpers) ;;; test-wttrin--mode-line-helpers.el ends here @@ -676,6 +676,16 @@ On failure with no cache, shows error placeholder." ;; No cache at all — show error placeholder (wttrin--mode-line-update-placeholder-error)))))))) +(defun wttrin--mode-line-stale-p (cache-entry) + "Return non-nil if CACHE-ENTRY is stale. +Stale means age greater than 2 × `wttrin-mode-line-refresh-interval'. +CACHE-ENTRY is a (TIMESTAMP . WEATHER-STRING) cons or nil. A nil +entry returns nil so callers can pass `wttrin--mode-line-cache' directly +without a separate guard." + (when cache-entry + (let ((age (- (float-time) (car cache-entry)))) + (> age (* 2 wttrin-mode-line-refresh-interval))))) + (defun wttrin--mode-line-tooltip (&optional _window _object _pos) "Compute tooltip text from `wttrin--mode-line-cache'. Calculates age at call time so the tooltip is always current. @@ -686,7 +696,7 @@ Optional arguments are ignored (required by `help-echo' function protocol)." (let* ((timestamp (car wttrin--mode-line-cache)) (weather-string (cdr wttrin--mode-line-cache)) (age (- (float-time) timestamp)) - (stale-p (> age (* 2 wttrin-mode-line-refresh-interval))) + (stale-p (wttrin--mode-line-stale-p wttrin--mode-line-cache)) (age-str (wttrin--format-age age))) ;; Re-render emoji if staleness state has changed (unless (eq stale-p wttrin--mode-line-rendered-stale) @@ -702,10 +712,8 @@ Reads cached weather data, computes age, and sets the mode-line string. If data is stale (age > 2x refresh interval), dims the emoji and shows staleness info in tooltip." (when wttrin--mode-line-cache - (let* ((timestamp (car wttrin--mode-line-cache)) - (weather-string (cdr wttrin--mode-line-cache)) - (age (- (float-time) timestamp)) - (stale-p (> age (* 2 wttrin-mode-line-refresh-interval)))) + (let* ((weather-string (cdr wttrin--mode-line-cache)) + (stale-p (wttrin--mode-line-stale-p wttrin--mode-line-cache))) (wttrin--debug-log "mode-line-display: Updating from cache, stale=%s" stale-p) ;; Response format is "Location: ☀️ +72°F Clear" — grab first char after colon (let ((emoji (if (string-match ":\\s-*\\(.\\)" weather-string) |
