"""Utility functions for Code Pattern Search CLI.""" import re from typing import Optional def validate_regex_pattern(pattern: str) -> tuple[bool, Optional[str]]: """Validate a regex pattern. Returns: tuple: (is_valid, error_message) """ try: re.compile(pattern) return True, None except re.error as e: return False, str(e) def sanitize_search_query(query: str) -> str: """Sanitize a search query for safe usage.""" return re.sub(r'[^\w\s\-_]', '', query).strip() def format_number(num: int) -> str: """Format a number with appropriate suffixes.""" if num >= 1_000_000: return f"{num / 1_000_000:.1f}M" elif num >= 1_000: return f"{num / 1_000:.1f}K" else: return str(num) def format_duration(seconds: float) -> str: """Format a duration in human-readable format.""" if seconds < 60: return f"{seconds:.1f}s" elif seconds < 3600: return f"{seconds / 60:.1f}m" else: return f"{seconds / 3600:.1f}h" def get_language_from_extension(extension: str) -> Optional[str]: """Get programming language from file extension.""" extension_map = { ".py": "Python", ".js": "JavaScript", ".ts": "TypeScript", ".jsx": "JavaScript React", ".tsx": "TypeScript React", ".java": "Java", ".go": "Go", ".rs": "Rust", ".cpp": "C++", ".c": "C", ".cs": "C#", ".rb": "Ruby", ".php": "PHP", ".swift": "Swift", ".kt": "Kotlin", ".scala": "Scala", ".html": "HTML", ".css": "CSS", ".json": "JSON", ".yaml": "YAML", ".yml": "YAML", ".md": "Markdown", ".sh": "Shell", ".xml": "XML", ".vue": "Vue", ".svelte": "Svelte", } return extension_map.get(extension.lower()) def truncate_text(text: str, max_length: int = 100, suffix: str = "...") -> str: """Truncate text to a maximum length.""" if len(text) <= max_length: return text return text[:max_length - len(suffix)] + suffix def calculate_similarity(str1: str, str2: str) -> float: """Calculate string similarity using Levenshtein distance.""" if str1 == str2: return 1.0 len1, len2 = len(str1), len(str2) if len1 == 0 or len2 == 0: return 0.0 matrix = [[0] * (len2 + 1) for _ in range(len1 + 1)] for i in range(len1 + 1): matrix[i][0] = i for j in range(len2 + 1): matrix[0][j] = j for i in range(1, len1 + 1): for j in range(1, len2 + 1): cost = 0 if str1[i - 1] == str2[j - 1] else 1 matrix[i][j] = min( matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost, ) max_len = max(len1, len2) return 1.0 - matrix[len1][len2] / max_len