""" TODO 解析器 — V2 修复 P1-8:列索引从表头推导,不再硬编码 cells[1]/cells[6]/cells[7]。 """ from __future__ import annotations import re from dataclasses import dataclass from pathlib import Path @dataclass class TodoTask: task_id: str task: str files_dirs: str = "" status: str = "TODO" done_when: str = "" validations: str = "" adr: str = "" def parse_tasks(todo_path: Path) -> list[TodoTask]: """从 todo.md 解析任务列表,动态检测列索引。""" if not todo_path.exists(): return [] content = todo_path.read_text(encoding="utf-8") lines = [l.strip() for l in content.splitlines() if l.strip()] # 找到 Markdown 表格头 header_idx = -1 for i, line in enumerate(lines): if line.startswith("|") and "Task" in line and "Status" in line: header_idx = i break if header_idx < 0: return [] # 解析列名 header_line = lines[header_idx] header_cols = [c.strip() for c in header_line.split("|") if c.strip()] # 建立列名 → 索引映射 col_map = {} for idx, col_name in enumerate(header_cols): col_name_lower = col_name.lower() if "task" in col_name_lower: col_map["task"] = idx elif "status" in col_name_lower: col_map["status"] = idx elif "files" in col_name_lower or "dir" in col_name_lower: col_map["files_dirs"] = idx elif "done" in col_name_lower or "when" in col_name_lower: col_map["done_when"] = idx elif "valid" in col_name_lower: col_map["validations"] = idx elif "adr" in col_name_lower: col_map["adr"] = idx # 跳过表头和分隔符 tasks = [] for line in lines[header_idx + 2:]: if not line.startswith("|"): continue cells = [c.strip() for c in line.split("|") if len(c.strip()) > 0] if not cells: continue task_cell = cells[col_map.get("task", 0)] if col_map.get("task", 0) < len(cells) else "" # 优先提取 [T-xxx] 方括号格式的 ID;若没有则尝试从开头提取 G-001/H-000 类短 ID tid_match = re.match(r"\[([A-Za-z0-9_\-\.]+)\]", task_cell) if tid_match: task_id = tid_match.group(1) else: short_match = re.match(r"^([A-Z]+-\d+[a-z]*)", task_cell) task_id = short_match.group(1) if short_match else task_cell task = task_cell status = cells[col_map.get("status", 1)] if col_map.get("status", 1) < len(cells) else "TODO" files_dirs = cells[col_map.get("files_dirs", 2)] if col_map.get("files_dirs", 2) < len(cells) else "" done_when = cells[col_map.get("done_when", 3)] if col_map.get("done_when", 3) < len(cells) else "" validations = cells[col_map.get("validations", 4)] if col_map.get("validations", 4) < len(cells) else "" adr = cells[col_map.get("adr", 5)] if col_map.get("adr", 5) < len(cells) else "" # 清理标记 task_id = re.sub(r"^\[|\]$", "", task_id).strip() if task_id and task_id != "---": tasks.append(TodoTask( task_id=task_id, task=task, files_dirs=files_dirs, status=status.upper() if status else "TODO", done_when=done_when, validations=validations, adr=adr, )) return tasks