diff options
Diffstat (limited to 'bin/udt-appthemes')
| -rwxr-xr-x | bin/udt-appthemes | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/bin/udt-appthemes b/bin/udt-appthemes new file mode 100755 index 0000000..eedc144 --- /dev/null +++ b/bin/udt-appthemes @@ -0,0 +1,88 @@ +#!/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" +VAULT_ROOT = Path.home() / "Documents" / "Obsidian" +TYPORA_THEMES = Path.home() / ".config" / "Typora" / "themes" + + +def vaults(): + """Every Obsidian vault under the vault root. + + A vault is any directory holding a .obsidian config dir. Nested vaults are + real: a vault inside another vault's folder is still its own vault. + """ + if not VAULT_ROOT.is_dir(): + return [] + return sorted(p for p in VAULT_ROOT.rglob(".obsidian") if p.is_dir()) + + +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()) |
