diff --git a/quickshell/services/python/theme_sync.py b/quickshell/services/python/theme_sync.py index a6b556e..a8411ea 100644 --- a/quickshell/services/python/theme_sync.py +++ b/quickshell/services/python/theme_sync.py @@ -1453,6 +1453,141 @@ def sync_xresources(bg, surface, current_line, fg, accent, sub_accent): except Exception: pass +def sync_obsidian(bg, surface, current_line, fg, accent, sub_accent, is_dark): + import json + home = os.path.expanduser('~') + + # CSS Template for Obsidian Vaults + obsidian_css = f"""/* Auto-generated by Quickshell Theme Engine */ +.theme-dark, .theme-light, :root, body {{ + --bg-primary: {bg} !important; + --bg-primary-alt: {surface} !important; + --bg-secondary: {surface} !important; + --bg-secondary-alt: {current_line} !important; + + --background-primary: {bg} !important; + --background-primary-alt: {surface} !important; + --background-secondary: {surface} !important; + --background-secondary-alt: {current_line} !important; + --background-modifier-border: {current_line} !important; + --background-modifier-border-hover: {accent} !important; + --background-modifier-form-field: {surface} !important; + + --text-normal: {fg} !important; + --text-muted: {fg} !important; + --text-faint: {current_line} !important; + + --interactive-accent: {accent} !important; + --interactive-accent-hover: {sub_accent} !important; + --interactive-hover: {current_line} !important; + + --text-accent: {accent} !important; + --text-accent-hover: {sub_accent} !important; + --nav-item-color-active: {accent} !important; + --nav-item-background-active: {surface} !important; + --tab-text-color-active: {accent} !important; + + --bold-color: {accent} !important; + --italic-color: {sub_accent} !important; + --title-color: {fg} !important; + --h1-color: {accent} !important; + --h2-color: {sub_accent} !important; + --h3-color: {fg} !important; + --h4-color: {fg} !important; + --h5-color: {fg} !important; + --h6-color: {fg} !important; + + --code-normal: {accent} !important; + --code-background: {surface} !important; + + --scrollbar-thumb-bg: {current_line} !important; + --status-bar-bg: {surface} !important; + --titlebar-background: {bg} !important; + --titlebar-background-focused: {bg} !important; +}} +""" + + vault_dirs = set() + + # Search common Documents and Home locations for .obsidian folders + search_bases = [ + home, + os.path.join(home, 'Documents'), + os.path.join(home, 'Obsidian'), + os.path.join(home, 'Vaults'), + os.path.join(home, 'Notes'), + os.path.join(home, '.var', 'app', 'md.obsidian.Obsidian', 'config', 'obsidian'), + os.path.join(home, '.config', 'obsidian') + ] + + for sb in search_bases: + if os.path.exists(sb): + obs_dir = os.path.join(sb, '.obsidian') + if os.path.isdir(obs_dir): + vault_dirs.add(obs_dir) + try: + for child in os.listdir(sb): + child_path = os.path.join(sb, child) + if os.path.isdir(child_path): + child_obs = os.path.join(child_path, '.obsidian') + if os.path.isdir(child_obs): + vault_dirs.add(child_obs) + except Exception: pass + + # Search registered vault paths in obsidian.json + obsidian_json_paths = [ + os.path.join(home, '.config', 'obsidian', 'obsidian.json'), + os.path.join(home, '.var', 'app', 'md.obsidian.Obsidian', 'config', 'obsidian', 'obsidian.json') + ] + + for ojp in obsidian_json_paths: + if os.path.exists(ojp): + try: + with open(ojp, 'r', encoding='utf-8') as f: + data = json.load(f) + vaults = data.get('vaults', {}) + if isinstance(vaults, dict): + for v_id, v_info in vaults.items(): + v_path = v_info.get('path') + if v_path: + obs_folder = os.path.join(v_path, '.obsidian') + if os.path.isdir(obs_folder): + vault_dirs.add(obs_folder) + except Exception: pass + + # Apply quickshell-theme.css and update appearance.json to enable the snippet automatically + for obs_dir in vault_dirs: + try: + snippets_dir = os.path.join(obs_dir, 'snippets') + os.makedirs(snippets_dir, exist_ok=True) + + css_path = os.path.join(snippets_dir, 'quickshell-theme.css') + with open(css_path, 'w', encoding='utf-8') as f: + f.write(obsidian_css) + + app_file = os.path.join(obs_dir, 'appearance.json') + app_data = {} + if os.path.exists(app_file): + try: + with open(app_file, 'r', encoding='utf-8') as f: + app_data = json.load(f) + except Exception: + app_data = {} + + enabled_snippets = app_data.get('enabledCssSnippets', []) + if not isinstance(enabled_snippets, list): + enabled_snippets = [] + + if 'quickshell-theme' not in enabled_snippets: + enabled_snippets.append('quickshell-theme') + app_data['enabledCssSnippets'] = enabled_snippets + + app_data['baseOption'] = 'dark' if is_dark else 'light' + + with open(app_file, 'w', encoding='utf-8') as f: + json.dump(app_data, f, indent=2) + except Exception: pass + def main(): parser = argparse.ArgumentParser() parser.add_argument('--bg', required=True) @@ -1472,6 +1607,7 @@ def main(): sync_vscode(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent, is_dark) sync_zen(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent, is_dark) sync_feishin(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent, is_dark, args.variantName) + sync_obsidian(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent, is_dark) sync_starship(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent, is_dark) sync_vim(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent, is_dark) sync_btop(args.bg, args.surface, args.currentLine, args.fg, args.accent, args.subAccent) @@ -1483,4 +1619,3 @@ def main(): if __name__ == '__main__': main() -