1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"""Default landing page for the pgt TUI."""
from __future__ import annotations
from typing import Literal
from unicurses import ( # type: ignore[import-untyped]
A_BOLD,
A_REVERSE,
KEY_RESIZE,
)
from pygittools.tui.branches import current_branch_name
from pygittools.tui.changes_list import ChangesList
from pygittools.tui.commit_draft import load_commit_draft
from pygittools.tui.draw import draw_line
from pygittools.tui.input_context import InputMode, input_context, nav_context
from pygittools.tui.types import Page, PageAction, PageContext, PageResult
_HEADER_ROWS = 5
_REPO_ROW = 2
_BRANCH_ROW = 3
_HeaderFocus = Literal["changes", "repo", "branch"]
class HomePage:
title = "pgt"
def __init__(self) -> None:
self._ctx: PageContext | None = None
self._changes = ChangesList()
self._header_focus: _HeaderFocus = "changes"
self._input_mode: InputMode = nav_context()
@property
def header_focus(self) -> _HeaderFocus:
return self._header_focus
def set_header_focus(self, focus: _HeaderFocus) -> None:
self._header_focus = focus
@property
def page_context(self) -> PageContext | None:
return self._ctx
@property
def changes(self) -> ChangesList:
return self._changes
def on_enter(self, ctx: PageContext) -> None:
self._ctx = ctx
self._header_focus = "changes"
self._input_mode = nav_context()
self._changes.set_commit_message(load_commit_draft(ctx.repo_path, ctx.repo))
self._changes.refresh(ctx.repo)
def status_text(self) -> str:
return self._input_mode.status_hint(self)
def draw(self, stdscr: int, height: int, width: int) -> None:
del stdscr
ctx = self._ctx
if ctx is None:
return
self._changes.refresh(ctx.repo)
worktree = ctx.repo.workdir or str(ctx.repo_path)
branch = current_branch_name(ctx.repo)
header_lines: list[tuple[str, int]] = [
("pgt", A_BOLD),
("", 0),
(f"Repository: {worktree}", 0),
(f"Branch: {branch}", 0),
("", 0),
]
for row, (text, attr) in enumerate(header_lines):
if row >= height:
break
if row == _REPO_ROW and self._header_focus == "repo":
attr = A_REVERSE
if row == _BRANCH_ROW and self._header_focus == "branch":
attr = A_REVERSE
draw_line(row, 0, text, width, attr)
list_height = max(0, height - _HEADER_ROWS)
if list_height > 0 and height > _HEADER_ROWS:
self._changes.draw(_HEADER_ROWS, list_height, width, highlight=self._header_focus == "changes")
def handle_key(self, key: int) -> PageResult:
if key in (ord("q"), ord("Q")):
return PageResult(action=PageAction.QUIT)
if key == KEY_RESIZE:
return PageResult()
dispatch = self._input_mode.dispatch_key(self, key)
if dispatch.next_mode == "input":
self._input_mode = input_context()
elif dispatch.next_mode == "nav":
self._input_mode = nav_context()
if dispatch.page_result is not None:
return dispatch.page_result
return PageResult()
def home_page() -> Page:
return HomePage()