"""Write or append daily summaries to Obsidian notes.""" from datetime import datetime, timezone from pathlib import Path from typing import List from .git_tracker import RepoSummary from .zed_tracker import ProjectSummary DAILY_NOTE_FORMAT = "%Y-%m-%d" SECTION_HEADER = "## Coding Work" def _format_time(ts: int) -> str: """Format a Unix timestamp as HH:MM.""" dt = datetime.fromtimestamp(ts, tz=timezone.utc).astimezone() return dt.strftime("%H:%M") def generate_markdown( zed_projects: List[ProjectSummary], git_repos: List[RepoSummary], date: datetime, ) -> str: """Generate the markdown content for the daily summary.""" lines = [] lines.append(SECTION_HEADER) lines.append("") if not zed_projects and not git_repos: lines.append("No coding activity tracked today. 🌴") return "\n".join(lines) if zed_projects: lines.append("### Zed Editors") lines.append("") for project in zed_projects: langs = ( f" ({', '.join(sorted(project.languages))})" if project.languages else "" ) lines.append( f"- **{project.project}**{langs} β€” {len(project.files)} file(s)" ) # Show up to 5 most recent files for path, mtime in project.files[:5]: time_str = _format_time(mtime) lines.append(f" - `{Path(path).name}` at {time_str}") if len(project.files) > 5: lines.append(f" - *…and {len(project.files) - 5} more*") lines.append("") if git_repos: lines.append("### Git Commits") lines.append("") for repo in git_repos: lines.append( f"- **{repo.name}** β€” {len(repo.commits)} commit(s), " f"+{repo.total_insertions}/-{repo.total_deletions} lines, " f"{repo.total_files} file(s)" ) for commit in repo.commits: time_str = _format_time(commit.timestamp) lines.append(f" - `{commit.hash}` {commit.message} β€” {time_str}") lines.append("") return "\n".join(lines) # Backward compatibility alias _generate_markdown = generate_markdown def write_daily_summary( vault_path: Path, zed_projects: List[ProjectSummary], git_repos: List[RepoSummary], daily_folder: str = "Daily Notes", date: datetime = None, ) -> Path: """Write or append a coding summary to the Obsidian daily note.""" if date is None: date = datetime.now(timezone.utc).astimezone() note_dir = vault_path / daily_folder note_dir.mkdir(parents=True, exist_ok=True) note_name = date.strftime(DAILY_NOTE_FORMAT) note_path = note_dir / f"{note_name}.md" content = _generate_markdown(zed_projects, git_repos, date) if note_path.exists(): existing = note_path.read_text(encoding="utf-8") # If section already exists, replace it; otherwise append if SECTION_HEADER in existing: before, _, after = existing.partition(SECTION_HEADER) # Find the next section header or end of file next_section_idx = after.find("\n## ") if next_section_idx != -1: after = after[next_section_idx:] else: after = "" new_content = before.rstrip() + "\n\n" + content + "\n" + after.lstrip() else: new_content = existing.rstrip() + "\n\n" + content + "\n" else: new_content = f"# {note_name}\n\n" + content + "\n" note_path.write_text(new_content, encoding="utf-8") return note_path