from __future__ import annotations import stat from typing import TYPE_CHECKING import curses from ..items.Symlink import Symlink from ..items.AItems import AItem if TYPE_CHECKING: from .App import App class UI: def __init__(self, app: App): self._app = app HEADER_ROWS = 2 ERROR_COLOR = 5 def _get_attr(self, item: any, index: int) -> str: attr = curses.color_pair(item.color_pair) if index == self.app.navigator.cursor.pos: attr |= curses.A_REVERSE return attr def render(self, stdscr: curses.window) -> None: stdscr.erase() height, width = stdscr.getmaxyx() navigator = self.app.navigator stdscr.addstr(0, 0, str(navigator.history[-1])[:width - 1]) if navigator.error: stdscr.addstr(1, 0, navigator.error[:width - 1], curses.color_pair(self.ERROR_COLOR)) items = navigator.items available = max(0, height - self.HEADER_ROWS) for index in range(min(available, len(items))): item = items[index] self._render_item(stdscr, item, index, index + self.HEADER_ROWS, width) SIZE_UNITS = ("", "K", "M", "G", "T", "P") @staticmethod def _format_size(size: int) -> str: value = float(size) for unit in UI.SIZE_UNITS: if value < 1024: return str(int(value)) if unit == "" else f"{value:.1f}{unit}" value /= 1024 return f"{value:.1f}E" ARROW = " -> " ARROW_LEN = len(ARROW) def _render_item(self, stdscr: curses.window, item: AItem, index: int, row: int, width: int) -> None: name, size, perm = item.fields() name_len = len(name) col_width = int(width / 3) attr = self._get_attr(item, index) stdscr.addstr(row, 0, name.ljust(col_width), attr) if type(item) is Symlink: attr_arrow = curses.color_pair(0) attr_target = curses.color_pair(Symlink.target_color(item.point_to)) if index == self.app.navigator.cursor.pos: attr_arrow |= curses.A_REVERSE attr_target |= curses.A_REVERSE stdscr.addstr(row, name_len, self.ARROW, attr_arrow) stdscr.addstr(row, name_len + self.ARROW_LEN, str(item.point_to), attr_target) stdscr.addstr(row, col_width, self._format_size(size).ljust(col_width * 2), attr) stdscr.addstr(row, col_width * 2, stat.filemode(perm), attr) @property def app(self) -> App: return self._app