From 8527f75bf8a8bd3ad26768d70dcc268d2d20e085 Mon Sep 17 00:00:00 2001 From: Julien Calixte Date: Sun, 12 Jul 2026 10:30:02 +0200 Subject: [PATCH] feat(firmware): read .typoena.snippets.json at boot into set_snippets Mirror the prefs boot-read: load the git-tracked snippet library from the SD repo, parse it with Snippets::parse, and hand it to the editor before the first render. Missing/unreadable/malformed is non-fatal (no snippets, editor runs). Verified serde_json builds for xtensa (cargo check, 0.6.0). --- firmware/Cargo.toml | 2 +- firmware/src/main.rs | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index b394331..0bb9b32 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "firmware" -version = "0.5.0" +version = "0.6.0" authors = ["Julien Calixte "] edition = "2024" resolver = "2" diff --git a/firmware/src/main.rs b/firmware/src/main.rs index 213711f..95869b1 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -10,7 +10,10 @@ use esp_idf_svc::hal::spi::{Dma, SpiBusDriver, SpiDriver}; use esp_idf_svc::hal::units::FromValueType; use display::Frame; -use editor::{Editor, Effect, Mode, Prefs, Scope, CH, LOCAL_DIR, PREFS_PATH, REPO_DIR}; +use editor::{ + Editor, Effect, Mode, Prefs, Scope, Snippets, CH, LOCAL_DIR, PREFS_PATH, REPO_DIR, + SNIPPETS_PATH, +}; use firmware::epd::{self, Epd}; use firmware::persistence::{Storage, NOTES}; @@ -130,6 +133,21 @@ fn main() -> anyhow::Result<()> { }; log::info!("prefs: {prefs:?}"); ed.set_prefs(prefs); + // Snippet library (.typoena.snippets.json, git-tracked). Parsed with + // serde_json in the editor crate; a missing / unreadable / malformed file is + // non-fatal — the editor simply has no snippets and runs unchanged. + let snippets = match storage.load_path(SNIPPETS_PATH) { + Ok(src) => match Snippets::parse(&src) { + Ok(s) => s, + Err(e) => { + log::warn!("snippets parse FAILED ({e}); none loaded"); + Snippets::default() + } + }, + Err(_) => Snippets::default(), + }; + log::info!("snippets: {} loaded", snippets.0.len()); + ed.set_snippets(snippets); let mut updates: u32 = 0; let mut cursor_shown = true; // the initial render includes the caret let mut last_activity = Instant::now();