retronews

a featureful fork of the luke8086/retronews hn+lobste.rs tui
Log | Files | Refs | README | LICENSE

commit 5e5673e83858760f26eb8bceb8c4a80c18146598
parent e26a73875b39bf4ab7ce1e7234b462b81899030c
Author: luke8086 <55237178+luke8086@users.noreply.github.com>
Date:   Sat, 23 Jul 2022 22:16:09 +0000

Refactor computation of the layout to a single function

Diffstat:
Mretronews.py | 107++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 71 insertions(+), 36 deletions(-)

diff --git a/retronews.py b/retronews.py @@ -24,7 +24,6 @@ from typing import Any, Dict, Generator, List, Optional, TypedDict, TypeVar, Uni T = TypeVar("T") QUOTE_REX = re.compile(r"^(> ?)+") -MENU_HEIGHT = 1 class Colors: @@ -77,6 +76,20 @@ class Message: index_tree: str = "" +@dataclass(frozen=True) +class Layout: + lines: int = 0 + cols: int = 0 + top_menu_row: int = 0 + index_start: int = 0 + index_height: int = 0 + index_menu_row: int = 0 + pager_start: Optional[int] = None + pager_height: Optional[int] = None + pager_menu_row: Optional[int] = None + flash_menu_row: int = 0 + + @dataclass class AppState: screen: "curses._CursesWindow" @@ -85,6 +98,7 @@ class AppState: messages: List[Message] = field(default_factory=list) messages_by_id: Dict[str, Message] = field(default_factory=dict) selected_message: Optional[Message] = None + layout: Layout = field(default_factory=Layout) pager_visible: bool = False pager_offset: int = 0 raw_mode: bool = False @@ -188,15 +202,13 @@ def cmd_index_down(app: AppState) -> None: def cmd_page_up(app: AppState) -> None: - index_height = app_get_index_height(app) - pos = app.selected_message.index_position - index_height if app.selected_message else 0 + pos = app.selected_message.index_position - app.layout.index_height if app.selected_message else 0 pos = max(pos, 0) app_select_message(app, list_get(app.messages, pos, app.selected_message)) def cmd_page_down(app: AppState) -> None: - index_height = app_get_index_height(app) - pos = app.selected_message.index_position + index_height if app.selected_message else 0 + pos = app.selected_message.index_position + app.layout.index_height if app.selected_message else 0 pos = min(pos, len(app.messages) - 1) app_select_message(app, list_get(app.messages, pos, app.selected_message)) @@ -416,25 +428,21 @@ def app_render_pager_line(app: AppState, row: int, line: str) -> None: app.screen.addstr(" ") -def app_render_pager(app: AppState, top: int, height: int) -> None: +def app_render_pager(app: AppState) -> None: message = app.selected_message + start = app.layout.pager_start + height = app.layout.pager_height - if message is None: + if message is None or start is None or height is None: return for i in range(height): line = list_get(message.lines, i + app.pager_offset) or "" - app_render_pager_line(app, i + top, line) - - -def app_get_index_height(app: AppState) -> int: - lines = app.screen.getmaxyx()[0] - max_height = lines - 3 * MENU_HEIGHT - return (max_height // 3) if app.pager_visible else max_height + app_render_pager_line(app, i + start, line) def app_render_index_row(app: AppState, row: int, message: Message) -> None: - cols = app.screen.getmaxyx()[1] + cols = app.layout.cols date = message.date.strftime("%Y-%m-%d %H:%M") author = message.author[:10].ljust(10) @@ -453,7 +461,9 @@ def app_render_index_row(app: AppState, row: int, message: Message) -> None: app.screen.chgat(row, 34 + len(message.index_tree), cols - 34 - len(message.index_tree), subject_attr) -def app_render_index(app: AppState, height: int) -> None: +def app_render_index(app: AppState) -> None: + height = app.layout.index_height + offset = app.selected_message.index_position - height // 2 if app.selected_message else 0 offset = min(offset, len(app.messages) - height) offset = max(offset, 0) @@ -461,45 +471,70 @@ def app_render_index(app: AppState, height: int) -> None: rows_to_render = min(height, len(app.messages) - offset) for i in range(rows_to_render): - app_render_index_row(app, MENU_HEIGHT + i, app.messages[i + offset]) + app_render_index_row(app, app.layout.index_start + i, app.messages[i + offset]) -def app_render_menus(app: AppState, index_height: int) -> None: - (lines, cols) = app.screen.getmaxyx() - top_menu_row = 0 - index_menu_row = MENU_HEIGHT + index_height - pager_menu_row = lines - 2 * MENU_HEIGHT - flash_menu_row = lines - MENU_HEIGHT +def app_render_menus(app: AppState) -> None: + lt = app.layout top_menu = "q:Quit n:Next p:Prev j:Down k:Up <space>:Open x:Close s:Star r:Raw" - app.screen.insstr(top_menu_row, 0, top_menu[:cols].ljust(cols), app.colors.menu | curses.A_BOLD) - app.screen.insstr(index_menu_row, 0, "index menu".ljust(cols), app.colors.menu | curses.A_BOLD) + app.screen.insstr(lt.top_menu_row, 0, top_menu[: lt.cols].ljust(lt.cols), app.colors.menu | curses.A_BOLD) + app.screen.insstr(lt.index_menu_row, 0, "index menu".ljust(lt.cols), app.colors.menu | curses.A_BOLD) - if app.pager_visible: - app.screen.insstr(pager_menu_row, 0, "pager menu".ljust(cols), app.colors.menu | curses.A_BOLD) + if lt.pager_menu_row is not None: + app.screen.insstr(lt.pager_menu_row, 0, "pager menu".ljust(lt.cols), app.colors.menu | curses.A_BOLD) - app.screen.insstr(flash_menu_row, 0, app.flash or "") + app.screen.insstr(lt.flash_menu_row, 0, app.flash or "") def app_render(app: AppState) -> None: + app.layout = app_compute_layout(app) app.screen.erase() - index_height = app_get_index_height(app) - - app_render_menus(app, index_height) - app_render_index(app, index_height) + app_render_menus(app) + app_render_index(app) if app.pager_visible: - lines = app.screen.getmaxyx()[0] - pager_top = index_height + 2 * MENU_HEIGHT - pager_height = lines - pager_top - 2 * MENU_HEIGHT - app_render_pager(app, pager_top, pager_height) + app_render_pager(app) app.screen.refresh() app.flash = "" +def app_compute_layout(app: AppState) -> Layout: + (lines, cols) = app.screen.getmaxyx() + + index_start = 1 + max_index_height = lines - 3 + index_height = (max_index_height // 3) if app.pager_visible else max_index_height + index_menu_row = index_start + index_height + + if app.pager_visible: + pager_start = index_start + index_height + 1 + pager_height = lines - pager_start - 2 + pager_menu_row = lines - 2 + else: + pager_start = None + pager_height = None + pager_menu_row = None + + flash_menu_row = lines - 1 + + return Layout( + lines=lines, + cols=cols, + top_menu_row=0, + index_start=index_start, + index_height=index_height, + index_menu_row=index_menu_row, + pager_start=pager_start, + pager_height=pager_height, + pager_menu_row=pager_menu_row, + flash_menu_row=flash_menu_row, + ) + + def app_init_logging() -> None: format = "%(asctime)s %(levelname)s: %(message)s" stream = open("tmp/retronews.log", "a")