diff options
Diffstat (limited to 'bin/udt-appthemes')
| -rwxr-xr-x | bin/udt-appthemes | 102 |
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()) |
