Hardware fixes: issue version, installer Cyrillic, console TUIs (0.9.2)
build / build (push) Canceled after 0s

- /etc/issue shows the Das OS version instead of the kernel's; the server
  installer carries it into the installed system.
- das-server-installer: setfont -C /dev/tty0 before the language menu
  (sudo runs it in its own pty, so the Cyrillic was drawn as Latin), and
  floppy drives are no longer offered as install targets.
- ncdu on the desktop image and in das-server 0.4.0.
- das-shell 0.2.0: each prompt line sets its own color; the dbanner start
  screen buttons are no longer covered by the key bar; on the Linux
  console (TERM=linux) dprompt and dbanner draw solid borders and swap
  the glyphs that no console font has (▊▎▔▁ and others) for ones it has.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
das
2026-10-21 19:21:47 +03:00
co-authored by Claude Opus 5.5
parent 94b1bf5f8b
commit 6564d1eb17
17 changed files with 83 additions and 26 deletions
@@ -17,7 +17,7 @@ from textual.widgets import (Button, Checkbox, Footer, Header, Input, Label, Lis
from . import banner, widgets
from .canvas import TOOLS, Canvas
from .i18n import t, title
from .tui_common import AskDialog, Swatches, run_as_root
from .tui_common import AskDialog, Swatches, console_mode, run_as_root
TOOL_NAMES = {
"pen": ("Олівець", "Pen"), "eraser": ("Гумка", "Eraser"), "line": ("Лінія", "Line"),
@@ -657,7 +657,8 @@ class StartScreen(Screen):
CSS = """
#list { width: 46; border-right: solid $primary; }
#start_preview { padding: 0 1; }
.buttons { height: 3; dock: bottom; }
#start_main { height: 1fr; }
.buttons { height: auto; }
.buttons Button { margin-right: 1; }
"""
BINDINGS = [
@@ -671,7 +672,7 @@ class StartScreen(Screen):
def compose(self):
yield Header()
with Horizontal():
with Horizontal(id="start_main"):
yield ListView(id="list")
yield VerticalScroll(Static(id="start_preview"))
with Horizontal(classes="buttons"):
@@ -769,6 +770,7 @@ class BannerApp(App):
def __init__(self):
# The terminal's own 16 colors: the picture looks as it will at login
console_mode()
super().__init__(ansi_color=True)
def on_mount(self):
@@ -275,6 +275,10 @@ class _Bash:
current = style
if isinstance(p, Lit):
out.append(_ps1_text(self.glyphs(p.text)))
if p.text.endswith("\n"):
# Readline redraws only the last line of the prompt, so
# each line has to set its color again
current = None
elif isinstance(p, Esc):
out.append(p.code)
elif isinstance(p, Dyn):
@@ -13,7 +13,7 @@ from textual.widgets import Button, Checkbox, Footer, Header, Input, Label, List
from . import prompt
from .cli_prompt import apply as apply_design, current
from .i18n import t
from .tui_common import NONE, AskDialog, color_options, color_value, run_as_root, to_select
from .tui_common import NONE, AskDialog, color_options, color_value, console_mode, run_as_root, to_select
# Settings of each segment type: (key, kind, Ukrainian label, English label)
COLOR_KEYS = [("fg", "color", "Колір", "Color"), ("bold", "bool", "Жирний", "Bold")]
@@ -83,6 +83,7 @@ class PromptApp(App):
def __init__(self, design=None):
# The terminal's own 16 colors, as the prompt will use them
console_mode()
super().__init__(ansi_color=True)
self.design, self.source = (design, None) if design else current()
self.design = prompt.normalize(self.design)
@@ -15,9 +15,39 @@ from textual.widgets import Button, Input, Label, Select
from . import colors
from .i18n import t
from .prompt import CONSOLE_GLYPHS as PROMPT_CONSOLE_GLYPHS
NONE = "-" # Select has no None value
# The Linux console's fonts hold at most 512 glyphs (cyr-sun16, Terminus: none has
# the eighth blocks ▊▎▔▁ Textual draws buttons, inputs and lists with), so the
# missing ones come out as squares. There we draw with what the fonts do have.
CONSOLE = os.environ.get("TERM") == "linux"
CONSOLE_BORDERS = ("tall", "wide", "panel", "tab", "hkey", "vkey", "round", "heavy", "dashed", "inner", "outer")
CONSOLE_GLYPHS = str.maketrans({
**PROMPT_CONSOLE_GLYPHS,
"▁": "▄", "▂": "▄", "▃": "▄", "▅": "▄", "▆": "▄", "▇": "█", "▔": "▀", "▉": "█",
"▊": "▌", "▋": "▌", "▍": "▌", "▎": "▌", "▏": "▌", "▕": "▐",
"━": "─", "╸": "─", "╺": "─", "┃": "│", "┏": "┌", "┓": "┐", "┗": "└", "┛": "┘",
"╭": "┌", "╮": "┐", "╰": "└", "╯": "┘", "╱": "/", "╲": "\\",
"—": "-", "…": ".", "×": "x", "✕": "x", "✓": "v", "☑": "x", "○": "o", "⭘": "o", "◢": "▀",
})
def console_mode():
"""On the Linux console: swaps the borders and glyphs its fonts lack. Call
before the app starts."""
if not CONSOLE:
return
from textual import _border
from textual.drivers.linux_driver import LinuxDriver
for kind in CONSOLE_BORDERS:
_border.BORDER_CHARS[kind] = _border.BORDER_CHARS["solid"]
_border.BORDER_LOCATIONS[kind] = _border.BORDER_LOCATIONS["solid"]
_border.get_box.cache_clear()
write = LinuxDriver.write
LinuxDriver.write = lambda self, data: write(self, data.translate(CONSOLE_GLYPHS))
def color_options(allow_none=True):
names = {
@@ -35,6 +35,11 @@ class PresetTest(unittest.TestCase):
self.assertNotIn("──", text(d))
self.assertIn("─[main*]─[.venv]─[jobs:2]", text(d, git="main*", venv=".venv", jobs=2))
def test_each_line_sets_its_color(self):
# Readline redraws only the last line, so it must not rely on the first
ps1 = prompt.script(prompt.load_preset("das")).split("PS1='", 1)[1].split("'", 1)[0]
self.assertTrue(ps1.split("\n")[1].startswith("\\[\\e[0;31m\\]└"), ps1)
def test_unknown_segments_are_dropped(self):
d = prompt.normalize({"segments": [{"type": "nope"}, {"type": "cwd"}]})
self.assertEqual([s["type"] for s in d["segments"]], ["cwd"])
+1 -1
View File
@@ -1,7 +1,7 @@
# Template file for 'das-shell'
# In-tree package: sources are in files/ (FILESDIR).
pkgname=das-shell
version=0.1.0
version=0.2.0
revision=1
create_wrksrc=yes
hostmakedepends="python3"