"""Fish history parser.""" import os import json from datetime import datetime from pathlib import Path from typing import List, Optional from .base import HistoryParser, ParsedCommand class FishHistoryParser(HistoryParser): """Parser for Fish shell history files.""" SHELL_NAME = "fish" DEFAULT_HISTORY_DIR = os.path.expanduser("~/.config/fish/history") def get_default_history_locations(self) -> List[str]: """Return default locations for fish history files.""" history_dir = Path(self.DEFAULT_HISTORY_DIR) if history_dir.exists() and history_dir.is_dir(): return list(history_dir.glob("*.json")) return [] def parse_file(self, filepath: str) -> List[ParsedCommand]: """Parse a fish history file.""" try: with open(filepath, 'r', encoding='utf-8', errors='replace') as f: content = f.read() return self.parse_content(content) except FileNotFoundError: return [] except Exception: return [] def parse_content(self, content: str) -> List[ParsedCommand]: """Parse fish history content from a string.""" commands = [] try: data = json.loads(content) if isinstance(data, list): for line_num, item in enumerate(data, start=1): if isinstance(item, dict) and 'text' in item: timestamp = None if 'timestamp' in item: try: timestamp = datetime.fromtimestamp(item['timestamp']) except (ValueError, TypeError): pass cmd = ParsedCommand( raw_command=item['text'], timestamp=timestamp, line_number=line_num ) commands.append(cmd) except json.JSONDecodeError: pass return commands def parse_all_history_files(self) -> List[ParsedCommand]: """Parse all fish history files in the default directory.""" all_commands = [] locations = self.get_default_history_locations() for filepath in locations: all_commands.extend(self.parse_file(str(filepath))) return all_commands