148 lines
4.1 KiB
Python
148 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
# /// script
|
|
# dependencies = ["python-frontmatter", "pyyaml"]
|
|
# ///
|
|
"""
|
|
Create a new note in the Obsidian vault with proper frontmatter.
|
|
|
|
Usage:
|
|
uv run create-note.py "title" "content" [--folder path] [--tags tag1,tag2] [--related "[[Note]]"]
|
|
|
|
Arguments:
|
|
title - Note title (will be used for filename)
|
|
content - Note content (markdown)
|
|
--folder - Folder path relative to vault (default: Geoffrey/Research)
|
|
--tags - Comma-separated tags
|
|
--related - Comma-separated related notes as wiki-links
|
|
|
|
Examples:
|
|
uv run create-note.py "AI Model Comparison" "Content..." --folder Geoffrey/Research --tags research,ai
|
|
uv run create-note.py "Meeting Notes" "Content..." --folder Meetings --related "[[John Smith]],[[Project]]"
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import json
|
|
import re
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
import frontmatter
|
|
|
|
VAULT_PATH = Path.home() / "Library/Mobile Documents/iCloud~md~obsidian/Documents/Personal_Notes"
|
|
|
|
|
|
def slugify(title: str) -> str:
|
|
"""Convert title to filename-safe slug."""
|
|
# Replace spaces with hyphens, remove special chars
|
|
slug = re.sub(r'[^\w\s-]', '', title.lower())
|
|
slug = re.sub(r'[-\s]+', '-', slug).strip('-')
|
|
return slug
|
|
|
|
|
|
def create_note(
|
|
title: str,
|
|
content: str,
|
|
folder: str = "Geoffrey/Research",
|
|
tags: list[str] = None,
|
|
related: list[str] = None
|
|
) -> str:
|
|
"""Create a new note with frontmatter."""
|
|
|
|
# Ensure folder exists
|
|
folder_path = VAULT_PATH / folder
|
|
folder_path.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Generate filename
|
|
date_prefix = datetime.now().strftime("%Y-%m-%d")
|
|
slug = slugify(title)
|
|
filename = f"{date_prefix}-{slug}.md"
|
|
file_path = folder_path / filename
|
|
|
|
# Check if file exists
|
|
if file_path.exists():
|
|
# Add timestamp to make unique
|
|
timestamp = datetime.now().strftime("%H%M%S")
|
|
filename = f"{date_prefix}-{slug}-{timestamp}.md"
|
|
file_path = folder_path / filename
|
|
|
|
# Build frontmatter
|
|
metadata = {
|
|
"created": datetime.now().strftime("%Y-%m-%d"),
|
|
"source": "geoffrey"
|
|
}
|
|
|
|
if tags:
|
|
metadata["tags"] = ["geoffrey"] + [t.strip() for t in tags if t.strip()]
|
|
else:
|
|
metadata["tags"] = ["geoffrey"]
|
|
|
|
if related:
|
|
metadata["related"] = [r.strip() for r in related if r.strip()]
|
|
|
|
# Create the post
|
|
post = frontmatter.Post(content)
|
|
post.metadata = metadata
|
|
|
|
# Add title as H1 if not already present
|
|
if not content.strip().startswith('#'):
|
|
post.content = f"# {title}\n\n{content}"
|
|
|
|
# Write file
|
|
with open(file_path, 'w', encoding='utf-8') as f:
|
|
f.write(frontmatter.dumps(post))
|
|
|
|
return str(file_path.relative_to(VAULT_PATH))
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 3:
|
|
print("Usage: uv run create-note.py \"title\" \"content\" [--folder path] [--tags t1,t2] [--related \"[[Note]]\"]")
|
|
sys.exit(1)
|
|
|
|
title = sys.argv[1]
|
|
content = sys.argv[2]
|
|
folder = "Geoffrey/Research"
|
|
tags = []
|
|
related = []
|
|
|
|
# Parse arguments
|
|
i = 3
|
|
while i < len(sys.argv):
|
|
if sys.argv[i] == "--folder" and i + 1 < len(sys.argv):
|
|
folder = sys.argv[i + 1]
|
|
i += 2
|
|
elif sys.argv[i] == "--tags" and i + 1 < len(sys.argv):
|
|
tags = sys.argv[i + 1].split(',')
|
|
i += 2
|
|
elif sys.argv[i] == "--related" and i + 1 < len(sys.argv):
|
|
related = sys.argv[i + 1].split(',')
|
|
i += 2
|
|
else:
|
|
i += 1
|
|
|
|
print(f"Creating note: {title}")
|
|
print(f"Folder: {folder}")
|
|
if tags:
|
|
print(f"Tags: {', '.join(tags)}")
|
|
if related:
|
|
print(f"Related: {', '.join(related)}")
|
|
|
|
relative_path = create_note(title, content, folder, tags, related)
|
|
full_path = VAULT_PATH / relative_path
|
|
|
|
print(f"\nNote created: {relative_path}")
|
|
|
|
# Output JSON for programmatic use
|
|
result = {
|
|
"success": True,
|
|
"path": relative_path,
|
|
"full_path": str(full_path),
|
|
"folder": folder,
|
|
"title": title
|
|
}
|
|
print(f"\n{json.dumps(result)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|