feat(tui): tui.toml configuration file support #51

Merged
charles merged 1 commit from tui/config-43 into main 2026-04-11 20:41:33 +00:00
Owner

Summary

Fourth PR in the loom-tui stack. Adds the tui.toml schema and load/save primitives so the #19 key map finally has a real override source.

Stacks on #50. Closes charles/loom#43.

What's in

  • LoomTuiConfig schema — [tui] (image_protocol, theme, sidebar_width, gallery_columns, mouse_enabled, smooth_scroll), [tui.keybinds] (raw toml::Table passed to the keybinds layer), [log] (buffer_size, level)
  • load_from — returns (LoomTuiConfig, Vec<LoadWarning>). Missing file → defaults silently. Read errors, parse errors, and out-of-range numeric clamping each surface their own LoadWarning variant
  • save_to — atomic: writes to tui.toml.tmp, renames, backs up the previous content to tui.toml.bak
  • build_key_map — starts from keybinds::defaults() and applies the [tui.keybinds] override table, returning warnings as LoadWarning::KeybindWarning
  • main.rs wires it: loads the config, logs warnings via tracing::warn! (notification-bar routing lands in #42), builds the effective key map, then starts App::with_key_map
  • Path canonicalised via loom_core::config::config_dir() so loom-tui honours the same XDG/Flatpak rules as the rest of Loom

Tests (5 new, 21 total)

  • Missing file yields defaults, no warnings
  • Roundtrip save → reload equal, and a second save creates the .bak
  • Out-of-range sidebar_width and gallery_columns clamp with warnings
  • Invalid TOML yields ParseError and falls back to defaults
  • build_key_map applies overrides and the new combo resolves through lookup

Notes

  • save / save_to are #[allow(dead_code)] in this PR because only the settings screen (#39) calls them outside tests. Kept public to avoid a rename later
  • [tui.keybinds] is parsed as an opaque Option<toml::Table> rather than typed into the keybinds layer: the schema is action-id → string/array which is easier to evolve without a serde re-derive and naturally preserves future keys
## Summary Fourth PR in the loom-tui stack. Adds the `tui.toml` schema and load/save primitives so the #19 key map finally has a real override source. Stacks on #50. Closes charles/loom#43. ## What's in - **`LoomTuiConfig`** schema — `[tui]` (image_protocol, theme, sidebar_width, gallery_columns, mouse_enabled, smooth_scroll), `[tui.keybinds]` (raw `toml::Table` passed to the keybinds layer), `[log]` (buffer_size, level) - **`load_from`** — returns `(LoomTuiConfig, Vec<LoadWarning>)`. Missing file → defaults silently. Read errors, parse errors, and out-of-range numeric clamping each surface their own `LoadWarning` variant - **`save_to`** — atomic: writes to `tui.toml.tmp`, renames, backs up the previous content to `tui.toml.bak` - **`build_key_map`** — starts from `keybinds::defaults()` and applies the `[tui.keybinds]` override table, returning warnings as `LoadWarning::KeybindWarning` - **`main.rs`** wires it: loads the config, logs warnings via `tracing::warn!` (notification-bar routing lands in #42), builds the effective key map, then starts `App::with_key_map` - Path canonicalised via `loom_core::config::config_dir()` so loom-tui honours the same XDG/Flatpak rules as the rest of Loom ## Tests (5 new, 21 total) - Missing file yields defaults, no warnings - Roundtrip save → reload equal, and a second save creates the `.bak` - Out-of-range `sidebar_width` and `gallery_columns` clamp with warnings - Invalid TOML yields `ParseError` and falls back to defaults - `build_key_map` applies overrides and the new combo resolves through `lookup` ## Notes - `save` / `save_to` are `#[allow(dead_code)]` in this PR because only the settings screen (#39) calls them outside tests. Kept public to avoid a rename later - `[tui.keybinds]` is parsed as an opaque `Option<toml::Table>` rather than typed into the keybinds layer: the schema is action-id → string/array which is easier to evolve without a serde re-derive and naturally preserves future keys
Adds LoomTuiConfig — the full schema for $XDG_CONFIG_HOME/loom/tui.toml
with sections [tui], [tui.keybinds], and [log]. Load yields the config
plus a Vec<LoadWarning> (read errors, parse errors, clamped numeric
ranges, keybind override warnings) so the caller can surface issues
without blocking startup. Missing file → defaults silently. Invalid
file → defaults + ParseError. Save writes atomically via tempfile +
rename and backs up the previous content to tui.toml.bak.

main.rs now loads the config before touching the terminal and hands
the effective KeyMap (defaults + [tui.keybinds] overrides) into App,
so the entire #19 system now has a real data source. Warnings are
logged — the eventual notification-bar routing lands with #42.

Closes charles/loom#43

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
charles changed target branch from tui/keybinds-19 to main 2026-04-11 20:41:27 +00:00
charles deleted branch tui/config-43 2026-04-11 20:41:34 +00: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
charles/loom!51
No description provided.