aboutsummaryrefslogtreecommitdiffstats
path: root/bin/udt-appthemes
diff options
context:
space:
mode:
Diffstat (limited to 'bin/udt-appthemes')
-rwxr-xr-xbin/udt-appthemes102
1 files changed, 102 insertions, 0 deletions
diff --git a/bin/udt-appthemes b/bin/udt-appthemes
new file mode 100755
index 0000000..37d3e63
--- /dev/null
+++ b/bin/udt-appthemes
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+# udt-appthemes: install the generated app themes that need more than a copy.
+# Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+# Licensed under the GNU General Public License v2 only.
+"""Install the Obsidian snippet into every vault, and the Typora theme.
+
+Separate from install.sh because enabling an Obsidian snippet means editing
+JSON that the user also owns: appearance.json lists every enabled snippet, so
+the entry has to be appended rather than the file rewritten, or a vault loses
+whatever layout snippets it had.
+"""
+
+import json
+import shutil
+import sys
+from pathlib import Path
+
+REPO = Path(__file__).resolve().parent.parent
+SNIPPET = "udt"
+OBSIDIAN_REGISTRY = Path.home() / ".config" / "obsidian" / "obsidian.json"
+TYPORA_THEMES = Path.home() / ".config" / "Typora" / "themes"
+
+
+def vaults():
+ """The vaults Obsidian itself knows about.
+
+ Read from Obsidian's own registry rather than found by scanning for
+ .obsidian directories. A scan cannot tell a vault from an abandoned one:
+ ~/Documents/Obsidian holds a leftover .obsidian from a vault that no longer
+ exists, and writing to it touched config for something Obsidian never
+ opens.
+ """
+ try:
+ data = json.loads(OBSIDIAN_REGISTRY.read_text())
+ except (OSError, json.JSONDecodeError):
+ return []
+
+ found = []
+ for entry in data.get("vaults", {}).values():
+ path = entry.get("path")
+ if not path:
+ continue
+ config = Path(path) / ".obsidian"
+ if config.is_dir():
+ found.append(config)
+ return sorted(found)
+
+
+def install_obsidian(source):
+ """Copy the snippet into each vault and enable it, preserving the rest."""
+ done = []
+ for config in vaults():
+ snippets = config / "snippets"
+ snippets.mkdir(exist_ok=True)
+ shutil.copyfile(source, snippets / f"{SNIPPET}.css")
+
+ appearance = config / "appearance.json"
+ try:
+ data = json.loads(appearance.read_text())
+ except (OSError, json.JSONDecodeError):
+ data = {}
+
+ enabled = data.get("enabledCssSnippets", [])
+ if SNIPPET not in enabled:
+ # Append: a vault may already have snippets on, and replacing the
+ # list would silently switch them off.
+ enabled.append(SNIPPET)
+ data["enabledCssSnippets"] = enabled
+ appearance.write_text(json.dumps(data, indent=2) + "\n")
+
+ done.append(config.parent.name or str(config.parent))
+ return done
+
+
+def install_typora(source):
+ """Drop the theme in. Typora picks it from Themes once the file exists."""
+ if not TYPORA_THEMES.is_dir():
+ return False
+ shutil.copyfile(source, TYPORA_THEMES / "udt.css")
+ return True
+
+
+def main():
+ obsidian = REPO / "templates" / "obsidian" / "udt.css"
+ typora = REPO / "templates" / "typora" / "udt.css"
+
+ if not obsidian.exists() or not typora.exists():
+ print("udt-appthemes: run udt-palette first", file=sys.stderr)
+ return 1
+
+ names = install_obsidian(obsidian)
+ if names:
+ print(f"obsidian: {len(names)} vaults ({', '.join(names)})")
+
+ if install_typora(typora):
+ print("typora: udt.css installed (select it in Themes)")
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())