Files
clide/legacy/clide/models/todos.py
T
jpmschweitzerandClaude Opus 4.7 a355751437 move python clide to legacy/
Clide is being rebuilt as a Flutter desktop app. The Python Textual
implementation moves wholesale into legacy/ rather than being deleted:
its pane model, panel set, git skills, and panel communication design
are real thought that should remain readable next to the new code
while the rebuild finds its shape. Git's rename tracking preserves
history, so `git log -- legacy/` still works.

The Flutter rebuild lives at the repo root alongside a Go sidecar
(the architecture claudian was heading toward, which folds into
clide as a core component rather than a separate plugin project).
Bootstrap of the new shape lands in subsequent commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:30:51 +02:00

139 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""TODO comments Pydantic models."""
from enum import Enum
from pathlib import Path
from pydantic import BaseModel, ConfigDict
class TodoType(str, Enum):
"""Type of TODO comment."""
TODO = "TODO"
FIXME = "FIXME"
HACK = "HACK"
XXX = "XXX"
NOTE = "NOTE"
BUG = "BUG"
OPTIMIZE = "OPTIMIZE"
REVIEW = "REVIEW"
class ProjectTodoItem(BaseModel):
"""A TODO item from TODO.md file."""
model_config = ConfigDict(strict=True, frozen=True)
text: str
section: str # Top-level section (## heading)
subsection: str | None = None # Optional subsection (### heading)
line: int # Line number in TODO.md
checked: bool = False # Whether the checkbox is checked
@property
def category(self) -> str:
"""Get full category path."""
if self.subsection:
return f"{self.section} {self.subsection}"
return self.section
@property
def icon(self) -> str:
"""Icon for display."""
return "☑" if self.checked else "☐"
class TodoItem(BaseModel):
"""A single TODO comment found in code."""
model_config = ConfigDict(strict=True, frozen=True)
file_path: Path
line: int
column: int
todo_type: TodoType
text: str
context_line: str # The full line containing the TODO
@property
def location(self) -> str:
"""Human-readable location string."""
return f"{self.file_path}:{self.line}"
@property
def type_icon(self) -> str:
"""Icon for TODO type."""
icons = {
TodoType.TODO: "☐",
TodoType.FIXME: "🔧",
TodoType.HACK: "⚡",
TodoType.XXX: "❗",
TodoType.NOTE: "📝",
TodoType.BUG: "🐛",
TodoType.OPTIMIZE: "⚡",
TodoType.REVIEW: "👀",
}
return icons[self.todo_type]
class TodosSummary(BaseModel):
"""Summary of TODOs in the workspace."""
model_config = ConfigDict(strict=True, frozen=True)
todo_count: int = 0
fixme_count: int = 0
hack_count: int = 0
other_count: int = 0
project_todo_count: int = 0 # Count from TODO.md
project_done_count: int = 0 # Checked items in TODO.md
@property
def total(self) -> int:
"""Total number of code TODOs."""
return self.todo_count + self.fixme_count + self.hack_count + self.other_count
@property
def project_total(self) -> int:
"""Total number of project TODOs."""
return self.project_todo_count + self.project_done_count
@property
def display_text(self) -> str:
"""Text for tab badge."""
return f"✓{self.total}"
class TodosState(BaseModel):
"""State of the TODOs panel."""
model_config = ConfigDict(strict=True)
items: list[TodoItem] = []
project_items: list[ProjectTodoItem] = [] # Items from TODO.md
summary: TodosSummary = TodosSummary()
filter_type: TodoType | None = None
selected_index: int | None = None
group_by_file: bool = True
show_completed_project_todos: bool = False # Toggle for checked items
def items_for_file(self, path: Path) -> list[TodoItem]:
"""Get TODO items for a specific file."""
return [item for item in self.items if item.file_path == path]
def items_by_type(self, todo_type: TodoType) -> list[TodoItem]:
"""Get TODO items of a specific type."""
return [item for item in self.items if item.todo_type == todo_type]
def project_items_by_section(self, section: str) -> list[ProjectTodoItem]:
"""Get project TODO items for a specific section."""
return [item for item in self.project_items if item.section == section]
def get_project_sections(self) -> list[str]:
"""Get unique sections from project TODOs."""
sections: list[str] = []
for item in self.project_items:
if item.section not in sections:
sections.append(item.section)
return sections