1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: 2026 FernTech
//! `teksilo-settings` — persistent, reactive user preferences for Teksilo.
//!
//! Two persistence shapes share one storage backbone:
//!
//! * [`SettingsStore`] — dynamic, dotted-key K/V for **scalar** values
//! (numbers, strings, bools, arrays of those), surfaced as
//! `Signal<T>`. The QSettings analogue. Struct values aren't supported
//! here because TOML serializes them as tables, indistinguishable from
//! nested key paths; use [`SettingsFile<T>`] for those instead.
//! * [`SettingsFile<T>`] — typed single-struct persistence with
//! migrations.
//! * [`PersistedListModel<T>`] — a reactive, [`Keyed`]-item ordered
//! collection persisted to a single file, merging by **op** (upsert /
//! remove / clear) rather than by whole-document snapshot — so a peer
//! process's concurrent addition survives.
//! * [`MruList<T>`] — generic dedupe + pin + cap list over an
//! app-defined item type implementing [`MruEntry`]. Apps register
//! their own via `TeksiloAppBuilder::app_state(handle)`.
//! * [`WindowStateService`] — per-window geometry persistence. When
//! registered via `TeksiloAppBuilder::settings(...)`, every
//! `WindowConfig` carrying an `id(...)` is automatically restored
//! on creation (sanitized against the current monitor) and recorded
//! on every change by `teksilo-app`'s window manager. No widget-side
//! wiring required.
//!
//! All disk writes are atomic (write-temp + rename). Every write **merges**
//! against the document read fresh off disk under an exclusive lock —
//! never a blind whole-document overwrite — so two processes sharing a
//! file (Skribisto's one-process-per-project model shares `general.toml`,
//! `recents.toml`, `window_state.toml` across every open project) cannot
//! silently clobber each other. [`Reloadable`] is the matching read-side
//! contract: a hook a file-system watcher calls to push a peer's write into
//! this process's live signals/models — and [`SettingsWatcher`] +
//! [`SettingsRegistry`] are the actual watcher: a `notify`-based directory
//! watch (parent-directory, not file, so an atomic rename-over doesn't
//! invalidate it) plus the path → [`Reloadable`] lookup a changed-file
//! event dispatches through. `TeksiloAppBuilder::settings(...)` wires one
//! up automatically (opt out via `.settings_watch(false)`); every service
//! [`SettingsBundle::open`] opens is pre-registered into
//! [`OpenedSettings::registry`], and application code can register its
//! own ad hoc `SettingsFile` / `PersistedListModel` / `MruList` handles
//! into that same registry.
//!
//! ```
//! use teksilo_settings::{AppPaths, SettingsStore, SettingsKey};
//!
//! const FONT_SIZE: SettingsKey<f32> =
//! SettingsKey::new("editor.font_size", || 14.0);
//!
//! // Tests / docs use `for_testing(...)` against a tempdir so they
//! // never touch the user's real config tree. Production apps use
//! // `AppPaths::new(qualifier, organization, application)`.
//! let tmp = tempfile::tempdir().unwrap();
//! let paths = AppPaths::for_testing(tmp.path());
//! let store = SettingsStore::open(paths.config_file("general")).unwrap();
//!
//! let font_size = store.signal_for(&FONT_SIZE);
//! font_size.set(18.0); // persisted on the next debounce tick
//! ```
pub use crate;
pub use crate;
pub use crateSettingsExt;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crateAppPaths;
pub use crateReloadable;
pub use crate;
pub use crate;
pub use crate;