#!/usr/bin/env python3
"""
# Script ob-snippets
## Metadata
**Kind**: #obsidian/ob-script
**Language**: #python
**Parent**:: [[Obsidian Chore Scripts]], [[Executable Markdown File]]
## Synopsis
I use LuaSnip for snippets expansion. This script export the snippets to Obsidian.
Example:: [[Snippets - Obsidian]]
## Script
```python
# """
from collections import defaultdict
from pathlib import Path
import filecmp
import os
import tempfile
import json
import itertools
SYNTAX_MAP = {
'Anki': 'html',
'Bats': 'shell',
'CKB': 'markdown',
'Console': 'shell',
'CriticMarkup': 'markdown',
'Cryptape': 'markdown',
'Deckset': 'markdown',
'Envrc': 'shell',
'Git': 'markdown',
'GitHub Actions': 'yaml',
'GitHub ID': 'markdown',
'GitHub': 'markdown',
'Global': '',
'HTML': 'html',
'IdeaVim': 'vim',
'Java': 'java',
'Markdown': 'markdown',
'Mirror': 'shell',
'Nerd Font': '',
'Obsidian': 'markdown',
'Parallels': 'ruby',
'Pass': '',
'PowerShell': 'powershell',
'Profile': '',
'Projections': 'json',
'Prompt': 'markdown',
'Proxy': 'shell',
'Python': 'python',
'Rust': 'rust',
'SQL': 'sql',
'SSH': '',
'Shell': 'shell',
'Signature': 'markdown',
'Snippet': '',
'Sudo': '',
'Symbols': '',
'Tmux': 'shell',
'Unreal': 'cpp',
'Vim': 'vim',
'Wiki': 'wiki',
}
PUBLISH = {
'CKB': False,
'Cryptape': False,
'GitHub ID': False,
}
def collect_snippets_in_file(file):
snippets = json.load(file.open())
for name, snippet in snippets.items():
name_parts = name.split(' ➤ ', maxsplit=1)
if len(name_parts) == 2:
category, name = name_parts
else:
category = "Global"
snippet['category'] = category
snippet['name'] = name
yield snippet
def collect_snippets_in_directory(directory):
for root, _, files in os.walk(directory):
root = Path(root)
for file in files:
if file == 'global.code-snippets' or file.endswith('.json'):
yield from collect_snippets_in_file(root / file)
abbrev_file = Path.home() / '.dotfiles' / 'repos' / 'public' / \
'nvim' / 'plugin' / 'iy-public-init.vim'
for line in abbrev_file.open().readlines():
if line.startswith('noreabbrev vv'):
prefix, body = line.split()[1:]
snippet = {
'name': prefix[2:],
'category': 'Symbols',
'prefix': prefix,
'body': [body]
}
yield snippet
def categorize_snippets(snippets):
categories = defaultdict(list)
for snippet in snippets:
categories[snippet['category']].append(snippet)
return categories
def save_categories(categories, directory):
index_page_lines = [
'# ♯ Snippets Library\n',
]
for category, snippets in sorted(categories.items()):
index_page_lines.append(
f'- [[Snippets - {category}|{category}]] ({len(snippets)})')
syntax = SYNTAX_MAP[category]
with open(directory / f'Snippets - {category}.md', 'w', newline="\n") as fout:
publish = 'true' if PUBLISH.get(category, True) else 'false'
print(f'---\npublish: {publish}', file=fout)
if syntax != '':
print(f'syntax: {syntax}', file=fout)
print(f'---\n# Snippets - {category}', file=fout)
print('\n**Kind**:: #snippets-collection', file=fout)
print('**Source**:: #from/vsnip', file=fout)
print('**Generated by**:: [[ob-snippets]]', file=fout)
print(f'**Snippets**:: {len(snippets)}', file=fout)
for snippet in snippets:
print(
f'\n## {snippet["name"]} (`{snippet["prefix"]}`)\n', file=fout)
if 'description' in snippet:
print(snippet['description'], file=fout)
print('', file=fout)
print(f'```{syntax}', file=fout)
print('\n'.join(snippet["body"]), file=fout, end='')
print('\n```', file=fout)
with open(directory / '♯ Snippets Library.md', 'w', newline="\n") as fout:
print('\n'.join(index_page_lines), file=fout)
def main():
repos_dir = Path.home() / '.dotfiles' / 'repos'
pub_snips_dir = repos_dir / 'public' / 'nvim' / 'snippets'
priv_snips_dir = repos_dir / 'private' / 'nvim' / 'snippets'
pub_snippets = collect_snippets_in_directory(pub_snips_dir)
priv_snippets = collect_snippets_in_directory(priv_snips_dir)
categories = categorize_snippets(
itertools.chain(pub_snippets, priv_snippets))
tmp_dir = Path(tempfile.mkdtemp())
save_categories(categories, tmp_dir)
export_dir = Path('robot') / 'Snippets Library'
for root, _, files in os.walk(tmp_dir):
for f in files:
src_file = Path(root) / f
relative_path = src_file.relative_to(tmp_dir)
target_file = export_dir / relative_path
target_file.parent.mkdir(exist_ok=True)
is_new = not target_file.exists() or not filecmp.cmp(
src_file, target_file, shallow=False
)
if is_new:
print('NEW:', relative_path)
os.replace(src_file, target_file)
else:
# print('SKIP:', relative_path)
pass
if __name__ == '__main__':
main()
"""
# vim: ft=python
```
"""