Skip to content

Commit

Permalink
Docstrings for TUI.
Browse files Browse the repository at this point in the history
  • Loading branch information
tcdent committed Feb 10, 2025
1 parent 8531d46 commit fa4f7ca
Showing 1 changed file with 68 additions and 12 deletions.
80 changes: 68 additions & 12 deletions agentstack/tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class RenderException(Exception):
POS_ABSOLUTE = "absolute"

Check warning on line 30 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L29-L30

Added lines #L29 - L30 were not covered by tests


class Node: # TODO this needs a better name
class Node:

Check warning on line 33 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L33

Added line #L33 was not covered by tests
"""
A simple data node that can be updated and have callbacks. This is used to
populate and retrieve data from an input field inside the user interface.
Expand Down Expand Up @@ -59,6 +59,17 @@ def remove_callback(self, callback):


class Key:

Check warning on line 61 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L61

Added line #L61 was not covered by tests
"""
Conversions and convenience methods for key codes.
Provides booleans about the key pressed:
`key.BACKSPACE`
`key.is_numeric`
`key.is_alpha`
...
"""

const = {

Check warning on line 73 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L73

Added line #L73 was not covered by tests
'UP': 259,
'DOWN': 258,
Expand All @@ -75,7 +86,7 @@ class Key:
def __init__(self, ch: int):
self.ch = ch

Check warning on line 87 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L86-L87

Added lines #L86 - L87 were not covered by tests

def __getattr__(self, name):
def __getattr__(self, name) -> bool:
try:
return self.ch == self.const[name]
except KeyError:
Expand All @@ -86,11 +97,11 @@ def chr(self):
return chr(self.ch)

Check warning on line 97 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L95-L97

Added lines #L95 - L97 were not covered by tests

@property
def is_numeric(self):
def is_numeric(self) -> bool:
return self.ch >= 48 and self.ch <= 57

Check warning on line 101 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L99-L101

Added lines #L99 - L101 were not covered by tests

@property
def is_alpha(self):
def is_alpha(self) -> bool:
return self.ch >= 65 and self.ch <= 122

Check warning on line 105 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L103-L105

Added lines #L103 - L105 were not covered by tests


Expand Down Expand Up @@ -248,6 +259,12 @@ def initialize(cls) -> None:


class ColorAnimation(Color):

Check warning on line 261 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L261

Added line #L261 was not covered by tests
"""
Animate between two colors over a duration.
Compatible interface with `Color` to add animation to element's color.
"""

start: Color
end: Color
reversed: bool = False
Expand All @@ -273,13 +290,13 @@ def to_curses(self) -> int:
self.end.reversed = True

Check warning on line 290 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L289-L290

Added lines #L289 - L290 were not covered by tests
elif self.start.reversed:
self.reversed = True

Check warning on line 292 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L292

Added line #L292 was not covered by tests

if self.bold:
self.start.bold = True
self.end.bold = True

Check warning on line 296 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L295-L296

Added lines #L295 - L296 were not covered by tests
elif self.start.bold:
self.bold = True

Check warning on line 298 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L298

Added line #L298 was not covered by tests

elapsed = time.time() - self._start_time

Check warning on line 300 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L300

Added line #L300 was not covered by tests
if elapsed > self.duration:
if self.loop:
Expand Down Expand Up @@ -308,6 +325,12 @@ def to_curses(self) -> int:


class Renderable:

Check warning on line 327 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L327

Added line #L327 was not covered by tests
"""
A base class for all renderable modules.
Handles sizing, positioning, and inserting the module into the grid.
"""

_grid: Optional[curses.window] = None
y: int
x: int
Expand All @@ -331,7 +354,6 @@ def __repr__(self):

@property
def grid(self):

Check warning on line 356 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L355-L356

Added lines #L355 - L356 were not covered by tests
# TODO cleanup
# TODO validate that coords and size are within the parent window and give
# an explanatory error message.
if not self._grid:
Expand All @@ -352,6 +374,7 @@ def grid(self):
return self._grid

Check warning on line 374 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L373-L374

Added lines #L373 - L374 were not covered by tests

def move(self, y: int, x: int):

Check warning on line 376 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L376

Added line #L376 was not covered by tests
"""Move the module's grid to a new position."""
self.y, self.x = y, x

Check warning on line 378 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L378

Added line #L378 was not covered by tests
if self._grid:
if self.positioning == POS_RELATIVE:
Expand All @@ -376,6 +399,7 @@ def abs_y(self):
return self.y

Check warning on line 399 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L398-L399

Added lines #L398 - L399 were not covered by tests

def render(self):

Check warning on line 401 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L401

Added line #L401 was not covered by tests
"""Render the module to the screen."""
pass

def hit(self, y, x):

Check warning on line 405 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L405

Added line #L405 was not covered by tests
Expand Down Expand Up @@ -420,6 +444,12 @@ def __repr__(self):
return f"{type(self)} at ({self.y}, {self.x}) with value '{self.value[:20]}'"

Check warning on line 444 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L443-L444

Added lines #L443 - L444 were not covered by tests

def _get_lines(self, value: str) -> list[str]:

Check warning on line 446 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L446

Added line #L446 was not covered by tests
"""
Get the lines to render.
Called by `render()` using the value of the element. This allows us to have
word wrapping and alignment in all module types.
"""
if self.word_wrap:
splits = [''] * self.height
words = value.split()

