from datetime import datetime
from typing import Dict, List, Optional
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()
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({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()