| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
| |
savehist rewrites its whole file on every save, keeping only the variables registered in the running process. Any Emacs that saved savehist without wttrin loaded (a batch tool, a session that never opened wttrin) silently deleted the persisted favorite and saved-location entries. A d-set default then reverted to the init value on the next restart.
The runtime favorite and directory now live in wttrin-state-file, written only by wttrin: write-through on every location command, atomic temp-file + rename, UTF-8 pinned both ways, read with read (never eval), versioned plist. Values restore at load and re-assert on savehist-mode-hook, so a stale legacy savehist restore can't clobber them. With no state file present, legacy savehist values are adopted and written once, so existing users migrate with zero steps. Search history stays on savehist. It's scrub-tolerant throwaway data, exactly what savehist is for.
Also: the README documents the mode-line tooltip forecast option, and the gitignore covers one more local tooling artifact.
|
| |
|
|
| |
The tooltip showed current conditions only. I added wttrin-mode-line-tooltip-forecast-days (default 0, capped at wttr.in's three days). When positive, the mode-line refresh also fetches ?format=j1 and caches the parsed day list, and the tooltip renders one line per day between the conditions and the age line: Today / Tomorrow / weekday label, min-max temps in the configured unit, and the midday description. A failed or malformed forecast fetch keeps the previous forecast and never disturbs the main fetch.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
wttrin-favorite-location did two jobs: a defcustom the user sets in init, and the savehist-persisted value that `d`/make-default mutated. Setting it in init (setopt) clobbered the `d` choice on every startup. So a favorite promoted with `d` reverted to the init value after a restart, and the mode-line showed the wrong location's weather. wttrin-saved-locations had the same defect.
I split the two roles. The defcustoms stay as the init-set base. New savehist-persisted runtime vars, wttrin--favorite-override and wttrin--saved-locations-runtime, hold what `d`, save, rename, remove, and the geolocation commands write. Reads go through resolvers: wttrin--favorite-location returns the override or the configured favorite, and wttrin--saved-locations overlays the runtime directory on the configured one (runtime wins on a name collision). Init and `d` now write different variables, so neither clobbers the other.
Removing a saved location that only comes from init can't delete it, since the runtime removal has nothing to touch. The command now says so instead of reporting a removal that didn't happen.
There's no automatic migration. A favorite set in init is unaffected, and a favorite set only with `d` before this version is re-set once with `d`. The README documents the behavior.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
wttrin--display-weather ran switch-to-buffer from the async callback, so a
response arriving after the user moved to another buffer yanked them back to
*wttr.in*. It now renders with set-buffer; selecting the buffer is the
interactive command's job (wttrin-query already does it at invocation), so a
late response updates the buffer in place without changing the selected window.
|
| |
|
|
|
|
|
| |
wttrin-query reuses the single *wttr.in* buffer, so requesting Paris then Berlin
and having Paris return last overwrote the Berlin buffer. Each query now stamps
a monotonic request id on the buffer; the callback displays only when its
captured id still matches, so a superseded response is ignored.
|
| |
|
|
|
|
|
|
|
| |
The delayed initial fetch was scheduled with run-at-time but the one-shot timer
was discarded, and when the mode is enabled before after-init the start is
queued on after-init-hook. Disabling the mode before either fired could still
start timers, hit the network, or mutate mode-line state after the user turned
it off. Stop now cancels the stored startup timer and removes the after-init
hook, and the startup callback no-ops when the mode is off.
|
| |
|
|
|
|
| |
wttrin--cleanup-cache-if-needed removed floor(count * 0.20) entries, which is 0
for a small cache (e.g. two entries at max one), so the cache could sit over its
advertised maximum indefinitely. It now removes at least one whenever it is over.
|
| |
|
|
|
|
|
|
|
|
|
| |
wttrin--make-cache-key keyed only on location and unit system, but the request
body also depends on wttrin-display-options and wttrin-default-languages.
Changing display options or language mid-session served the old cached response,
and the staleness header then claimed it was current for the new settings. The
key now includes every setting that shapes the response.
Cache-key tests rewritten to assert behavior (distinct key per varying setting,
stable key for identical settings) instead of an exact key string.
|
| |
|
|
|
| |
wttrin.el calls string-trim throughout but never required subr-x, so a clean
load could hit a void-function before something else pulled subr-x in.
|
| |
|
|
|
| |
Drop the "games" keyword (it miscategorizes a weather tool) from wttrin.el and
Eask. Sync wttrin-geolocation.el's version to 0.3.2 to match the main module.
|
| |
|
|
|
| |
The list mixed tabs and spaces. Aligned every entry on spaces, no behavior
change.
|
| |
|
|
|
|
|
|
| |
Pull the eight-condition validity check in wttrin--fit-font-height into
wttrin--fit-inputs-usable-p, so the arithmetic branch reads as one line.
Reword wttrin--center-margin's docstring, which still said "column counts"
after the pixel-based centering rewrite started passing it pixels.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Centering and auto-fit share one resize hook (wttrin--update-layout on
window-configuration-change-hook).
Centering is always on. The block centers via the window's left margin,
measured in pixels from the buffer font so it stays exact under a font-height
remap. It centers against the available width including the current margin, so
the margin shrinking the body can't make the value oscillate.
Auto-fit is opt-in (wttrin-auto-fit-font, off by default). When on, the font is
sized so the whole buffer fits top to bottom (down to the row past the footer's
last menu item) without the widest line truncating, clamped to
wttrin-font-height-min and -max.
The pixel-exact measurement needs window-font-width and window-font-height, so
the minimum is now Emacs 25.1.
|
| |
|
|
| |
Making a location the default saved it and dropped the favorite name from history, but not the underlying query. For an alias whose query differs from its name, that query lingered as a separate history candidate. Both saving branches now drop the name and the query, matching wttrin-save-location.
|
| |
|
|
|
|
| |
Pressing d cleaned the location from history, but saving with s did not. A place saved under a friendly name kept its raw query as a separate history candidate, and removing the saved entry let that query resurface in the picker.
wttrin-save-location now drops the saved name and its query from history, and wttrin-remove-location drops both the removed name and its query (captured before removal). A new wttrin--drop-from-location-history helper does the work. A place now lives in the directory or in history, never both.
|
| |
|
|
|
|
| |
Pressing d on a typed or aliased location set the favorite but never added it to wttrin-saved-locations, so the default persisted only as the favorite string, not as a named directory entry. The coordinate branch already saved. The typed/alias branch did not.
The typed/alias branch now puts the location into the directory before promoting it, so a typed default like "Reykjavik" persists as a ("Reykjavik" . "Reykjavik") entry. An empty-name coordinate detection still keeps the raw coordinates without saving an entry.
|
| | |
|
| |
|
|
|
|
|
|
| |
A saved location carries a display name distinct from its query target ("Mom's House" maps to coordinates or an address), stored in a savehist-persisted wttrin-saved-locations alist. The name shows everywhere the place appears (picker, buffer header, mode-line tooltip) while wttr.in is still queried by the target.
Management commands wttrin-save-location, wttrin-rename-location, and wttrin-remove-location edit the directory, with refuse-on-collision rename and a favorite-fallback warning on remove. In the weather buffer, s/r/x reach those commands and d names a detected location before promoting it to the default. The footer is two columns: a "This view" column (another, refresh, quit) and a "Saved locations" column (save, make default, rename, remove). The buffer anchors to the top so the forecast isn't scrolled out of view in a short window.
The mode-line follows favorite changes immediately rather than waiting for the next scheduled fetch, and its hover tooltip shows the saved name instead of the raw query. History holds named entries only: raw coordinate detections and saved names stay out of it.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
These build on the current-location picker with the rest of the geolocation work.
wttrin-geolocation-command runs a command that prints {lat,lng} (and optionally an address) and queries wttr.in by those coordinates. IP geolocation only finds the network's exit point, which is wrong on a VPN or hotspot. A command that scans nearby WiFi resolves to street level. It runs asynchronously, falls back to the IP provider when unset or failing, and assumes nothing about the OS, so it's inert until set. When the command returns an address, wttrin shows it on a "Location:" line, so the resolved place is readable even though the fetch is by raw coordinates.
wttrin-use-current-location is a labeled command that sets the favorite to auto-detect, so the bare t value never has to be typed into init by hand.
wttrin-geolocation-enabled (default t) turns every geolocation surface off for anyone who wants that: the picker entry, the auto-detect favorite, and the command.
examples/geolocation/ ships two reference adapters for the command: google-geolocate.py (Google API, key via the environment or ~/.authinfo.gpg) and apple-wps.py (Apple's keyless WiFi positioning, which uses an undocumented endpoint, so read its caveat). Both are Python 3 standard library and scan via nmcli, with notes on adapting the scan to other systems.
|
| |
|
|
|
|
|
|
|
|
| |
Geolocation used to live in a separate command, so getting weather for where you are meant knowing a second command existed. I added a "Current location (detect)" entry pinned to the top of the M-x wttrin picker. Selecting it detects your location and shows its weather. If the guess is wrong (VPN, hotspot) the detected city is visible in the header, so you reopen the picker and type one. Press d to keep the detected city as the default.
The entry is pinned first through a completion table whose display-sort-function holds against completion frameworks that re-sort, and it never enters location history or the cache as a place.
A new wttrin-geolocation-enabled (default t) turns every geolocation surface off for users who want that: the picker entry, the auto-detect favorite, and the command. It stays on by default.
The older wttrin-set-location-from-geolocation command is now obsolete in favor of the picker. Its customize-save-variable persistence advice is replaced by savehist, which already carries the favorite across sessions.
|
| |
|
|
|
|
| |
Pressing d to promote a displayed location to the favorite changed wttrin-favorite-location but left the mode-line untouched. Its cache still held the old location's weather. The next scheduled refetch could be up to an hour away, so the hover tooltip kept showing the previous default.
wttrin--set-favorite-location now detects a real change and, when the mode-line is active, clears the stale cache and fetches the new location at once via a new wttrin--mode-line-refresh-now helper. The tooltip switches within seconds instead of waiting for the timer.
|
| |
|
|
|
|
|
|
|
|
| |
I bound d in the weather buffer to wttrin-make-default, which sets wttrin-favorite-location to the location on screen so it drives the mode-line and future sessions. The footer advertises "[d] to make default".
Persistence rides savehist, not the Emacs custom-variable mechanism: wttrin--savehist-register registers wttrin-favorite-location alongside the search history, at load and on savehist-save-hook. Enable savehist-mode and the favorite survives restarts.
Promoting a location drops it from the search history, the way wttrin-default-locations entries are kept out of history. The favorite shows in the picker instead: wttrin--completion-candidates prepends it when it's a string and not already a default, so it appears exactly once.
The setter only assigns the variable and trims history. It doesn't register with savehist itself, because savehist-additional-variables is unbound until savehist loads, so a direct add-to-list would error for users without savehist. Registration stays on the load and save-hook path.
|
| |
|
|
|
|
|
|
|
|
| |
I added four customizable faces so themes and customize-face can restyle the text wttrin draws itself: wttrin-mode-line-stale (the dimmed stale mode-line emoji), wttrin-staleness-header (the "Last updated:" line), wttrin-instructions (the footer prose), and wttrin-key (the [a]/[g]/[q] chords).
The package exposed no faces before and hardcoded one color. The stale-emoji dimming used a literal "gray60". Now it inherits a face, so the color tracks the theme. I changed make-emoji-icon's second argument from a color string to a face symbol applied via :inherit.
wttrin-key inherits bold rather than help-key-binding, which is Emacs 28+ while the package supports 24.4.
The weather ASCII art stays colored by xterm-color's ANSI faces. Only the package's own text is newly faced.
|
| |
|
|
|
|
|
|
| |
A one-time add-to-list put wttrin--location-history into savehist-additional-variables when savehist loaded. Any user who later setqs that list, a common config pattern for curating which histories persist, replaces it and drops the entry. The search history then silently never saves.
Re-assert the registration on savehist-save-hook, which runs at the top of every savehist-save. The variable is now in the list whenever a save happens, regardless of init order or a clobbering setq. Restore was never affected, since savehist reloads the value from explicit setq forms in its file.
The README persistence note now reflects this: the variable stays registered even if you set savehist-additional-variables yourself.
|
| |
|
|
|
|
|
|
|
|
| |
Successful searches are now remembered and offered as completion candidates the next time you run wttrin, listed after the configured defaults. Only successful fetches are saved, so typos and not-found locations never enter the history. A location already in wttrin-default-locations isn't duplicated into it. The list is capped at wttrin-location-history-max (default 20), oldest entries falling off first.
Persistence uses savehist: the history variable is registered with savehist-additional-variables, so enabling savehist-mode carries it across restarts with no custom file I/O. Without savehist it lasts the session.
Two commands manage the list: wttrin-remove-location-history drops one entry, wttrin-clear-location-history clears all.
I don't pass the history variable as the completing-read history argument, because the minibuffer would then save every typed string, including failed lookups. It stays a curated candidate source, updated only on success. I trim with butlast rather than seq-take to keep the Emacs 24.4 baseline.
|
| |
|
|
|
|
|
|
|
|
| |
Define a wttrin-error condition with children wttrin-invalid-input, wttrin-network-error, wttrin-not-found-error, wttrin-service-error, and wttrin-parse-error, so callers branch on the class of a failure instead of matching message text.
Synchronous paths signal these directly: a nil query and an unknown geolocation provider now raise wttrin-invalid-input. The async fetch path can't signal across its callback, so it tags the error string with the class via a wttrin-error-type text property. The wttrin-error-message-type accessor reads it back, and two-arg callbacks are untouched.
Retyping the classifier also closed two gaps: a missing status and a 2xx with an empty body used to go silent or get mislabeled "Unexpected HTTP status". Both are now parse errors.
wttrin-geolocation.el now requires wttrin for the shared conditions. It's only ever loaded through wttrin, so the require is a no-op in practice and just makes the dependency explicit.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Completes the three-mode configuration the favorite-location feature was always meant to have:
- nil — disabled (default; unchanged)
- a string — explicit location (unchanged)
- t — auto-detect via IP geolocation (NEW)
When the user sets `wttrin-favorite-location` to t, wttrin runs the geolocation lookup once on first use and caches the result for the session. Subsequent reads return the cached string. The lookup happens in the background via the existing `wttrin-geolocation-detect`, so Emacs startup is never blocked.
I added two private state vars (`wttrin--resolved-favorite-location`, `wttrin--favorite-location-pending`) and a resolver `wttrin--resolve-favorite-location` that maps the three modes onto a returned string or nil. When t is set and the cache is empty, the resolver kicks off the lookup and returns nil for that call — the next consumer tick after the callback completes gets the cached string. The pending flag prevents duplicate concurrent lookups when several consumers ask during the resolution window.
Five consumer call sites now go through the resolver instead of reading `wttrin-favorite-location` directly: `wttrin--mode-line-fetch-weather`, `wttrin-mode-line-click`, `wttrin-mode-line-force-refresh`, `wttrin--buffer-cache-refresh`, and `wttrin--mode-line-start`. Two display sites (the placeholder and error tooltips) use a new `wttrin--favorite-location-display-name` helper that returns "current location" while a t-mode lookup is pending, instead of showing the literal `t` to the user.
Tests cover the resolver across all three modes, including the pending state, the duplicate-suppression behavior, and detection-failure retry. Existing consumer tests stay green because the resolver returns the bound string unchanged when the variable is a string. One care: the test file requires wttrin-geolocation up front so cl-letf mocks of `wttrin-geolocation-detect` aren't undone by the resolver's lazy require — without that, the first run hit ipapi.co for real.
README documents the new mode under "Setting the Favorite Location from IP Geolocation".
|
| |
|
|
|
|
|
|
|
|
|
|
| |
wttr.in accepts single-character flags appended to the URL that control what the report looks like — no Follow line (F), narrow output (n), quiet mode (q), forecast horizon (0/1/2), console-glyph mode (d), and so on. Until now wttrin always used the same default report shape with no way to opt into these.
Added a `wttrin-display-options` defcustom that takes a string of concatenated flags, e.g. "0Fq" for current weather only with no Follow line and no header. The flags get appended to every request via `wttrin--build-url`. The defcustom defaults to nil so existing users see no change.
I excluded `A` and `T` from the recommended set in the docstring since wttrin needs ANSI output for the xterm-color rendering to produce the colored glyphs. The user could still pass them, but the docstring nudges them away.
Tests cover the normal cases (single, multi-flag, with and without unit system), the boundaries (nil and empty string both leave the URL unchanged from baseline, single character works), and a sanity check that the new flags slot in after the always-on `A`. Existing build-url tests stay green because they don't bind the new variable, and the default is nil.
Also added `.claude/` to .gitignore — the scheduled-tasks lockfile from local wakeup scheduling shouldn't be tracked.
|
| |
|
|
|
|
| |
Four variables hold the mode-line's runtime state: the cache, the rendered string, the stale-render flag, and the refresh timer. They get updated in a specific order across three different functions. Anyone reading `wttrin--mode-line-tooltip` for the first time hits a clever bit on every hover: the tooltip re-evaluates staleness and triggers a re-render of the icon if it flipped. Without a comment that ties this to the rest of the update flow, you have to trace through three other functions to understand why.
The new comment block above the defvars lays out the order and the hover-driven re-render in one place, so future readers don't have to reconstruct it from the call graph.
|
| |
|
|
|
|
|
|
| |
The regex that pulls the emoji character out of a wttr.in mode-line response was inlined inside `wttrin--mode-line-update-display`, mixed in with the render logic. Six tests of the parser couldn't be written without invoking the whole render path.
The new pure helper takes the weather string, runs the regex, and returns either the first non-whitespace character after the colon or "?" as a placeholder. The format-explanation comment that used to sit above the inline code is gone now that the same explanation lives in the helper's docstring. There's no risk of comment and code drifting apart.
Six tests cover Normal (typical response, different emoji), Boundary (no whitespace after colon, multiple whitespace chars), and Error (no colon, empty string).
|
| |
|
|
|
|
|
|
| |
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.
|
| | |
|
| |
|
|
|
|
| |
The font branch of wttrin--make-emoji-icon built its face plist with `:foreground foreground` even when foreground was nil, producing a literal `(:family ... :height 1.0 :foreground nil)`. The mode-line redisplays many times per second, and Emacs validates faces on every redisplay. A single fresh-cache state produced hundreds of "Invalid face attribute :foreground nil" warnings in *Messages*. The bug's been live since 2026-02-21 (b74b98f). The 130bbc07 helper extraction kept it in place.
Switch to backquote splicing so the :foreground key is included only when foreground is non-nil. Behavior is identical on the colored path. On the nil path the emoji renders with the default mode-line color, the same visible result as before, without the warning flood.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Lets users set `wttrin-favorite-location` by IP lookup instead of typing a city by hand. `M-x wttrin-set-location-from-geolocation` runs the lookup, shows the detected "City, Region" in a yes/no prompt, and on confirmation sets the variable for the session. The docstring points at `M-x customize-save-variable` for persistence across restarts.
The new `wttrin-geolocation.el` module provides the provider layer. Three providers come built in: ipapi.co (the default), ipinfo.io, and ipwho.is. All three are HTTPS, need no API key, and have free tiers large enough for interactive use. The module has three layers. Pure JSON parsers handle the per-provider quirks: ipapi's `error: true` flag, ipwho.is's `success: false` flag, ipinfo's HTTP-status-only signalling. A small fetch helper extracts the HTTP body. `wttrin-geolocation-detect` wires them together and calls back with "City, Region" on success, or nil on any failure (network error, HTTP 4xx or 5xx, malformed response, rate-limit signal).
Providers live in an alist keyed by symbol, with plist values for :name, :url, and :parser. To use a different provider, push an entry onto `wttrin-geolocation--providers` and select it via `wttrin-geolocation-provider`. No code change needed.
README gains a subsection under Mode-line Weather Display covering the command, how to persist the result, provider selection with free-tier limits, and the accuracy caveat for VPN or mobile-hotspot users.
39 new tests across the parser layer (10 ipapi, 6 ipinfo, 6 ipwhois), fetch-and-dispatch (11), and interactive command (6). Each suite covers Normal, Boundary, and Error categories. Tests mock `url-retrieve` and `yes-or-no-p` at their boundaries and run the real extract-and-parse pipeline underneath. Test suite: 333 → 373 passing.
|
| | |
|
| |
|
|
|
| |
Enable truncate-lines in wttrin-mode so the fixed-width weather art
clips at the window edge instead of wrapping and breaking the layout.
|
| |
|
|
|
|
| |
wttr.in returns "Weather report: new orleans, la" regardless of
query casing. Replace the lowercase location on the header line
with the user's original string after rendering.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add HTTP status code checking (wttrin--extract-http-status) and pass
error descriptions through the callback chain so users see "Location
not found (HTTP 404)" or "Network error — check your connection"
instead of the generic "Perhaps the location was misspelled?" for
every failure.
Also fix pre-existing bug where the condition-case error handler in
extract-response-body killed an unrelated buffer after unwind-protect
already cleaned up.
330 tests (was 307), all passing.
|
| |
|
|
|
|
| |
Dynamic mode-line tooltip, staleness dimming, location casing fix,
debug guard refactor, expanded test suite (307 tests), and multiple
bug fixes since 0.2.3.
|
| |
|
|
|
|
|
| |
Move define-obsolete-variable-alias before its referent defcustom to
fix "alias should be declared before its referent" warning. Add
defvar for wttrin--force-refresh in wttrin-debug.el so the
byte-compiler knows the dynamic variable is intentional.
|
| |
|
|
|
|
| |
wttr.in updates its data roughly every 10 minutes (max-age=600).
Add a note to both refresh interval defcustoms so users know not
to poll more aggressively than the service can provide.
|
| |
|
|
|
|
|
|
|
|
| |
Remove obvious comments that restate what the code does ("save debug
data if enabled", "temporarily allow editing", "align buffer to top").
Add comments explaining non-obvious decisions: why risky-local-variable
is needed, why user-agent is curl, what wttr.in format codes mean,
what the emoji extraction regex matches, and why after-init-time
matters. Fix stale docstrings that no longer match the no-op stub
pattern.
|
| |
|
|
|
|
|
|
|
|
| |
The emoji face (dimmed/normal) was frozen at the last update-display
call, but the tooltip computes staleness dynamically. Between
refreshes, data could cross the stale threshold — tooltip says "Stale"
while the emoji is still normal.
Track the rendered staleness state. When the tooltip detects a
transition, trigger a re-render so the emoji dimming matches.
|
| |
|
|
|
|
|
| |
float-time was captured in the outer let* before the async fetch.
The callback used this stale value, making cache entries appear
slightly older than they are. Move the float-time call into the
callback so the timestamp reflects when the data actually arrived.
|
| |
|
|
|
| |
string-match modifies global match data as a side effect. A predicate
should not do this. Use string-match-p instead.
|
| |
|
|
|
|
|
|
|
|
|
| |
The tooltip was a static string computed at fetch time. Since every
successful fetch sets the cache timestamp to now and immediately
renders the tooltip, it was always "just now".
Extract wttrin--mode-line-tooltip as a named function that computes
age from the cache at call time. Set help-echo to this function so
Emacs invokes it on hover, producing an accurate age like
"Updated 12 minutes ago".
|
| |
|
|
|
|
|
| |
wttr.in's %l format returns locations in lowercase (e.g.,
"new orleans, la") regardless of the query casing. Replace the API's
location prefix with the user's original wttrin-favorite-location
string at cache time so tooltips display what the user expects.
|
| |
|
|
|
| |
Update copyright headers across all 37 .el files to include 2026.
Add missing Author field to testutil-wttrin.el for consistency.
|