build / build (push) Successful in 38m26s
- das-shell 0.1.0: the Das two-line bash prompt by default (replaces the PS1 of Void's skel .bashrc once), dprompt (Textual prompt builder with presets and live preview) and dbanner (SSH login banner editor: canvas tools, fields with values, widgets, das-banner service for cached ones, Das OS logo and tryzub pictures). Python tests in make test. - das-server 0.3.0 depends on das-shell; the server installer mentions dprompt and dbanner; the desktop image includes it. - run-qemu.sh forwards the guest's SSH to localhost:2222. - Hardware fixes: Ventoy menu icon, boot menu titles "Das OS <version>". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
170 lines
6.8 KiB
Python
170 lines
6.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Writes the ready-made dbanner designs to srcpkgs/das-shell/files/share/banner/presets.
|
|
|
|
The designs are drawn with the same Grid that the editor uses, so they stay
|
|
editable in dbanner. Run after changing this file or the pictures in
|
|
share/banner/art (tools/art/build.sh).
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
FILES = os.path.join(ROOT, "srcpkgs", "das-shell", "files")
|
|
sys.path.insert(0, os.path.join(FILES, "python"))
|
|
|
|
from das_shell import banner # noqa: E402
|
|
|
|
OUT = os.path.join(FILES, "share", "banner", "presets")
|
|
|
|
|
|
def art(name):
|
|
return banner.Grid.from_design(banner.load_file(os.path.join(FILES, "share", "banner", "art", name + ".json")))
|
|
|
|
|
|
def field(grid, x, y, width, text, fg=None, bold=False, bg=None, align="left", font=None):
|
|
f = {"x": x, "y": y, "width": width, "align": align, "text": text,
|
|
"style": grid.style_key(fg, bg, bold)}
|
|
if font:
|
|
f["font"] = font
|
|
return f
|
|
|
|
|
|
def builtin(name, **extra):
|
|
return dict({"type": "builtin", "name": name}, **extra)
|
|
|
|
|
|
def save(name, uk, en, grid, fields, widgets, vars_=None, position="below"):
|
|
d = {"name": name, "title": {"uk": uk, "en": en}, "local": False, "vars": vars_ or {},
|
|
"fields": fields, "widgets_position": position, "widgets": widgets}
|
|
d = grid.to_design(d)
|
|
banner.save(d, os.path.join(OUT, name + ".json"))
|
|
|
|
|
|
def das_classic():
|
|
# The frame of the banner on the author's home server
|
|
g = banner.Grid(39, 5)
|
|
frame = g.style_key("blue")
|
|
g.box(0, 0, 38, 4, "hash", frame)
|
|
red = g.style_key("red", None, True)
|
|
g.text(7, 2, "Server IP:", red)
|
|
g.text(7, 3, "Link:", red)
|
|
fields = [
|
|
field(g, 2, 1, 35, "-=:dAs:=- {title}", "white", True, align="center"),
|
|
field(g, 18, 2, 19, "{ip}", "cyan", True),
|
|
field(g, 13, 3, 24, "{url}", "cyan", True),
|
|
]
|
|
widgets = [builtin("uptime"), builtin("disks"), builtin("memory"), builtin("docker"),
|
|
builtin("services"), builtin("updates")]
|
|
save("das-classic", "Das класичний: рамка з #, назва, IP, посилання", "Das classic: # frame, name, IP, link",
|
|
g, fields, widgets, {"title": "Das OS", "url": "https://das.org.ua/"})
|
|
|
|
|
|
def double():
|
|
w = 64
|
|
g = banner.Grid(w, 10)
|
|
cyan = g.style_key("cyan", None, True)
|
|
g.box(0, 0, w - 1, 9, "double", cyan)
|
|
g.text(1, 7, "─" * (w - 2), g.style_key("bright_black"))
|
|
fields = [
|
|
field(g, 2, 1, w - 4, "{hostname}", "bright_white", True, align="center", font="small"),
|
|
field(g, 2, 5, w - 4, "{title}", "yellow", True, align="center"),
|
|
field(g, 2, 6, w - 4, "{url}", "cyan", align="center"),
|
|
field(g, 2, 8, w - 4, "IP {ip} · {os} · {kernel}", "white", align="center"),
|
|
]
|
|
widgets = [builtin("uptime"), builtin("load"), builtin("memory"), builtin("disks"), builtin("services")]
|
|
save("double", "Подвійна рамка з великим ім'ям сервера", "Double frame with the server name in big letters",
|
|
g, fields, widgets, {"title": "Das OS Server", "url": ""})
|
|
|
|
|
|
def info_column(g, x, y, width, label_fg, value_fg, rows):
|
|
fields = []
|
|
for i, (label, value) in enumerate(rows):
|
|
if label is None:
|
|
fields.append(field(g, x, y + i, width, value, label_fg))
|
|
continue
|
|
fields.append(field(g, x, y + i, 9, label, label_fg, True))
|
|
fields.append(field(g, x + 9, y + i, width - 9, value, value_fg))
|
|
return fields
|
|
|
|
|
|
def blocks():
|
|
logo = art("das-logo")
|
|
g = banner.Grid(76, max(logo.height, 12))
|
|
g.stamp(0, 0, logo)
|
|
x = logo.width + 4
|
|
fields = [field(g, x, 0, 76 - x, "{user}@{hostname}", "bright_cyan", True)]
|
|
fields += info_column(g, x, 1, 76 - x, "bright_blue", "white", [
|
|
(None, "─" * 30),
|
|
("[[ОС|OS]]", "{os}"),
|
|
("[[Ядро|Kernel]]", "{kernel}"),
|
|
("[[Працює|Uptime]]", "{uptime}"),
|
|
("CPU", "{cpu}"),
|
|
("[[Пам'ять|Memory]]", "{mem}"),
|
|
("IP", "{ips}"),
|
|
("[[Вхід|Users]]", "{users}"),
|
|
])
|
|
fields.append(field(g, x, 10, 76 - x, "{url}", "yellow"))
|
|
save("blocks", "Логотип Das OS і відомості про систему", "Das OS logo and system facts",
|
|
g, fields, [builtin("disks")], {"url": ""})
|
|
|
|
|
|
def dashboard():
|
|
w = 70
|
|
g = banner.Grid(w, 3)
|
|
g.box(0, 0, w - 1, 2, "rounded", g.style_key("bright_blue"))
|
|
fields = [field(g, 2, 1, w - 4, "{hostname} · {ip} · {url}", "bright_white", True, align="center")]
|
|
widgets = [builtin(n) for n in ("uptime", "load", "memory", "disks", "network", "docker", "updates",
|
|
"weather", "smart", "services", "fail2ban", "snapshots", "lastlog")]
|
|
save("dashboard", "Панель: усі віджети під заголовком", "Dashboard: every widget under a header",
|
|
g, fields, widgets, {"url": "", "city": "Kyiv"})
|
|
|
|
|
|
def minimal():
|
|
g = banner.Grid(70, 1)
|
|
fields = [field(g, 0, 0, 70, "{hostname} · {ip} · [[працює|up]] {uptime} · {load}", "bright_cyan", True)]
|
|
save("minimal", "Мінімальний: один рядок", "Minimal: one line", g, fields, [])
|
|
|
|
|
|
def ukraine():
|
|
shield = art("trident-shield")
|
|
g = banner.Grid(80, shield.height)
|
|
g.stamp(0, 0, shield)
|
|
x = shield.width + 4
|
|
blue, yellow = "bright_blue", "bright_yellow"
|
|
fields = [
|
|
field(g, x, 1, 80 - x, "{hostname}", yellow, True, font="small"),
|
|
field(g, x, 6, 80 - x, "[[Слава Україні!|Glory to Ukraine!]]", blue, True),
|
|
]
|
|
fields += info_column(g, x, 8, 80 - x, blue, yellow, [
|
|
("IP", "{ip}"),
|
|
("[[Сайт|Site]]", "{url}"),
|
|
("[[Працює|Uptime]]", "{uptime}"),
|
|
("[[Пам'ять|Memory]]", "{mem}"),
|
|
("[[ОС|OS]]", "{os}"),
|
|
])
|
|
save("ukraine", "Тризуб: малий герб України і дані сервера", "Tryzub: Ukrainian coat of arms and server facts",
|
|
g, fields, [builtin("disks"), builtin("services")], {"url": ""})
|
|
|
|
|
|
def tryzub_small():
|
|
# A compact one for small screens: the small tryzub, a few lines of text
|
|
tz = art("trident-small")
|
|
g = banner.Grid(60, tz.height)
|
|
g.stamp(0, 0, tz)
|
|
x = tz.width + 3
|
|
fields = [
|
|
field(g, x, 2, 60 - x, "{hostname}", "bright_yellow", True),
|
|
field(g, x, 3, 60 - x, "{ip}", "bright_blue", True),
|
|
field(g, x, 5, 60 - x, "[[Працює|Uptime]]: {uptime}", "white"),
|
|
field(g, x, 6, 60 - x, "{url}", "bright_blue"),
|
|
]
|
|
save("tryzub", "Малий тризуб з іменем і IP", "Small tryzub with name and IP", g, fields,
|
|
[builtin("disks")], {"url": ""})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
os.makedirs(OUT, exist_ok=True)
|
|
for make in (das_classic, double, blocks, dashboard, minimal, ukraine, tryzub_small):
|
|
make()
|