b0229b6332
Scans codebases for TODO/FIXME/HACK/XXX comments and generates Markdown notes in an Obsidian vault. Includes Zed editor integration that runs on file save, plus a shell wrapper for CLI usage. Supports customizable vault paths, project names, and output directories.
64 lines
1.9 KiB
Python
64 lines
1.9 KiB
Python
"""Configuration and common utilities for Obsidian import."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
DEFAULT_CONFIG_PATH = Path.home() / ".config" / "obsidian-import" / "config.ini"
|
|
|
|
|
|
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
|
|
|
|
# Try common default locations
|
|
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 sanitize_filename(name: str) -> str:
|
|
"""Remove or replace characters unsafe for filenames."""
|
|
invalid = '<>:"/\\|?*'
|
|
for ch in invalid:
|
|
name = name.replace(ch, "_")
|
|
return name.strip(". ")
|
|
|
|
|
|
def ensure_unique_path(target: Path) -> Path:
|
|
"""If target exists, append a counter to make it unique."""
|
|
if not target.exists():
|
|
return target
|
|
stem = target.stem
|
|
suffix = target.suffix
|
|
parent = target.parent
|
|
counter = 1
|
|
while True:
|
|
new_name = f"{stem}_{counter}{suffix}"
|
|
candidate = parent / new_name
|
|
if not candidate.exists():
|
|
return candidate
|
|
counter += 1
|