diff --git a/shell/Commons/Color.qml b/shell/Commons/Color.qml index d6cf9790..466a9158 100644 --- a/shell/Commons/Color.qml +++ b/shell/Commons/Color.qml @@ -173,12 +173,18 @@ QtObject { if (!foundMuted) muted = color8Value.length > 0 ? color8Value : foreground } + // Last theme-supplied and user-supplied shell.toml dicts, kept separate so + // either can be reloaded without re-reading the other. `shellValues` is + // always the merge of theme (base) and user (override) — see mergeShell. + property var themeShellValues: ({}) + property var userShellValues: ({}) + // Single TOML walker for shell.toml. Both Color (surface roles) and Style // (typography, spacing, bar, control states) consume the resulting dict. // Accepts quoted strings, bare numeric values, bare width lists, and bare // role names; tolerates inline comments. Numbers are kept as strings here — // readers coerce when they pull a value. - function loadShell(raw) { + function parseShell(raw) { var parsed = {} var text = String(raw || "") if (text) { @@ -198,8 +204,28 @@ QtObject { parsed[section + "." + kv[1]] = kv[2] } } - shellValues = parsed - Style.applyShellValues(parsed) + return parsed + } + + // Re-derive `shellValues` from theme base + user override and push it to + // Style. User keys win, so a machine-level `~/.config/omarchy/shell.toml` + // survives theme switches (which replace only themeShellValues). + function mergeShell() { + var merged = {} + for (var tk in themeShellValues) merged[tk] = themeShellValues[tk] + for (var uk in userShellValues) merged[uk] = userShellValues[uk] + shellValues = merged + Style.applyShellValues(merged) + } + + function loadShell(raw) { + themeShellValues = parseShell(raw) + mergeShell() + } + + function loadUserShell(raw) { + userShellValues = parseShell(raw) + mergeShell() } // Startup load only. Runtime theme switches push the payload explicitly @@ -219,4 +245,19 @@ QtObject { onLoaded: root.loadShell(text()) onLoadFailed: root.loadShell("") } + // Machine-level override, layered on top of whatever theme is active. This + // is where `omarchy display text size` writes `[font] base-size`. Watched so the + // CLI takes effect live without restarting the shell; absent by default. + property FileView userShellFile: FileView { + id: userShellFile + path: root.home + "/.config/omarchy/shell.toml" + watchChanges: true + printErrors: false + onLoaded: root.loadUserShell(text()) + // Re-read on change (including first creation) before loading — `text()` + // is stale in the change signal itself, so route both paths through reload + // → onLoaded to always parse fresh content. + onFileChanged: reload() + onLoadFailed: root.loadUserShell("") + } }