from typing import List, Dict, Optional from datetime import datetime from .colors import Colors from .progress import ProgressBar class EditOperation: def __init__(self, op_type: str, filepath: str, start_pos: int = 0, end_pos: int = 0, content: str = "", old_content: str = ""): self.op_type = op_type self.filepath = filepath self.start_pos = start_pos self.end_pos = end_pos self.content = content self.old_content = old_content self.timestamp = datetime.now() self.status = "pending" def format_operation(self) -> str: op_colors = { 'INSERT': Colors.GREEN, 'REPLACE': Colors.YELLOW, 'DELETE': Colors.RED, 'WRITE': Colors.BLUE } color = op_colors.get(self.op_type, Colors.RESET) status_icon = { 'pending': '○', 'in_progress': '◐', 'completed': '●', 'failed': '✗' }.get(self.status, '○') return f"{color}{status_icon} [{self.op_type}]{Colors.RESET} {self.filepath}" def format_details(self, show_content: bool = True) -> str: output = [self.format_operation()] if self.op_type in ('INSERT', 'REPLACE'): output.append(f" {Colors.GRAY}Position: {self.start_pos}-{self.end_pos}{Colors.RESET}") if show_content: if self.old_content: lines = self.old_content.split('\n') preview = lines[0][:60] + ('...' if len(lines[0]) > 60 or len(lines) > 1 else '') output.append(f" {Colors.RED}- {preview}{Colors.RESET}") if self.content: lines = self.content.split('\n') preview = lines[0][:60] + ('...' if len(lines[0]) > 60 or len(lines) > 1 else '') output.append(f" {Colors.GREEN}+ {preview}{Colors.RESET}") return '\n'.join(output) class EditTracker: def __init__(self): self.operations: List[EditOperation] = [] self.current_file: Optional[str] = None def add_operation(self, op_type: str, filepath: str, **kwargs) -> EditOperation: op = EditOperation(op_type, filepath, **kwargs) self.operations.append(op) self.current_file = filepath return op def mark_in_progress(self, operation: EditOperation): operation.status = "in_progress" def mark_completed(self, operation: EditOperation): operation.status = "completed" def mark_failed(self, operation: EditOperation): operation.status = "failed" def get_stats(self) -> Dict[str, int]: stats = { 'total': len(self.operations), 'completed': sum(1 for op in self.operations if op.status == 'completed'), 'pending': sum(1 for op in self.operations if op.status == 'pending'), 'in_progress': sum(1 for op in self.operations if op.status == 'in_progress'), 'failed': sum(1 for op in self.operations if op.status == 'failed') } return stats def get_completion_percentage(self) -> float: if not self.operations: return 0.0 stats = self.get_stats() return (stats['completed'] / stats['total']) * 100 def display_progress(self) -> str: if not self.operations: return f"{Colors.GRAY}No edit operations tracked{Colors.RESET}" output = [] output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}") output.append(f"{Colors.BOLD}{Colors.BLUE}EDIT OPERATIONS PROGRESS{Colors.RESET}") output.append(f"{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n") stats = self.get_stats() completion = self.get_completion_percentage() progress_bar = ProgressBar(total=stats['total'], width=40) progress_bar.current = stats['completed'] bar_display = progress_bar._get_bar_display() output.append(f"Progress: {bar_display}") output.append(f"{Colors.BLUE}Total: {stats['total']}, Completed: {stats['completed']}, " f"Pending: {stats['pending']}, Failed: {stats['failed']}{Colors.RESET}\n") output.append(f"{Colors.BOLD}Recent Operations:{Colors.RESET}") for i, op in enumerate(self.operations[-5:], 1): output.append(f"{i}. {op.format_operation()}") output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n") return '\n'.join(output) def display_timeline(self, show_content: bool = False) -> str: if not self.operations: return f"{Colors.GRAY}No edit operations tracked{Colors.RESET}" output = [] output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}") output.append(f"{Colors.BOLD}{Colors.BLUE}EDIT TIMELINE{Colors.RESET}") output.append(f"{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n") for i, op in enumerate(self.operations, 1): timestamp = op.timestamp.strftime("%H:%M:%S") output.append(f"{Colors.GRAY}[{timestamp}]{Colors.RESET} {i}.") output.append(op.format_details(show_content)) output.append("") stats = self.get_stats() output.append(f"{Colors.BOLD}Summary:{Colors.RESET}") output.append(f"{Colors.BLUE}Total operations: {stats['total']}, " f"Completed: {stats['completed']}, Failed: {stats['failed']}{Colors.RESET}") output.append(f"\n{Colors.BOLD}{Colors.BLUE}{'=' * 60}{Colors.RESET}\n") return '\n'.join(output) def display_summary(self) -> str: if not self.operations: return f"{Colors.GRAY}No edits to summarize{Colors.RESET}" stats = self.get_stats() files_modified = len(set(op.filepath for op in self.operations)) output = [] output.append(f"\n{Colors.BOLD}{Colors.GREEN}{'=' * 60}{Colors.RESET}") output.append(f"{Colors.BOLD}{Colors.GREEN}EDIT SUMMARY{Colors.RESET}") output.append(f"{Colors.BOLD}{Colors.GREEN}{'=' * 60}{Colors.RESET}\n") output.append(f"{Colors.GREEN}Files Modified: {files_modified}{Colors.RESET}") output.append(f"{Colors.GREEN}Total Operations: {stats['total']}{Colors.RESET}") output.append(f"{Colors.GREEN}Successful: {stats['completed']}{Colors.RESET}") if stats['failed'] > 0: output.append(f"{Colors.RED}Failed: {stats['failed']}{Colors.RESET}") output.append(f"\n{Colors.BOLD}Operations by Type:{Colors.RESET}") op_types = {} for op in self.operations: op_types[op.op_type] = op_types.get(op.op_type, 0) + 1 for op_type, count in sorted(op_types.items()): output.append(f" {op_type}: {count}") output.append(f"\n{Colors.BOLD}{Colors.GREEN}{'=' * 60}{Colors.RESET}\n") return '\n'.join(output) def clear(self): self.operations.clear() self.current_file = None tracker = EditTracker() def track_edit(op_type: str, filepath: str, **kwargs) -> EditOperation: return tracker.add_operation(op_type, filepath, **kwargs) def display_edit_progress() -> str: return tracker.display_progress() def display_edit_timeline(show_content: bool = False) -> str: return tracker.display_timeline(show_content) def display_edit_summary() -> str: return tracker.display_summary() def clear_tracker(): tracker.clear()