diff --git a/src/shell_history_search/parsers/zsh.py b/src/shell_history_search/parsers/zsh.py new file mode 100644 index 0000000..4030368 --- /dev/null +++ b/src/shell_history_search/parsers/zsh.py @@ -0,0 +1,64 @@ +from pathlib import Path +from typing import Iterator +import re +import socket + +from shell_history_search.parsers import HistoryEntry, HistoryParser + + +class ZshHistoryParser(HistoryParser): + shell_type = "zsh" + + def get_history_path(self) -> Path: + return Path.home() / ".zsh_history" + + def parse(self, history_path: Path) -> Iterator[HistoryEntry]: + extended_line_pattern = re.compile( + r":\s*(\d+)\s*:\s*0;\s*(.+)$" + ) + basic_line_pattern = re.compile( + r":\s*(\d+)\s*:\s*;\s*(.+)$" + ) + + for line in self.read_history_file(history_path): + line = line.strip() + if not line: + continue + + extended_match = extended_line_pattern.match(line) + if extended_match: + timestamp_str = extended_match.group(1) + command = extended_match.group(2) + else: + basic_match = basic_line_pattern.match(line) + if basic_match: + timestamp_str = basic_match.group(1) + command = basic_match.group(2) + else: + if line.startswith(":"): + continue + if line.startswith("#"): + continue + entry = HistoryEntry( + command=line, + shell_type=self.shell_type, + timestamp=None, + hostname=None, + command_hash=HistoryEntry.create_hash(line), + ) + yield entry + continue + + try: + timestamp = int(timestamp_str) + except ValueError: + timestamp = None + + entry = HistoryEntry( + command=command, + shell_type=self.shell_type, + timestamp=timestamp, + hostname=socket.gethostname(), + command_hash=HistoryEntry.create_hash(command), + ) + yield entry \ No newline at end of file