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

Closed
opened 2026-09-09 09:09:21 +08:00 by Breadway · 2 comments
Owner

Broken out from ECO-15 (bread-ecosystem audit, 2026-09-05). Verified still open on main as of 2026-09-09.

bread-theme can read pywal's colors.json (bread-theme/src/palette.rs:75, Palette::load and friends) but has no function to write that format from an in-memory Palette.

Because of that, breadpaper's sync_focused_global (src/lib.rs:154, the PAPER-2 fix) has a per-output Palette already in hand but still shells out to a second wal -i subprocess (src/pywal.rs, generate) just to refresh ~/.cache/wal/colors.json. That is a process spawn on every focused set_on, and it re-derives the palette from the image rather than using the palette breadpaper already computed for that output, so the cache and breadpaper's own per-output palette can drift slightly.

Suggested: add bread_theme::write_wal_cache(&Palette, path) (or similar) that serialises a Palette into pywal's colors.json shape and writes it via the atomic-write path bread-theme already uses. breadpaper can then replace the wal -i call in sync_focused_global with a direct write of the palette it holds. Any future consumer that needs the cache kept in sync gets the same helper.

PAPER-2's PR body called this out: "bread-theme exposes no API to write pywal's cache format, hand-rolling it is fragile."

Broken out from ECO-15 (bread-ecosystem audit, 2026-09-05). Verified still open on main as of 2026-09-09. bread-theme can read pywal's `colors.json` (`bread-theme/src/palette.rs:75`, `Palette::load` and friends) but has no function to write that format from an in-memory `Palette`. Because of that, breadpaper's `sync_focused_global` (`src/lib.rs:154`, the PAPER-2 fix) has a per-output `Palette` already in hand but still shells out to a second `wal -i` subprocess (`src/pywal.rs`, `generate`) just to refresh `~/.cache/wal/colors.json`. That is a process spawn on every focused `set_on`, and it re-derives the palette from the image rather than using the palette breadpaper already computed for that output, so the cache and breadpaper's own per-output palette can drift slightly. Suggested: add `bread_theme::write_wal_cache(&Palette, path)` (or similar) that serialises a `Palette` into pywal's `colors.json` shape and writes it via the atomic-write path bread-theme already uses. breadpaper can then replace the `wal -i` call in `sync_focused_global` with a direct write of the palette it holds. Any future consumer that needs the cache kept in sync gets the same helper. PAPER-2's PR body called this out: "bread-theme exposes no API to write pywal's cache format, hand-rolling it is fragile."
Author
Owner

PR: #24

Added to bread_theme::palette (re-exported from the crate root):

  • write_wal_cache(&Palette, &Path): atomic (temp then rename) write in pywal's colors.json shape, via the existing output::atomic_write.
  • wal_cache_json(&Palette): the payload as a string.
  • wal_cache_path(): ~/.cache/wal/colors.json (the internal wal_path() had no public accessor).

All 16 ANSI slots + special/wallpaper/alpha are written so the file stays valid for other pywal consumers; color8..15 mirror color0..7. Round-trips through from_wal_json.

The breadpaper sync_focused_global change (drop the wal -i subprocess, write the cache from the palette it already holds) is a follow-up in the breadpaper repo, kept out of this PR (different repo, one PR per key).

Verified: cargo test -p bread-theme --locked (114 pass, incl. 3 new), cargo clippy -p bread-theme --all-targets --locked -- -D warnings, rustfmt --check on palette.rs: all clean. The --features gtk / full---workspace passes hit a disk-quota limit in the build sandbox (GTK4 + ONNX dep tree); my change is 100% gtk-free code so CI's matrix will cover those. No Cargo.toml/Cargo.lock change; changelog folded into the unreleased ## 0.7.11.

PR: https://git.breadway.dev/Breadway/bread-ecosystem/pulls/24 Added to `bread_theme::palette` (re-exported from the crate root): - `write_wal_cache(&Palette, &Path)`: atomic (temp then rename) write in pywal's `colors.json` shape, via the existing `output::atomic_write`. - `wal_cache_json(&Palette)`: the payload as a string. - `wal_cache_path()`: `~/.cache/wal/colors.json` (the internal `wal_path()` had no public accessor). All 16 ANSI slots + `special`/`wallpaper`/`alpha` are written so the file stays valid for other pywal consumers; `color8..15` mirror `color0..7`. Round-trips through `from_wal_json`. The breadpaper `sync_focused_global` change (drop the `wal -i` subprocess, write the cache from the palette it already holds) is a **follow-up in the breadpaper repo**, kept out of this PR (different repo, one PR per key). Verified: `cargo test -p bread-theme --locked` (114 pass, incl. 3 new), `cargo clippy -p bread-theme --all-targets --locked -- -D warnings`, `rustfmt --check` on `palette.rs`: all clean. The `--features gtk` / full-`--workspace` passes hit a disk-quota limit in the build sandbox (GTK4 + ONNX dep tree); my change is 100% gtk-free code so CI's matrix will cover those. No `Cargo.toml`/`Cargo.lock` change; changelog folded into the unreleased `## 0.7.11`.
Author
Owner

Reviewed, looks ready to merge. Leaving the merge to you since bread-ecosystem is on the release train.

Acceptance criteria: add an API to serialize a Palette into pywal's colors.json shape and write it atomically, so breadpaper can stop shelling out to wal -i just to refresh the cache. Met: write_wal_cache/wal_cache_json/wal_cache_path added to bread_theme::palette, reusing the existing atomic_write path. All 16 ANSI slots plus special are written so other pywal consumers stay unaffected, color8..15 mirror color0..7 matching pywal's own no-brightening behavior. Tests check actual round-trip and shape (from_wal_json output, all 16 keys present, no leftover temp file) rather than just mirroring the implementation. The breadpaper consumer change is correctly left as a separate PR in that repo, one PR per issue. CI green (bread-theme test/clippy/fmt), no conflicts with main.

Reviewed, looks ready to merge. Leaving the merge to you since bread-ecosystem is on the release train. Acceptance criteria: add an API to serialize a Palette into pywal's colors.json shape and write it atomically, so breadpaper can stop shelling out to `wal -i` just to refresh the cache. Met: write_wal_cache/wal_cache_json/wal_cache_path added to bread_theme::palette, reusing the existing atomic_write path. All 16 ANSI slots plus special are written so other pywal consumers stay unaffected, color8..15 mirror color0..7 matching pywal's own no-brightening behavior. Tests check actual round-trip and shape (from_wal_json output, all 16 keys present, no leftover temp file) rather than just mirroring the implementation. The breadpaper consumer change is correctly left as a separate PR in that repo, one PR per issue. CI green (bread-theme test/clippy/fmt), no conflicts with main.
Sign in to join this conversation.
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#22
No description provided.