from dataclasses import dataclass from pathlib import Path from .buffer import Buffer from .selection import Selection class StateChange: def invert(self) -> "StateChange" | None: return None @dataclass class SetCurrentSelection(StateChange): old_selection: Selection new_selection: Selection def invert(self) -> "SetCurrentSelection": return SetCurrentSelection( old_selection=self.new_selection, new_selection=self.old_selection, ) @dataclass class SetCurrentBuffer(StateChange): old_buffer: Buffer new_buffer: Buffer def invert(self) -> "SetCurrentBuffer": return SetCurrentBuffer( old_buffer=self.new_buffer, new_buffer=self.old_buffer, ) @dataclass class ModifyBuffer(StateChange): buffer: Buffer old_start: int old_end: int old_content: str new_content: str def invert(self) -> None: # TODO: implement return None @dataclass class CreateBuffer(StateChange): buffer: Buffer file: Path | None @dataclass class DeleteBuffer(StateChange): buffer: Buffer @dataclass class EditorState: current_buffer: Buffer current_selection: Selection buffer_to_file: dict[Buffer, Path | None] history: list[StateChange] def commit(self, change: StateChange) -> "EditorState": match change: case SetCurrentSelection(_, new_selection): self.current_selection = new_selection case SetCurrentBuffer(_, new_buffer): self.current_buffer = new_buffer case ModifyBuffer(buffer, old_start, old_end, _, new_content): self.current_buffer.content = ( self.current_buffer.content[:old_start] + new_content + self.current_buffer.content[old_end:] ) case CreateBuffer(buffer, file): self.buffer_to_file[buffer] = file case DeleteBuffer(buffer): del self.buffer_to_file[buffer] self.history.append(change) return self def commit_changes(self, changes: list[StateChange]) -> "EditorState": for change in changes: self.commit(change) return self Result = tuple[Selection, list[StateChange]]