zettcode-tui 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zettcode/tui/__init__.py +422 -0
- zettcode/tui/_compat.py +32 -0
- zettcode/tui/capabilities.py +107 -0
- zettcode/tui/clipboard.py +91 -0
- zettcode/tui/console.py +229 -0
- zettcode/tui/core/__init__.py +63 -0
- zettcode/tui/core/app.py +658 -0
- zettcode/tui/core/events.py +134 -0
- zettcode/tui/core/focus.py +85 -0
- zettcode/tui/core/geometry.py +212 -0
- zettcode/tui/core/host.py +66 -0
- zettcode/tui/core/keymap.py +218 -0
- zettcode/tui/core/scheduler.py +105 -0
- zettcode/tui/core/screen.py +80 -0
- zettcode/tui/core/theme.py +248 -0
- zettcode/tui/core/widget.py +204 -0
- zettcode/tui/gallery.py +588 -0
- zettcode/tui/glyphs.py +73 -0
- zettcode/tui/input/__init__.py +18 -0
- zettcode/tui/input/bridge.py +46 -0
- zettcode/tui/input/decoder.py +234 -0
- zettcode/tui/input/events.py +64 -0
- zettcode/tui/input/keys.py +289 -0
- zettcode/tui/input/reader.py +147 -0
- zettcode/tui/layout/__init__.py +24 -0
- zettcode/tui/layout/box.py +153 -0
- zettcode/tui/layout/overlay.py +164 -0
- zettcode/tui/layout/scroll.py +477 -0
- zettcode/tui/layout/solver.py +95 -0
- zettcode/tui/layout/spacing.py +137 -0
- zettcode/tui/py.typed +0 -0
- zettcode/tui/render/__init__.py +71 -0
- zettcode/tui/render/ansi.py +371 -0
- zettcode/tui/render/canvas.py +153 -0
- zettcode/tui/render/code.py +456 -0
- zettcode/tui/render/color.py +177 -0
- zettcode/tui/render/renderer.py +151 -0
- zettcode/tui/render/rich_text.py +80 -0
- zettcode/tui/render/style.py +121 -0
- zettcode/tui/render/sweep.py +87 -0
- zettcode/tui/render/text.py +319 -0
- zettcode/tui/runner.py +316 -0
- zettcode/tui/terminal.py +222 -0
- zettcode/tui/testing/__init__.py +6 -0
- zettcode/tui/testing/harness.py +220 -0
- zettcode/tui/testing/snapshot.py +64 -0
- zettcode/tui/theme_file.py +300 -0
- zettcode/tui/themes/ayu-mirage.toml +44 -0
- zettcode/tui/themes/catppuccin-latte.toml +44 -0
- zettcode/tui/themes/catppuccin-mocha.toml +44 -0
- zettcode/tui/themes/dracula.toml +44 -0
- zettcode/tui/themes/github-dimmed.toml +44 -0
- zettcode/tui/themes/github-light.toml +44 -0
- zettcode/tui/themes/gruvbox-dark.toml +44 -0
- zettcode/tui/themes/gruvbox-light.toml +44 -0
- zettcode/tui/themes/kanagawa.toml +44 -0
- zettcode/tui/themes/nord.toml +44 -0
- zettcode/tui/themes/one-dark.toml +44 -0
- zettcode/tui/themes/rose-pine-dawn.toml +44 -0
- zettcode/tui/themes/rose-pine.toml +44 -0
- zettcode/tui/themes/solarized-dark.toml +44 -0
- zettcode/tui/themes/solarized-light.toml +44 -0
- zettcode/tui/themes/tokyo-night.toml +44 -0
- zettcode/tui/widgets/__init__.py +121 -0
- zettcode/tui/widgets/collapsible.py +116 -0
- zettcode/tui/widgets/completion.py +211 -0
- zettcode/tui/widgets/console.py +442 -0
- zettcode/tui/widgets/dialog.py +165 -0
- zettcode/tui/widgets/diff.py +236 -0
- zettcode/tui/widgets/list.py +293 -0
- zettcode/tui/widgets/list_page.py +121 -0
- zettcode/tui/widgets/markdown.py +657 -0
- zettcode/tui/widgets/progress.py +166 -0
- zettcode/tui/widgets/rich_text.py +84 -0
- zettcode/tui/widgets/status.py +106 -0
- zettcode/tui/widgets/table.py +101 -0
- zettcode/tui/widgets/tasks.py +130 -0
- zettcode/tui/widgets/text.py +111 -0
- zettcode/tui/widgets/textarea.py +671 -0
- zettcode/tui/widgets/toast.py +137 -0
- zettcode_tui-0.4.0.dist-info/METADATA +20 -0
- zettcode_tui-0.4.0.dist-info/RECORD +83 -0
- zettcode_tui-0.4.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""Static display primitives: a label and a horizontal rule."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from typing import TypeAlias
|
|
7
|
+
|
|
8
|
+
from zettcode.tui import RULE
|
|
9
|
+
|
|
10
|
+
from ..core.geometry import Constraints, Size
|
|
11
|
+
from ..core.widget import Widget
|
|
12
|
+
from ..render import Alignment, Canvas, Span, Style, TextLine
|
|
13
|
+
from .rich_text import RichText
|
|
14
|
+
|
|
15
|
+
Value: TypeAlias = str | Callable[[], str]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Text(RichText):
|
|
19
|
+
"""A label that may compute its value at paint time and wrap to its width.
|
|
20
|
+
|
|
21
|
+
Shape::
|
|
22
|
+
|
|
23
|
+
bold heading <- bold=True
|
|
24
|
+
muted caption that wraps across <- muted=True, wrapped at rect.width
|
|
25
|
+
rows
|
|
26
|
+
right aligned <- align="right"
|
|
27
|
+
|
|
28
|
+
It uses the same styled-line layout as :class:`RichText`; the label never
|
|
29
|
+
grows past the rectangle it was given, it just writes fewer rows.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
#: The label resolves to text only, never to styled fragments.
|
|
33
|
+
value: Value
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
value: Value = "",
|
|
38
|
+
*,
|
|
39
|
+
align: Alignment = "left",
|
|
40
|
+
bold: bool = False,
|
|
41
|
+
muted: bool = False,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""Configure the label's content and its paint-time styling.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
value: Static text, or a callback re-evaluated on every paint so the
|
|
47
|
+
label can mirror live state without the owner calling invalidate.
|
|
48
|
+
align: ``"left"``, ``"center"``, or ``"right"`` within the widget
|
|
49
|
+
rectangle, as :func:`layout_rich_lines` implements them; a value
|
|
50
|
+
the layout does not know raises rather than falling back, so a
|
|
51
|
+
caller that misspells one hears about it. Wrapping is unaffected.
|
|
52
|
+
bold: Draw every span bold.
|
|
53
|
+
muted: Use the theme's muted colour instead of the body text colour.
|
|
54
|
+
"""
|
|
55
|
+
super().__init__(value, align=align)
|
|
56
|
+
self.value = value
|
|
57
|
+
self.bold = bold
|
|
58
|
+
self.muted = muted
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def content(self) -> str:
|
|
62
|
+
"""Resolve the current text, calling the value when it is a provider."""
|
|
63
|
+
return self.value() if callable(self.value) else self.value
|
|
64
|
+
|
|
65
|
+
def style_for(self) -> Style:
|
|
66
|
+
"""Return the style this label paints with."""
|
|
67
|
+
theme = self.theme
|
|
68
|
+
return Style(foreground=theme.muted if self.muted else theme.text, bold=self.bold)
|
|
69
|
+
|
|
70
|
+
def _lines(self) -> tuple[TextLine, ...]:
|
|
71
|
+
"""Return the label as styled lines for the shared layout."""
|
|
72
|
+
style = self.style_for()
|
|
73
|
+
return tuple(TextLine((Span(source, style),)) for source in self.content.split("\n"))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Rule(Widget):
|
|
77
|
+
"""A one-row horizontal separator.
|
|
78
|
+
|
|
79
|
+
Shape::
|
|
80
|
+
|
|
81
|
+
-------------------------------- <- character repeated rect.width times
|
|
82
|
+
|
|
83
|
+
Drawn with U+2500 by default. It asks for a single cell and takes whatever
|
|
84
|
+
width its slot gives it, so it is normally used as ``Slot(Rule(), size=1)``
|
|
85
|
+
between two regions.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def __init__(self, character: str = RULE) -> None:
|
|
89
|
+
"""Set the glyph the rule repeats across its width.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
character: Repeated once per column; the default is a box-drawing dash.
|
|
93
|
+
"""
|
|
94
|
+
super().__init__()
|
|
95
|
+
self.character = character
|
|
96
|
+
|
|
97
|
+
def measure(self, constraints: Constraints) -> Size:
|
|
98
|
+
"""Claim a single cell; the parent box supplies the real width."""
|
|
99
|
+
return constraints.constrain(Size(1, 1))
|
|
100
|
+
|
|
101
|
+
def render(self, canvas: Canvas) -> None:
|
|
102
|
+
"""Fill the assigned row with the rule character."""
|
|
103
|
+
if self.rect.empty:
|
|
104
|
+
return
|
|
105
|
+
canvas.draw_text(
|
|
106
|
+
self.rect.x,
|
|
107
|
+
self.rect.y,
|
|
108
|
+
self.character * self.rect.width,
|
|
109
|
+
Style(foreground=self.theme.border),
|
|
110
|
+
max_width=self.rect.width,
|
|
111
|
+
)
|