import os from pathlib import Path from ..items.AItems import AItem from ..items.Folder import Folder from ..items.Symlink import Symlink from . import Sort from .Config import Config from .Cursor import Cursor class Navigator: def __init__(self, path: Path, config: Config) -> None: self._config = config self._sort_mode = config.sort_mode self._history = [path] self._cursor = Cursor() self._current: Folder | None = None self._items: list[AItem] = [] self._error: str | None = None self._load() def _load(self) -> None: self._error = None try: self._current = Folder(self._history[-1]) self._items = Sort.sort_items(self._current.children(), self._sort_mode) except FileNotFoundError: self._items = [] except PermissionError: self._items = [] self._error = f"Permission denied: {self._history[-1]}" def refresh(self) -> None: self._load() def cycle_sort(self) -> None: self._sort_mode = Sort.next_mode(self._sort_mode) self._items = Sort.sort_items(self._items, self._sort_mode) def _reset_cursor(self) -> None: if self._config.cursor_reset == "keep": self._cursor.clamp(len(self._items)) else: self._cursor.resete() def _navigate_to(self, path: Path) -> bool: if not os.access(path, os.R_OK | os.X_OK): self._error = f"Permission denied: {path}" return False self._history.append(path) self._error = None self._load() self._reset_cursor() return True def enter(self, item: AItem) -> bool: if not item.is_navigable(): return False path = item.point_to if isinstance(item, Symlink) else item.path return self._navigate_to(path) def up(self) -> bool: parent = self._history[-1].parent if parent == self._history[-1]: return False return self._navigate_to(parent) def back(self) -> bool: if len(self._history) <= 1: return False self._history.pop() self._load() self._reset_cursor() return True @property def current(self) -> Folder: return self._current @property def items(self) -> list[AItem]: return self._items @property def history(self) -> list[Path]: return self._history @property def cursor(self) -> Cursor: return self._cursor @property def error(self) -> str | None: return self._error