| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
| |
I added 24 unit tests across six new files for wttrin-debug.el. They cover enable/disable, the debug-log writer, clear-log, show-log, and the mode-line diagnostic dump. That lifts wttrin-debug.el coverage from 27% to 95%, and overall coverage from 84% to 94%. Each function gets Normal / Boundary / Error categories where applicable. Globals like `wttrin-debug` and `wttrin--debug-log` are isolated per test with let-bindings. The dynamic-scope rebinding restores state cleanly at exit.
I expanded the `lint` target to run on all three source files instead of just `wttrin.el`. Checkdoc and elisp-lint run on every file. Package-lint stays scoped to `wttrin.el` because the others aren't standalone packages.
The tricky bit: `elisp-lint-file` re-runs package-lint internally as one of its validators. So the explicit guard alone wasn't enough. The fix binds `elisp-lint-ignored-validators` to include "package-lint" for the secondaries, which suppresses the re-run at the validator level.
I also added `*-autoloads.el` to .gitignore. Eask generates `emacs-wttrin-autoloads.el` during install, and it shouldn't be tracked.
I skipped one function: `wttrin--debug-mode-line-info` is a one-line dispatcher to `debug-wttrin-mode-line`. Testing it would assert the dispatch happened, which only tests Emacs.
|
| |
|
|
|
|
|
|
|
|
| |
I wanted a coverage number, so I added an Eask file declaring the runtime dep (xterm-color) plus three dev deps (undercover, package-lint, elisp-lint). The Makefile now runs every test and lint recipe through `eask emacs`. That drops the hand-rolled `(require 'package)` + `add-to-list 'package-archives` boilerplate that was duplicated across six recipes.
I added a `make deps` target that runs `eask install-deps --dev`. I also added a `make coverage` target that loads `tests/run-coverage-file.el` before each unit-test file. Undercover instruments the three source files first, then the test loads pick up the instrumented copy. Per-file results merge into `.coverage/simplecov.json` in simplecov format.
I expanded `validate-parens` and `compile` to cover all three source files instead of just `wttrin.el`. Lint stays scoped to the main file for now.
Coverage right now is 84% overall: wttrin.el 92%, wttrin-geolocation.el 100%, wttrin-debug.el 27%. The debug module is low because only the integration test exercises it. The coverage loop runs unit tests only.
|
| |
|
|
|
|
| |
Stop tracking the Syncthing ignore file. It's local-machine config,
not project content. Add it to .gitignore so the file stays put
locally without showing up in git status.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Four pure helpers in wttrin-geolocation.el were exercised only indirectly through the parser tests: --decode-json, --format-city-region, --lookup-provider, and --extract-body. None of them had direct unit coverage. Edge cases like an empty JSON object, a missing-vs-empty city field, an unknown provider symbol, or a missing HTTP body separator weren't locked.
The new file groups all four functions together. Each gets Normal, Boundary, and Error cases per testing.md. Highlights:
- --decode-json: distinguishes nil input, empty string, and malformed JSON, all of which return nil for different reasons.
- --format-city-region: separates "missing key" from "empty string" since the predicate `(and (stringp city) (> (length city) 0) ...)` short-circuits on either.
- --lookup-provider: tests two of the three built-ins plus a `let`-bound synthetic provider, locking the documented extension point on `wttrin-geolocation--providers`.
- --extract-body: real UTF-8 bytes inserted into a temp buffer (mirroring what `url-retrieve` delivers) verify the decoding path. 4xx, 5xx, and missing-separator paths each get their own test.
21 new tests, all green on first run since they characterize existing behavior.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
When wttrin-mode-line-emoji-font is set and the cache is fresh, --make-emoji-icon was emitting a face plist of the form (:family ... :height 1.0 :foreground nil). Emacs validates faces on every redisplay, so a single fresh-cache state produced hundreds of "Invalid face attribute :foreground nil" warnings in *Messages*.
The new boundary test asserts the face plist omits :foreground entirely when the caller passes nil. The assertion uses plist-member, not plist-get. plist-get returns nil for both a missing key and a present key bound to nil. That's the exact distinction Emacs's redisplay validator cares about.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
| |
Per claude-templates c36fd14. Claude tooling moves to hidden .ai/;
project-level docs/ reserved for real documentation.
|
| |
|
|
|
|
| |
Quick-start commands, full Makefile target table, writing guide
with file template and naming conventions, testutil-wttrin.el API
docs, key patterns, and test inventory.
|
| | |
|
| |
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
Rewrite sections that read like generated text: replace clinical
descriptions with conversational language matching the existing
voice, cut padding phrases ("proactively", "several aspects",
"what's happening"), and trim the debug section down to essentials.
|
| |
|
|
|
|
|
|
|
|
| |
Add: staleness display in weather buffer, stale mode-line dimming,
wttrin-clear-cache command, wttrin-mode-line-startup-delay option,
minimum Emacs version (24.4).
Fix: font height default was listed as 110 (actually 130), debug
output example didn't match current log format, manual debug setup
section was a duplicate of the use-package section.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
A debug command should show what the API currently returns, not a
cached copy. Bind wttrin--force-refresh to t so the fetch always
bypasses the cache.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
The ;;;###autoload(put ...) form on the same line was never processed
by the autoload generator. The actual (put ...) call on the next line
handles this at load time. Remove the dead cookie.
|
| |
|
|
|
|
|
|
| |
Add wttrin--make-emoji-icon and wttrin--set-mode-line-string to
eliminate three near-identical propertize blocks across
update-placeholder-error, set-placeholder, and update-display.
Reduces wttrin--mode-line-update-display from 40 lines to 25.
|
| |
|
|
|
|
|
|
|
| |
Define wttrin--debug-log and wttrin--debug-mode-line-info as no-op
stubs in wttrin.el that get overridden when wttrin-debug.el loads.
Remove all 24 (when (featurep 'wttrin-debug) ...) guard blocks.
Reduces cyclomatic complexity across 12 functions and eliminates
visual clutter without changing behavior.
|
| |
|
|
|
| |
Never called anywhere. The 'q' keybinding in wttrin-mode inherits
quit-window from special-mode, making this function redundant.
|
| |
|
|
|
|
|
| |
debug-wttrin-show-raw called wttrin--get-cached-or-fetch with 1 arg,
but the function now requires 2 (location + callback) since the async
refactor. Rewrote to use the callback pattern. Also handles nil
response gracefully.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add 11 new test files covering wttrin--save-debug-data,
wttrin--buffer-cache-refresh, wttrin--mode-line-stop,
wttrin--mode-line-start, wttrin-query, wttrin-requery-force,
wttrin-mode-line-click, wttrin-mode-line-force-refresh,
wttrin-fetch-raw-string, wttrin-clear-cache, and wttrin-requery.
Fix bug in wttrin--save-debug-data where nil raw-string caused
(insert nil) crash — reachable when debug mode is on and fetch fails.
Refactor wttrin-requery: extract wttrin--requery-location so the
core kill-buffer-and-query logic is testable without mocking
completing-read.
267 tests total (was 217), all passing.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replace TTL-based cache invalidation with proactive scheduled refresh.
Both mode-line and buffer systems now follow: timer refreshes cache,
display reads from cache, staleness indicated when data is old.
Phase 1 - Mode-line cache formalization + staleness display:
- Replace wttrin--mode-line-tooltip-data with wttrin--mode-line-cache
as (timestamp . data) cons cell matching buffer cache pattern
- Add wttrin--format-age helper for human-readable age strings
- Rewrite wttrin--mode-line-update-display to take no arguments,
read from cache, compute staleness (age > 2x refresh interval),
dim emoji gray when stale, show staleness info in tooltip
- Rewrite wttrin--mode-line-fetch-weather to write cache on success,
show stale display on failure with cache, error placeholder without
- Add wttrin--mode-line-update-placeholder-error for first-launch failure
Phase 2 - Remove TTL, add proactive buffer refresh:
- Rename wttrin-cache-ttl to wttrin-refresh-interval (default 3600s)
with define-obsolete-variable-alias for backward compatibility
- Change wttrin-mode-line-refresh-interval default from 900 to 3600
- Remove TTL check from wttrin--get-cached-or-fetch; serve cached data
regardless of age, background timer keeps it fresh
- Add buffer refresh timer (wttrin--buffer-cache-refresh)
Phase 3 - Buffer staleness display:
- Add wttrin--format-staleness-header for buffer age display
- Insert staleness line in wttrin--display-weather before instructions
Phase 4 - Cleanup:
- Remove all references to wttrin--mode-line-tooltip-data
- Update README.org cache settings and mode-line documentation
- Update tests for new API (198 tests across 21 files, all passing)
|
| |
|
|
|
|
| |
Display ⏳ with "Fetching weather..." tooltip immediately when
mode-line mode starts, so the user sees wttrin is active before
the first API response arrives.
|
| |
|
|
|
|
| |
Reject empty or malformed wttr.in responses to prevent blank icon and
tooltip. Fix tooltip lambda to treat empty string as falsy. Add debug
logging for nil-location and invalid-response paths.
|
| |
|
|
| |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Expand testutil-wttrin.el with shared fixtures and macros
(testutil-wttrin-with-clean-weather-buffer,
testutil-wttrin-mock-http-response, sample ANSI/weather constants)
- Consolidate cache tests: port unique tests from cleanup-cache-constants
and cleanup-cache-refactored into cleanup-cache-if-needed, delete
obsolete files
- Extract startup-delay tests into dedicated file
- Add setup/teardown and (require 'testutil-wttrin) to all test files
- Rename all 160 tests to follow
test-<module>-<category>-<scenario>-<expected-result> convention
- Rename integration test file and add detailed docstrings
- Update Makefile glob to discover new integration test naming pattern
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
| |
|
|
|
|
|
|
| |
wttrin-favorite-location
Renamed variable to remove 'mode-line' prefix, making it usable for
future location-based features beyond mode-line display. Updated all
references in code, tests, and documentation. All 187 tests passing.
|
| |
|
|
|
|
| |
Fixed two checkdoc issues in recently added functions:
- Added double space after period in wttrin--extract-response-body
- Quoted url-retrieve symbol in wttrin--handle-fetch-callback
|
| |
|
|
|
|
| |
Prevents mode-line from making network requests during Emacs startup.
Network activity now deferred to after-init-hook when Emacs is not yet
fully initialized, improving startup performance.
|
| |
|
|
|
|
| |
Extracted wttrin--extract-response-body and wttrin--handle-fetch-callback
from wttrin--fetch-url to improve testability and separation of concerns.
Added comprehensive unit tests for both new functions.
|
| |
|
|
|
| |
Replace add-to-list approach with use-package's :load-path keyword
for cleaner, more idiomatic configuration.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Remove outdated xterm-color configuration requirements following the
lazy-load refactor. Users no longer need :after, :preface, or separate
use-package declarations for xterm-color.
Changes:
- Simplified local development setup (no xterm-color use-package needed)
- Removed :preface xterm-color :demand t from debug examples
- Updated manual install to just require wttrin (not xterm-color first)
- Clarified that xterm-color loads automatically when needed
- Noted MELPA auto-installs xterm-color as dependency
The configuration is now simpler and matches the lazy-loading behavior.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Move xterm-color from top-level require to on-demand loading within
functions that actually use it. This simplifies user configuration
by eliminating the need for separate xterm-color use-package declarations.
Changes:
- Replace top-level (require 'xterm-color) with declare-function
- Add (require 'xterm-color) in wttrin--process-weather-content
- Add (require 'xterm-color) in wttrin--display-weather
- Update smoke test to check loadability vs. feature presence
Benefits:
- Simpler use-package config (no :after xterm-color needed)
- xterm-color still auto-installed via Package-Requires on MELPA
- Load time optimization (loads only when displaying weather)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Smoke Test Target:
- Add SMOKE_TESTS variable matching test-*-smoke.el pattern
- Create test-smoke target that runs before unit/integration tests
- Implement fail-fast behavior: smoke test failures stop further execution
- Update test execution order: smoke → unit → integration (testing pyramid)
- Fix INTEGRATION_TESTS pattern to match test-*-integration-*.el
- Update help text with correct test counts for each category
Symbol Standardization:
- Replace Unicode symbols with bracketed ASCII for better portability
- ✓ → [✓] (success/completion)
- ✗ → [✗] (error/failure)
- ⚠ → [!] (warning/attention)
- Apply to all targets: test, validate, compile, lint, install-deps, clean
- No color codes (were never present)
- Benefits: works in all terminals, easier to grep/parse
Test organization now:
- 1 smoke test file (package sanity checks - runs first)
- 16 unit test files (function behavior)
- 1 integration test file (component interactions)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
conventions
- Create test-wttrin-smoke.el with 15 smoke tests for package sanity checks
- Delete test-wttrin-integration.el (misnamed, contained smoke tests not integration tests)
- Remove redundant functional tests already covered in dedicated unit test files
- URL building: covered by test-wttrin--build-url.el (12 tests)
- Cache operations: covered by test-wttrin--get-cached-or-fetch.el (11 tests)
- Mode-line display: covered by test-wttrin--mode-line-map.el
Smoke tests verify:
- Package loads without errors
- Dependencies available (xterm-color, url)
- Public API exists and is interactive
- Configuration variables defined
- Keymaps exist and are valid
- Package metadata correct (version, autoload cookies)
Final test organization: 18 files, 162 tests (15 smoke + 142 unit + 5 integration)
|