diff --git a/src/utils/__init__.py b/src/utils/__init__.py new file mode 100644 index 0000000..5353844 --- /dev/null +++ b/src/utils/__init__.py @@ -0,0 +1,70 @@ +"""Utility functions for file handling and output.""" + +from pathlib import Path +from typing import Optional + + +def get_file_language(file_path: Path) -> Optional[str]: + """Determine programming language from file extension.""" + extension_map = { + ".py": "python", + ".js": "javascript", + ".ts": "typescript", + ".jsx": "javascript", + ".tsx": "typescript", + } + return extension_map.get(file_path.suffix.lower()) + + +def is_supported_file(file_path: Path) -> bool: + """Check if file is supported for analysis.""" + return get_file_language(file_path) is not None + + +def read_source_file(file_path: Path) -> Optional[str]: + """Read source file contents.""" + try: + return file_path.read_text(encoding="utf-8") + except (UnicodeDecodeError, FileNotFoundError): + return None + + +def write_source_file(file_path: Path, content: str) -> bool: + """Write source file contents.""" + try: + file_path.write_text(content, encoding="utf-8") + return True + except (UnicodeDecodeError, FileNotFoundError, PermissionError): + return False + + +def create_backup(file_path: Path) -> Optional[Path]: + """Create a backup of the file.""" + try: + backup_path = file_path.with_suffix(file_path.suffix + ".bak") + backup_path.write_text(file_path.read_text(encoding="utf-8"), encoding="utf-8") + return backup_path + except (FileNotFoundError, PermissionError): + return None + + +def remove_backup(file_path: Path) -> bool: + """Remove a backup file.""" + try: + backup_path = file_path.with_suffix(file_path.suffix + ".bak") + if backup_path.exists(): + backup_path.unlink() + return True + except (FileNotFoundError, PermissionError): + return False + + +def count_lines_of_code(source_code: str) -> int: + """Count lines of code (excluding empty lines and comments).""" + lines = source_code.split("\n") + code_lines = 0 + for line in lines: + stripped = line.strip() + if stripped and not stripped.startswith("#"): + code_lines += 1 + return code_lines