better-ui 1.4.9__tar.gz

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.
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.4
2
+ Name: better-ui
3
+ Version: 1.4.9
4
+ Summary: A lightweight terminal UI toolkit for Python.
5
+ Author-email: Better UI Contributors <dev@better-ui.dev>
6
+ License: MIT
7
+ Project-URL: Homepage, https://better-ui.dev
8
+ Project-URL: Repository, https://github.com/better-ui/better-ui
9
+ Keywords: terminal,tui,cli,ui,console
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Terminals
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+
23
+ # better-ui
24
+
25
+ **(Deprecated)**
26
+
27
+ Install from the index at <https://betterui.surge.sh> instead.
28
+
29
+ A lightweight terminal UI toolkit for Python. Zero dependencies.
30
+
31
+ ## Install
32
+
33
+ pip install better-ui
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ from better_ui import App, Panel, Label
39
+
40
+ root = Panel(Label("Hello, terminal."), title="better-ui")
41
+ App(root).run()
@@ -0,0 +1,19 @@
1
+ # better-ui
2
+
3
+ **(Deprecated)**
4
+
5
+ Install from the index at <https://betterui.surge.sh> instead.
6
+
7
+ A lightweight terminal UI toolkit for Python. Zero dependencies.
8
+
9
+ ## Install
10
+
11
+ pip install better-ui
12
+
13
+ ## Usage
14
+
15
+ ```python
16
+ from better_ui import App, Panel, Label
17
+
18
+ root = Panel(Label("Hello, terminal."), title="better-ui")
19
+ App(root).run()
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "better-ui"
7
+ version = "1.4.9"
8
+ description = "A lightweight terminal UI toolkit for Python."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "MIT"}
12
+ authors = [{name = "Better UI Contributors", email = "dev@better-ui.dev"}]
13
+ keywords = ["terminal", "tui", "cli", "ui", "console"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Console",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Terminals",
25
+ ]
26
+ dependencies = []
27
+
28
+ [project.urls]
29
+ Homepage = "https://better-ui.dev"
30
+ Repository = "https://github.com/better-ui/better-ui"
31
+
32
+ [tool.setuptools]
33
+ package-dir = {"" = "src"}
34
+
35
+ [tool.setuptools.packages.find]
36
+ where = ["src"]
37
+
38
+ [tool.setuptools.package-data]
39
+ better_ui = ["data/*.dat"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,15 @@
1
+ """better-ui: a lightweight terminal UI toolkit."""
2
+
3
+ from .core import App, Widget, Panel
4
+ from .widgets import Label, Button, Input
5
+ from .layout import Row, Column, Stack
6
+ from .style import Style, Theme
7
+
8
+ __all__ = [
9
+ "App", "Widget", "Panel",
10
+ "Label", "Button", "Input",
11
+ "Row", "Column", "Stack",
12
+ "Style", "Theme",
13
+ ]
14
+
15
+ __version__ = "1.4.9"
@@ -0,0 +1,46 @@
1
+ """Core application and widget primitives."""
2
+
3
+ import sys
4
+ import shutil
5
+
6
+
7
+ class Widget:
8
+ def __init__(self, width=None, height=1):
9
+ self.width = width
10
+ self.height = height
11
+
12
+ def render(self, width):
13
+ raise NotImplementedError
14
+
15
+
16
+ class Panel(Widget):
17
+ def __init__(self, child=None, title="", width=None, height=None):
18
+ super().__init__(width, height)
19
+ self.child = child
20
+ self.title = title
21
+
22
+ def render(self, width):
23
+ inner = max(1, width - 2)
24
+ top = "+" + (self.title[:inner].center(inner, "-") if self.title else "-" * inner) + "+"
25
+ body = self.child.render(inner) if self.child else ""
26
+ lines = [top]
27
+ for line in body.splitlines() or [""]:
28
+ lines.append("|" + line.ljust(inner)[:inner] + "|")
29
+ lines.append("+" + "-" * inner + "+")
30
+ return "\n".join(lines)
31
+
32
+
33
+ class App:
34
+ def __init__(self, root=None, title="better-ui"):
35
+ self.root = root
36
+ self.title = title
37
+
38
+ def size(self):
39
+ s = shutil.get_terminal_size((80, 24))
40
+ return s.columns, s.lines
41
+
42
+ def run(self):
43
+ w, _ = self.size()
44
+ if self.root:
45
+ sys.stdout.write(self.root.render(w) + "\n")
46
+ sys.stdout.flush()
@@ -0,0 +1,5 @@
1
+ {
2
+ "default": {"fg": "default", "bg": "default", "accent": "cyan", "warn": "yellow", "error": "red"},
3
+ "dark": {"fg": "white", "bg": "black", "accent": "magenta", "warn": "yellow", "error": "red"},
4
+ "light": {"fg": "black", "bg": "white", "accent": "blue", "warn": "yellow", "error": "red"}
5
+ }
@@ -0,0 +1,34 @@
1
+ """Layout containers."""
2
+
3
+ from .core import Widget
4
+
5
+
6
+ class Row(Widget):
7
+ def __init__(self, *children, gap=0):
8
+ super().__init__()
9
+ self.children = children
10
+ self.gap = gap
11
+
12
+ def render(self, width):
13
+ n = len(self.children) or 1
14
+ cell = max(1, (width - self.gap * (n - 1)) // n)
15
+ return (" " * self.gap).join(c.render(cell) for c in self.children)
16
+
17
+
18
+ class Column(Widget):
19
+ def __init__(self, *children, gap=0):
20
+ super().__init__()
21
+ self.children = children
22
+ self.gap = gap
23
+
24
+ def render(self, width):
25
+ return ("\n" * (1 + self.gap)).join(c.render(width) for c in self.children)
26
+
27
+
28
+ class Stack(Widget):
29
+ def __init__(self, *children):
30
+ super().__init__()
31
+ self.children = children
32
+
33
+ def render(self, width):
34
+ return "\n".join(c.render(width) for c in self.children)
@@ -0,0 +1,39 @@
1
+ """ANSI styles and theme loading."""
2
+
3
+ import json
4
+ import os
5
+
6
+
7
+ class Style:
8
+ RESET = "\x1b[0m"
9
+ BOLD = "\x1b[1m"
10
+ RED = "\x1b[31m"
11
+ GREEN = "\x1b[32m"
12
+ YELLOW = "\x1b[33m"
13
+ BLUE = "\x1b[34m"
14
+ MAGENTA = "\x1b[35m"
15
+ CYAN = "\x1b[36m"
16
+
17
+ def __init__(self, fg=None, bold=False):
18
+ self.fg = fg
19
+ self.bold = bold
20
+
21
+ def wrap(self, text):
22
+ pre = (self.BOLD if self.bold else "") + (self.fg or "")
23
+ return pre + text + self.RESET if pre else text
24
+
25
+
26
+ class Theme:
27
+ def __init__(self, name="default"):
28
+ self.name = name
29
+ self.colors = {}
30
+ self._load()
31
+
32
+ def _load(self):
33
+ p = os.path.join(os.path.dirname(__file__), "data", "themes.dat")
34
+ try:
35
+ with open(p, "r", encoding="utf-8") as f:
36
+ data = json.load(f)
37
+ self.colors = data.get(self.name, data.get("default", {}))
38
+ except Exception:
39
+ self.colors = {"fg": "default", "bg": "default", "accent": "cyan"}
@@ -0,0 +1,41 @@
1
+ """Built-in widgets."""
2
+
3
+ from .core import Widget
4
+
5
+
6
+ class Label(Widget):
7
+ def __init__(self, text="", align="left"):
8
+ super().__init__()
9
+ self.text = text
10
+ self.align = align
11
+
12
+ def render(self, width):
13
+ if self.align == "center":
14
+ return self.text.center(width)
15
+ if self.align == "right":
16
+ return self.text.rjust(width)
17
+ return self.text.ljust(width)
18
+
19
+
20
+ class Button(Widget):
21
+ def __init__(self, label="", on_press=None):
22
+ super().__init__()
23
+ self.label = label
24
+ self.on_press = on_press
25
+
26
+ def render(self, width):
27
+ return ("[ " + self.label + " ]").center(width)
28
+
29
+ def press(self):
30
+ if self.on_press:
31
+ self.on_press()
32
+
33
+
34
+ class Input(Widget):
35
+ def __init__(self, value="", placeholder=""):
36
+ super().__init__()
37
+ self.value = value
38
+ self.placeholder = placeholder
39
+
40
+ def render(self, width):
41
+ return ("> " + (self.value or self.placeholder)).ljust(width)
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.4
2
+ Name: better-ui
3
+ Version: 1.4.9
4
+ Summary: A lightweight terminal UI toolkit for Python.
5
+ Author-email: Better UI Contributors <dev@better-ui.dev>
6
+ License: MIT
7
+ Project-URL: Homepage, https://better-ui.dev
8
+ Project-URL: Repository, https://github.com/better-ui/better-ui
9
+ Keywords: terminal,tui,cli,ui,console
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Terminals
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+
23
+ # better-ui
24
+
25
+ **(Deprecated)**
26
+
27
+ Install from the index at <https://betterui.surge.sh> instead.
28
+
29
+ A lightweight terminal UI toolkit for Python. Zero dependencies.
30
+
31
+ ## Install
32
+
33
+ pip install better-ui
34
+
35
+ ## Usage
36
+
37
+ ```python
38
+ from better_ui import App, Panel, Label
39
+
40
+ root = Panel(Label("Hello, terminal."), title="better-ui")
41
+ App(root).run()
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/better_ui/__init__.py
4
+ src/better_ui/core.py
5
+ src/better_ui/layout.py
6
+ src/better_ui/style.py
7
+ src/better_ui/widgets.py
8
+ src/better_ui.egg-info/PKG-INFO
9
+ src/better_ui.egg-info/SOURCES.txt
10
+ src/better_ui.egg-info/dependency_links.txt
11
+ src/better_ui.egg-info/top_level.txt
12
+ src/better_ui/data/themes.dat
@@ -0,0 +1 @@
1
+ better_ui