Hardware fixes: issue version, installer Cyrillic, console TUIs (0.9.2)
build / build (push) Canceled after 0s
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:
@@ -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"])
|
||||
|
||||
Reference in New Issue
Block a user