From 25fb9cf9163b5a7e00b8e04fed4550574fd88950 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Mon, 20 Jul 2026 18:06:36 -0700 Subject: [PATCH] Layer a machine-level shell.toml override on top of the theme Read ~/.config/omarchy/shell.toml as a user override merged over the active theme's shell values, so a personal font/spacing/bar tweak survives theme switches. The file is watched, so edits re-flow the shell live. Co-Authored-By: Claude Opus 4.8 (1M context) --- shell/Commons/Color.qml | 47 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) 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("") + } }