4b7ddcb1c1
Integrates with Zed editor history and Git commits to track daily coding activity. Writes idempotent `## Coding Work` sections into Obsidian daily notes with project breakdowns and commit stats.
62 lines
2.0 KiB
Python
62 lines
2.0 KiB
Python
"""Configuration and common utilities for daily summary."""
|
|
|
|
import os
|
|
from datetime import datetime, timedelta, timezone
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
|
|
def get_vault_path(cli_vault: Optional[str] = None) -> Path:
|
|
"""Resolve the Obsidian vault path from CLI arg, env var, or default locations."""
|
|
if cli_vault:
|
|
vault = Path(cli_vault).expanduser().resolve()
|
|
if not vault.exists():
|
|
raise FileNotFoundError(f"Vault path does not exist: {vault}")
|
|
return vault
|
|
|
|
env_vault = os.environ.get("OBSIDIAN_VAULT")
|
|
if env_vault:
|
|
vault = Path(env_vault).expanduser().resolve()
|
|
if vault.exists():
|
|
return vault
|
|
|
|
obsidian_dir = Path.home() / "Obsidian"
|
|
if obsidian_dir.exists():
|
|
vaults = [d for d in obsidian_dir.iterdir() if d.is_dir()]
|
|
if len(vaults) == 1:
|
|
return vaults[0]
|
|
elif len(vaults) > 1:
|
|
raise RuntimeError(
|
|
f"Multiple vaults found in {obsidian_dir}. "
|
|
"Set OBSIDIAN_VAULT or use --vault."
|
|
)
|
|
|
|
raise RuntimeError(
|
|
"Could not determine Obsidian vault path. "
|
|
"Use --vault or set OBSIDIAN_VAULT environment variable."
|
|
)
|
|
|
|
|
|
def get_daily_notes_folder(vault_path: Path) -> Path:
|
|
"""Return the daily notes folder, defaulting to 'Daily Notes'."""
|
|
folder = os.environ.get("OBSIDIAN_DAILY_FOLDER", "Daily Notes")
|
|
return vault_path / folder
|
|
|
|
|
|
def date_range(dt: datetime) -> tuple[int, int]:
|
|
"""Return Unix timestamp range for the given datetime's date (start, end)."""
|
|
start = datetime(dt.year, dt.month, dt.day, tzinfo=dt.tzinfo or timezone.utc)
|
|
end = start + timedelta(days=1)
|
|
return int(start.timestamp()), int(end.timestamp())
|
|
|
|
|
|
def format_duration(seconds: int) -> str:
|
|
"""Format seconds as 'Xh Ym' or 'Ym'."""
|
|
if seconds < 60:
|
|
return f"{seconds}s"
|
|
hours, remainder = divmod(seconds, 3600)
|
|
minutes = remainder // 60
|
|
if hours:
|
|
return f"{hours}h {minutes}m"
|
|
return f"{minutes}m"
|