bread-theme: add an API to write pywal's colors.json cache from a Palette #24

Merged
Breadway merged 1 commit from feature/eco-22-write-wal-cache into main 2026-09-11 11:03:56 +08:00
Owner

Summary

bread-theme could read pywal's colors.json (load_palette, from_wal_json) but had no way to write that format from an in-memory Palette. This adds it.

New public API in bread_theme::palette (re-exported from the crate root):

  • write_wal_cache(palette: &Palette, path: &Path) -> io::Result<()> - atomic (temp file then rename) write of palette in pywal's colors.json shape, via the existing output::atomic_write.
  • wal_cache_json(palette: &Palette) -> String - the same payload as a string, for tests and callers that want it without writing.
  • wal_cache_path() -> PathBuf - ~/.cache/wal/colors.json, the path load_palette reads (previously the internal wal_path() had no public accessor).

Format

All 16 ANSI slots plus special (background/foreground/cursor), wallpaper, and alpha are written, so the file stays valid for every other pywal consumer on the system (terminal palettes, editor themes), not just the six accents bread-theme itself reads back. color8..color15 mirror color0..color7 - bread-theme has no bright variants, which matches pywal's own behaviour when brightening is off. special.background / foreground come straight from the Palette (BOS's fixed dark values).

Round-trips: from_wal_json(&wal_cache_json(&p)) gives back p's color1..color6 and the fixed bg/fg/surface/overlay, same as any other wal JSON.

Motivating consumer

breadpaper's sync_focused_global (PAPER-2) holds a per-output Palette but still shells out to a second wal -i on every focused set_on just to refresh ~/.cache/wal/colors.json: a process spawn per switch, and it re-extracts from the image rather than using the palette it already computed, so the cache and breadpaper's per-output palette can drift. It can now call write_wal_cache directly. That breadpaper change is a separate follow-up in the breadpaper repo (kept out of this PR: different repo, one PR per issue).

Verification

  • cargo build -p bread-theme, cargo test -p bread-theme --locked (114 pass, incl. 3 new: round-trip, all-16-slots-and-special, atomic-write-no-tmp-leftover), cargo clippy -p bread-theme --all-targets --locked -- -D warnings: clean
  • rustfmt --check on palette.rs: clean
  • The --features gtk and full---workspace passes could not run locally (a disk-quota limit in the build sandbox on the GTK4 + ONNX dependency tree). My change is entirely in gtk-free code (palette.rs, one re-export line, the existing output::atomic_write), so CI's gtk and workspace matrix will cover it.
  • No Cargo.toml / Cargo.lock change; CHANGELOG entry folded into the current unreleased ## 0.7.11 section.

Closes #22

## Summary `bread-theme` could read pywal's `colors.json` (`load_palette`, `from_wal_json`) but had no way to write that format from an in-memory `Palette`. This adds it. New public API in `bread_theme::palette` (re-exported from the crate root): - **`write_wal_cache(palette: &Palette, path: &Path) -> io::Result<()>`** - atomic (temp file then rename) write of `palette` in pywal's `colors.json` shape, via the existing `output::atomic_write`. - **`wal_cache_json(palette: &Palette) -> String`** - the same payload as a string, for tests and callers that want it without writing. - **`wal_cache_path() -> PathBuf`** - `~/.cache/wal/colors.json`, the path `load_palette` reads (previously the internal `wal_path()` had no public accessor). ## Format All 16 ANSI slots plus `special` (`background`/`foreground`/`cursor`), `wallpaper`, and `alpha` are written, so the file stays valid for every other pywal consumer on the system (terminal palettes, editor themes), not just the six accents bread-theme itself reads back. `color8..color15` mirror `color0..color7` - bread-theme has no bright variants, which matches pywal's own behaviour when brightening is off. `special.background` / `foreground` come straight from the `Palette` (BOS's fixed dark values). Round-trips: `from_wal_json(&wal_cache_json(&p))` gives back `p`'s `color1..color6` and the fixed bg/fg/surface/overlay, same as any other wal JSON. ## Motivating consumer breadpaper's `sync_focused_global` (PAPER-2) holds a per-output `Palette` but still shells out to a second `wal -i` on every focused `set_on` just to refresh `~/.cache/wal/colors.json`: a process spawn per switch, and it re-extracts from the image rather than using the palette it already computed, so the cache and breadpaper's per-output palette can drift. It can now call `write_wal_cache` directly. **That breadpaper change is a separate follow-up in the breadpaper repo** (kept out of this PR: different repo, one PR per issue). ## Verification - `cargo build -p bread-theme`, `cargo test -p bread-theme --locked` (114 pass, incl. 3 new: round-trip, all-16-slots-and-special, atomic-write-no-tmp-leftover), `cargo clippy -p bread-theme --all-targets --locked -- -D warnings`: clean - `rustfmt --check` on `palette.rs`: clean - The `--features gtk` and full-`--workspace` passes could not run locally (a disk-quota limit in the build sandbox on the GTK4 + ONNX dependency tree). My change is entirely in gtk-free code (`palette.rs`, one re-export line, the existing `output::atomic_write`), so CI's gtk and workspace matrix will cover it. - No `Cargo.toml` / `Cargo.lock` change; CHANGELOG entry folded into the current unreleased `## 0.7.11` section. Closes #22
feat(bread-theme): add write_wal_cache to serialise a Palette to pywal's colors.json
All checks were successful
check / check (push) Successful in 2m51s
18524f2d28
bread-theme could read pywal's colors.json (load_palette) but had no way
to write that format from an in-memory Palette. Add:

- write_wal_cache(&Palette, path): atomic (temp then rename) write in
  pywal's colors.json shape, reusing output::atomic_write.
- wal_cache_json(&Palette): the payload as a string, for tests and
  callers that want it without writing.
- wal_cache_path(): ~/.cache/wal/colors.json, the path load_palette reads.

All 16 ANSI slots plus special/wallpaper/alpha are written so the cache
stays valid for other pywal consumers (terminal palettes, editor themes);
color8..color15 mirror color0..color7 since bread-theme has no bright
variants.

The motivating consumer is breadpaper's sync_focused_global, which holds
a per-output Palette but shells out to a second wal -i on every focused
set_on just to refresh the cache. That breadpaper change is a follow-up
in its own repo.

Closes #22
Breadway deleted branch feature/eco-22-write-wal-cache 2026-09-11 11:03:56 +08:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/bread-ecosystem!24
No description provided.