Check warning on line 455 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L454-L455

Added lines #L454 - L455 were not covered by tests
Expand Down Expand Up @@ -464,6 +494,10 @@ def render(self):


class NodeElement(Element):

Check warning on line 496 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L496

Added line #L496 was not covered by tests
"""
A module that is bound to a node and updates when the node changes.
"""

format: Optional[Callable] = None

Check warning on line 501 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L501

Added line #L501 was not covered by tests

def __init__(

Check warning on line 503 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L503

Added line #L503 was not covered by tests
Expand All @@ -490,14 +524,20 @@ def destroy(self):


class Editable(NodeElement):

Check warning on line 526 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L526

Added line #L526 was not covered by tests
"""
A module that can be edited by the user.
Handles mouse clicks, key input, and managing global editing state.
"""

active: bool
_original_value: Any

Check warning on line 534 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L533-L534

Added lines #L533 - L534 were not covered by tests

def __init__(

Check warning on line 536 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L536

Added line #L536 was not covered by tests
self,
coords,
dims,
node: Node,
node: Node,
color=None,
):
super().__init__(coords, dims, node=node, color=color)
Expand Down Expand Up @@ -596,7 +636,7 @@ def render(self) -> None:
color = self.color.to_curses() | curses.A_ITALIC

Check warning on line 636 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L636

Added line #L636 was not covered by tests
else:
color = self.color.to_curses()

Check warning on line 638 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L638

Added line #L638 was not covered by tests

for i, line in enumerate(self._get_lines(str(self.value))):
self.grid.addstr(i, 0, line, color)

Check warning on line 641 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L641

Added line #L641 was not covered by tests

Expand All @@ -609,14 +649,20 @@ def render(self) -> None:


class Text(Element):

Check warning on line 651 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L651

Added line #L651 was not covered by tests
"""Basic text module"""

pass


class WrappedText(Text):

Check warning on line 657 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L657

Added line #L657 was not covered by tests
"""Text module with word wrapping"""

word_wrap: bool = True

Check warning on line 660 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L660

Added line #L660 was not covered by tests


class ASCIIText(Text):

Check warning on line 663 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L663

Added line #L663 was not covered by tests
"""Text module that renders as ASCII art"""

default_font: str = "pepper"
formatter: Figlet
_ascii_render: Optional[str] = None # rendered content
Expand All @@ -643,6 +689,8 @@ def _get_lines(self, value: str) -> list[str]:


class BoldText(Text):

Check warning on line 691 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L691

Added line #L691 was not covered by tests
"""Text module with bold text"""

def __init__(

Check warning on line 694 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L694

Added line #L694 was not covered by tests
self,
coords: tuple[int, int],
Expand All @@ -655,11 +703,15 @@ def __init__(


class Title(BoldText):

Check warning on line 705 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L705

Added line #L705 was not covered by tests
"""A title module; shortcut for bold, centered text"""

h_align: str = ALIGN_CENTER
v_align: str = ALIGN_MIDDLE

Check warning on line 709 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L708-L709

Added lines #L708 - L709 were not covered by tests


class Button(Element):

Check warning on line 712 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L712

Added line #L712 was not covered by tests
"""A clickable button module"""

h_align: str = ALIGN_CENTER
v_align: str = ALIGN_MIDDLE
active: bool = False
Expand Down Expand Up @@ -736,6 +788,8 @@ class CheckButton(RadioButton):


class Contains(Renderable):

Check warning on line 790 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L790

Added line #L790 was not covered by tests
"""A container for other modules"""

_grid: Optional[curses.window] = None
y: int
x: int
Expand Down Expand Up @@ -1115,6 +1169,8 @@ def layout(self) -> list[Renderable]:


class App:

Check warning on line 1171 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1171

Added line #L1171 was not covered by tests
"""The main application class."""

stdscr: curses.window
height: int
width: int
Expand All @@ -1128,7 +1184,7 @@ class App:

def __init__(self, stdscr: curses.window) -> None:
self.stdscr = stdscr
self.height, self.width = self.stdscr.getmaxyx() # TODO dynamic resizing
self.height, self.width = self.stdscr.getmaxyx()

Check warning on line 1187 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1185-L1187

Added lines #L1185 - L1187 were not covered by tests

if not self.width >= self.min_width or not self.height >= self.min_height:
raise RenderException(

Check warning on line 1190 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1190

Added line #L1190 was not covered by tests
Expand Down Expand Up @@ -1210,7 +1266,7 @@ def render(self):
if cls == self.view.__class__:
break
self.load(name)

Check warning on line 1268 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1267-L1268

Added lines #L1267 - L1268 were not covered by tests

# render loop
try:
self.view.render()
Expand All @@ -1223,7 +1279,7 @@ def render(self):
raise RenderException("Grid not large enough to render all modules.")
if "curses function returned NULL" in str(e):

Check warning on line 1280 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1279-L1280

Added lines #L1279 - L1280 were not covered by tests
pass
#raise RenderException("Window not large enough to render.")
# raise RenderException("Window not large enough to render.")
raise e

Check warning on line 1283 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1283

Added line #L1283 was not covered by tests

def click(self, y, x):

Check warning on line 1285 in agentstack/tui.py

View check run for this annotation

Codecov / codecov/patch

agentstack/tui.py#L1285

Added line #L1285 was not covered by tests
Expand Down

0 comments on commit fa4f7ca

Please sign in to comment.