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
+3 -3
View File
@@ -1,7 +1,7 @@
## Das OS ## Das OS
### _A light, friendly Void Linux–based desktop with Xfce and a Ukrainian touch, plus a console server edition_ ### _A light, friendly Void Linux–based desktop with Xfce and a Ukrainian touch, plus a console server edition_
[![Void Linux](https://img.shields.io/badge/Void_Linux-x86__64_glibc-green)](https://voidlinux.org) [![Xfce](https://img.shields.io/badge/Xfce-4.20-orange)](https://xfce.org) [![runit](https://img.shields.io/badge/init-runit-blue)](https://docs.voidlinux.org/config/services/) [![Go](https://img.shields.io/badge/Go-1.24+-blue)](https://go.dev) [![Docker](https://img.shields.io/badge/Docker-29-blue)](https://www.docker.com) [![Python](https://img.shields.io/badge/Python-3-blue)](https://www.python.org) [![Textual](https://img.shields.io/badge/Textual-8.2-blue)](https://textual.textualize.io) [![Version](https://img.shields.io/badge/version-0.9.1-lightgrey)](#) [![Void Linux](https://img.shields.io/badge/Void_Linux-x86__64_glibc-green)](https://voidlinux.org) [![Xfce](https://img.shields.io/badge/Xfce-4.20-orange)](https://xfce.org) [![runit](https://img.shields.io/badge/init-runit-blue)](https://docs.voidlinux.org/config/services/) [![Go](https://img.shields.io/badge/Go-1.24+-blue)](https://go.dev) [![Docker](https://img.shields.io/badge/Docker-29-blue)](https://www.docker.com) [![Python](https://img.shields.io/badge/Python-3-blue)](https://www.python.org) [![Textual](https://img.shields.io/badge/Textual-8.2-blue)](https://textual.textualize.io) [![Version](https://img.shields.io/badge/version-0.9.2-lightgrey)](#)
🇺🇦 [Українська версія](README_ua.md) 🇺🇦 [Українська версія](README_ua.md)
@@ -135,7 +135,7 @@ Void Linux is fast, simple and independent: runit instead of systemd, and its ow
- The installed system runs `sshd`, `chronyd`, `nftables`, `fail2ban`, `docker`, `socklog` and the chosen network service. - The installed system runs `sshd`, `chronyd`, `nftables`, `fail2ban`, `docker`, `socklog` and the chosen network service.
- nftables lets in only SSH, ICMP and DHCPv6 (`/etc/nftables.conf`), more ports are opened with `dfw`. The rules live in their own table `inet das`, so reloading them keeps the Docker and fail2ban rules. Ports that containers publish pass through Docker's own rules. - nftables lets in only SSH, ICMP and DHCPv6 (`/etc/nftables.conf`), more ports are opened with `dfw`. The rules live in their own table `inet das`, so reloading them keeps the Docker and fail2ban rules. Ports that containers publish pass through Docker's own rules.
- fail2ban bans addresses that keep failing SSH logins, reading the socklog log. sshd doesn't accept root password logins. - fail2ban bans addresses that keep failing SSH logins, reading the socklog log. sshd doesn't accept root password logins.
- Tools: Docker with Compose, lazydocker, lazygit, Midnight Commander, tmux, htop, Python 3, curl, `das-update --cli`, the [helpers](#Helpers), [`dprompt` and `dbanner`](#Terminal) and xtools (`xi`, `xq`, `xrs`). There are no graphical libraries, and no firmware for NVIDIA graphics or sound cards (`/etc/xbps.d/das-server.conf` keeps updates from bringing it back). - Tools: Docker with Compose, lazydocker, lazygit, Midnight Commander, tmux, htop, ncdu, Python 3, curl, `das-update --cli`, the [helpers](#Helpers), [`dprompt` and `dbanner`](#Terminal) and xtools (`xi`, `xq`, `xrs`). There are no graphical libraries, and no firmware for NVIDIA graphics or sound cards (`/etc/xbps.d/das-server.conf` keeps updates from bringing it back).
#### Command-line helpers<a id='Helpers' /> #### Command-line helpers<a id='Helpers' />
**_Short commands for tasks that systemd distributions handle with systemctl, hostnamectl and the like, and that Void leaves to manual editing._** **_Short commands for tasks that systemd distributions handle with systemctl, hostnamectl and the like, and that Void leaves to manual editing._**
@@ -222,6 +222,6 @@ make clean # remove build output, keep the download cache
``` ```
The ISOs appear in `out/iso/dasos-<version>-x86_64.iso` and `out/iso/dasos-server-<version>-x86_64.iso`. Write them to a USB stick with `dd` or Ventoy. For a Ventoy theme there is a 48×48 menu icon `live/branding/ventoy/dasos.png`: copy it to the theme's `icons/` folder and add `{ "key": "dasos", "class": "dasos" }` to `menu_class` in `ventoy.json`. The ISOs appear in `out/iso/dasos-<version>-x86_64.iso` and `out/iso/dasos-server-<version>-x86_64.iso`. Write them to a USB stick with `dd` or Ventoy. For a Ventoy theme there is a 48×48 menu icon `live/branding/ventoy/dasos.png`: copy it to the theme's `icons/` folder and add `{ "key": "dasos", "class": "dasos" }` to `menu_class` in `ventoy.json`.
**Note:** Das OS is an early version (0.9.1). Packages and ISOs are built in CI; signed repository hosting is planned for an upcoming stage. Until the repository is hosted, an installed system gets updates from Void only. Das OS is based on Void Linux but is not affiliated with it. **Note:** Das OS is an early version (0.9.2). Packages and ISOs are built in CI; signed repository hosting is planned for an upcoming stage. Until the repository is hosted, an installed system gets updates from Void only. Das OS is based on Void Linux but is not affiliated with it.
###### _Made by -=:dAs:=-_ ###### _Made by -=:dAs:=-_
+3 -3
View File
@@ -1,7 +1,7 @@
## Das OS ## Das OS
### _Легкий і дружній десктоп на базі Void Linux з Xfce та українським колоритом, а також консольна серверна версія_ ### _Легкий і дружній десктоп на базі Void Linux з Xfce та українським колоритом, а також консольна серверна версія_
[![Void Linux](https://img.shields.io/badge/Void_Linux-x86__64_glibc-green)](https://voidlinux.org) [![Xfce](https://img.shields.io/badge/Xfce-4.20-orange)](https://xfce.org) [![runit](https://img.shields.io/badge/init-runit-blue)](https://docs.voidlinux.org/config/services/) [![Go](https://img.shields.io/badge/Go-1.24+-blue)](https://go.dev) [![Docker](https://img.shields.io/badge/Docker-29-blue)](https://www.docker.com) [![Python](https://img.shields.io/badge/Python-3-blue)](https://www.python.org) [![Textual](https://img.shields.io/badge/Textual-8.2-blue)](https://textual.textualize.io) [![Version](https://img.shields.io/badge/version-0.9.1-lightgrey)](#) [![Void Linux](https://img.shields.io/badge/Void_Linux-x86__64_glibc-green)](https://voidlinux.org) [![Xfce](https://img.shields.io/badge/Xfce-4.20-orange)](https://xfce.org) [![runit](https://img.shields.io/badge/init-runit-blue)](https://docs.voidlinux.org/config/services/) [![Go](https://img.shields.io/badge/Go-1.24+-blue)](https://go.dev) [![Docker](https://img.shields.io/badge/Docker-29-blue)](https://www.docker.com) [![Python](https://img.shields.io/badge/Python-3-blue)](https://www.python.org) [![Textual](https://img.shields.io/badge/Textual-8.2-blue)](https://textual.textualize.io) [![Version](https://img.shields.io/badge/version-0.9.2-lightgrey)](#)
🇬🇧 [English version](README.md) 🇬🇧 [English version](README.md)
@@ -135,7 +135,7 @@ Void Linux швидкий, простий і незалежний: runit зам
- Встановлена система запускає `sshd`, `chronyd`, `nftables`, `fail2ban`, `docker`, `socklog` і вибрану мережеву службу. - Встановлена система запускає `sshd`, `chronyd`, `nftables`, `fail2ban`, `docker`, `socklog` і вибрану мережеву службу.
- nftables пропускає лише SSH, ICMP і DHCPv6 (`/etc/nftables.conf`), інші порти відкриває `dfw`. Правила лежать у власній таблиці `inet das`, тож їх перезавантаження не чіпає правил Docker і fail2ban. Порти, які публікують контейнери, проходять через власні правила Docker. - nftables пропускає лише SSH, ICMP і DHCPv6 (`/etc/nftables.conf`), інші порти відкриває `dfw`. Правила лежать у власній таблиці `inet das`, тож їх перезавантаження не чіпає правил Docker і fail2ban. Порти, які публікують контейнери, проходять через власні правила Docker.
- fail2ban блокує адреси, з яких раз у раз не вдається увійти по SSH, читаючи журнал socklog. sshd не приймає вхід root за паролем. - fail2ban блокує адреси, з яких раз у раз не вдається увійти по SSH, читаючи журнал socklog. sshd не приймає вхід root за паролем.
- Інструменти: Docker з Compose, lazydocker, lazygit, Midnight Commander, tmux, htop, Python 3, curl, `das-update --cli`, [помічники](#Helpers), [`dprompt` і `dbanner`](#Terminal) та xtools (`xi`, `xq`, `xrs`). Графічних бібліотек немає, як і прошивок для відеокарт NVIDIA та звукових карт (`/etc/xbps.d/das-server.conf` не дає оновленням повернути їх). - Інструменти: Docker з Compose, lazydocker, lazygit, Midnight Commander, tmux, htop, ncdu, Python 3, curl, `das-update --cli`, [помічники](#Helpers), [`dprompt` і `dbanner`](#Terminal) та xtools (`xi`, `xq`, `xrs`). Графічних бібліотек немає, як і прошивок для відеокарт NVIDIA та звукових карт (`/etc/xbps.d/das-server.conf` не дає оновленням повернути їх).
#### Консольні помічники<a id='Helpers' /> #### Консольні помічники<a id='Helpers' />
**_Короткі команди для задач, які в дистрибутивах із systemd розв'язують systemctl, hostnamectl тощо, а у Void доводиться робити вручну._** **_Короткі команди для задач, які в дистрибутивах із systemd розв'язують systemctl, hostnamectl тощо, а у Void доводиться робити вручну._**
@@ -222,6 +222,6 @@ make clean # видалити результати збиранн
``` ```
ISO з'являються в `out/iso/dasos-<версія>-x86_64.iso` і `out/iso/dasos-server-<версія>-x86_64.iso`. Записати їх на флешку можна через `dd` або Ventoy. Для теми Ventoy є значок меню 48×48 `live/branding/ventoy/dasos.png`: скопіюйте його в теку `icons/` теми й додайте `{ "key": "dasos", "class": "dasos" }` до `menu_class` у `ventoy.json`. ISO з'являються в `out/iso/dasos-<версія>-x86_64.iso` і `out/iso/dasos-server-<версія>-x86_64.iso`. Записати їх на флешку можна через `dd` або Ventoy. Для теми Ventoy є значок меню 48×48 `live/branding/ventoy/dasos.png`: скопіюйте його в теку `icons/` теми й додайте `{ "key": "dasos", "class": "dasos" }` до `menu_class` у `ventoy.json`.
**Примітка:** Das OS — рання версія (0.9.1). Пакети й ISO збираються в CI; підписаний репозиторій на хостингу заплановано на наступний етап. Поки репозиторій не розміщено на хостингу, встановлена система отримує оновлення лише з Void. Das OS базується на Void Linux, але не пов'язана з ним офіційно. **Примітка:** Das OS — рання версія (0.9.2). Пакети й ISO збираються в CI; підписаний репозиторій на хостингу заплановано на наступний етап. Поки репозиторій не розміщено на хостингу, встановлена система отримує оновлення лише з Void. Das OS базується на Void Linux, але не пов'язана з ним офіційно.
###### _Made by -=:dAs:=-_ ###### _Made by -=:dAs:=-_
+11 -1
View File
@@ -1,6 +1,6 @@
# Das OS — що зробити далі # Das OS — що зробити далі
Стан на 2026-10-20: версія 0.8.0, етапи 1–8 готові (live ISO, власний репозиторій, оформлення, інсталятор Calamares зі знімками Btrfs, Go-утиліти `das-update` і `das-welcome`, серверний образ з консольним інсталятором, менші ISO, консольні помічники, профіль розробника), CI (етап 9: пакети й обидва ISO збираються на власному runner, ~45 хв). Стан на 2026-10-21: версія 0.9.2, етапи 1–8 готові (live ISO, власний репозиторій, оформлення, інсталятор Calamares зі знімками Btrfs, Go-утиліти `das-update` і `das-welcome`, серверний образ з консольним інсталятором, менші ISO, консольні помічники, профіль розробника), CI (етап 9: пакети й обидва ISO збираються на власному runner, ~45 хв).
## Етап 5. Go-утиліти (готово, лишилися перевірки) ## Етап 5. Go-утиліти (готово, лишилися перевірки)
- [x] `das-update`: вікно, значок у треї (лише коли є оновлення), консольний режим `--cli`, знімок snapper pre/post, встановлення через pkexec, підказка про відкат. - [x] `das-update`: вікно, значок у треї (лише коли є оновлення), консольний режим `--cli`, знімок snapper pre/post, встановлення через pkexec, підказка про відкат.
@@ -27,6 +27,10 @@ Live ISO без графіки з консольним інсталятором:
- [x] Перевірено в QEMU: встановлення через TUI на UEFI (з SSH-ключем) і BIOS (з паролем, NetworkManager, `ua-utf`), вхід по SSH лише за ключем, `docker run hello-world`, опублікований порт nginx, fail2ban бачить невдалі входи, `das-update --cli` зі знімками pre/post, `dsv`. - [x] Перевірено в QEMU: встановлення через TUI на UEFI (з SSH-ключем) і BIOS (з паролем, NetworkManager, `ua-utf`), вхід по SSH лише за ключем, `docker run hello-world`, опублікований порт nginx, fail2ban бачить невдалі входи, `das-update --cli` зі знімками pre/post, `dsv`.
- [x] `das-server-install --config` перевірено (0.5.0, UEFI). - [x] `das-server-install --config` перевірено (0.5.0, UEFI).
- [x] Розмір ISO: див. нижче. - [x] Розмір ISO: див. нижче.
- [x] Запрошення до входу (`/etc/issue`) показувало версію ядра (`\r` agetty, 6.18): тепер версія Das OS з `VERSION` (`@VERSION@` у `branding/issue`), серверний інсталятор переносить перший рядок у встановлену систему (0.9.2).
- [x] Українська в `das-server-install` на консолі показувалася латиницею («Ukra■ns'ka»): стандартний шрифт підміняє кирилицю схожими латинськими літерами, а `setfont` не спрацьовував, бо `sudo` запускає інсталятор у власному pty (`tty` → `/dev/pts/N`). Тепер `setfont -C /dev/tty0 cyr-sun16` до вибору мови (перевірено в QEMU: «Гаразд їєіґ»).
- [x] Серед дисків для встановлення був дисковод `/dev/fd0`: тепер пропускається.
- [x] Перевірено серверний ISO 0.9.2 у QEMU: «Das OS Server 0.9.2 (tty1)» у запрошенні, «Українська» в меню мови, `/dev/fd0` немає серед дисків.
### Розмір ISO: 0.4.0 → 0.5.0 ### Розмір ISO: 0.4.0 → 0.5.0
Десктоп 1,96 → 1,72 ГБ, сервер 1,57 → 1,14 ГБ. Десктоп 1,96 → 1,72 ГБ, сервер 1,57 → 1,14 ГБ.
@@ -75,6 +79,11 @@ Live ISO без графіки з консольним інсталятором:
- [x] `dprompt`: конструктор запрошень (5 готових, сегменти, кольори, живий перегляд), застосування для себе або для всіх. - [x] `dprompt`: конструктор запрошень (5 готових, сегменти, кольори, живий перегляд), застосування для себе або для всіх.
- [x] `dbanner`: редактор банера при вході по SSH (7 готових, полотно з інструментами, поля зі змінними, віджети, служба `das-banner` для кешу), малюнки: логотип Das OS і тризуб (`tools/art`). - [x] `dbanner`: редактор банера при вході по SSH (7 готових, полотно з інструментами, поля зі змінними, віджети, служба `das-banner` для кешу), малюнки: логотип Das OS і тризуб (`tools/art`).
- [x] `scripts/run-qemu.sh`: SSH гостя на `localhost:2222`. - [x] `scripts/run-qemu.sh`: SSH гостя на `localhost:2222`.
- [x] Запрошення за замовчуванням: `└─╼` другого рядка міг бути білим, бо колір успадковувався з першого рядка, а readline перемальовує лише останній. Тепер кожен рядок задає колір заново (das-shell 0.2.0).
- [ ] Перевірити в терміналі автора, що `└─╼` червоний.
- [x] `dbanner`: кнопки внизу стартового екрана перекривав рядок підказок клавіш (обидва були прикріплені до низу): тепер кнопки — звичайний рядок під списком.
- [x] У консолі Linux (`TERM=linux`) рамки кнопок, полів і списків `dprompt`/`dbanner` були квадратиками: Textual малює їх символами `▊▎▔▁`, яких немає в жодному консольному шрифті (до 512 символів; перевірено `cyr-sun16`, `default8x16`, `eurlatgr`, Terminus). Тепер там рамки `┌─┐`, а решта відсутніх символів замінюється на наявні. Символи палітри малювання (★ ☀ ♥…) лишаються як є: це вміст банера для SSH-клієнтів.
- [ ] Перевірити `dprompt` і `dbanner` у консолі встановленої системи.
- [ ] Перевірити в QEMU: сервер — банер при вході по SSH, `dbanner apply dashboard` зі службою, `ssh host cmd` без банера; десктоп — запрошення в xfce4-terminal, обидва редактори. - [ ] Перевірити в QEMU: сервер — банер при вході по SSH, `dbanner apply dashboard` зі службою, `ssh host cmd` без банера; десктоп — запрошення в xfce4-terminal, обидва редактори.
## Репозиторій пакетів ## Репозиторій пакетів
@@ -98,6 +107,7 @@ Live ISO без графіки з консольним інсталятором:
- [ ] Прибрати значки томів live-носія («Том 6,6 ГБ») з робочого столу live-сесії. - [ ] Прибрати значки томів live-носія («Том 6,6 ГБ») з робочого столу live-сесії.
- [ ] Тема GRUB у встановленій системі (зараз стандартний чорний екран). - [ ] Тема GRUB у встановленій системі (зараз стандартний чорний екран).
- [ ] Перевірити меню Whisker вручну. - [ ] Перевірити меню Whisker вручну.
- [x] `ncdu` (аналіз зайнятого місця на диску в терміналі): у десктопному образі й у `das-server` 0.4.0.
- [x] Прискорити `make packages`: пакет перезбирається лише після змін у `srcpkgs/<назва>`, без бінарного пакета або коли у Void зникла потрібна йому бібліотека (`xbps-install -n`). `DASOS_REBUILD=1` перезбирає все. - [x] Прискорити `make packages`: пакет перезбирається лише після змін у `srcpkgs/<назва>`, без бінарного пакета або коли у Void зникла потрібна йому бібліотека (`xbps-install -n`). `DASOS_REBUILD=1` перезбирає все.
## Відкладено ## Відкладено
+1 -1
View File
@@ -1 +1 @@
0.9.1 0.9.2
+1 -1
View File
@@ -1,2 +1,2 @@
Das OS \r (\l) Das OS @VERSION@ (\l)
+1
View File
@@ -40,6 +40,7 @@ firefox-i18n-uk
udisks2 udisks2
xdg-user-dirs xdg-user-dirs
xdg-utils xdg-utils
ncdu
# Boot loader and disk tools, also kept by the installed system # Boot loader and disk tools, also kept by the installed system
btrfs-progs btrfs-progs
+3 -2
View File
@@ -82,8 +82,9 @@ done
sed -i -e 's/echo void-live >/echo dasos >/' -e 's/voidlinux/live/g' "$adduser" sed -i -e 's/echo void-live >/echo dasos >/' -e 's/voidlinux/live/g' "$adduser"
# mklive copies its /etc/issue (Void live logins) into the image, and the # mklive copies its /etc/issue (Void live logins) into the image, and the
# installers copy the image to disk, so use a Das OS one (the server's tells # installers copy the image to disk, so use a Das OS one (the server's tells
# how to log in to the live system; its installer writes a neutral one). # how to log in to the live system; its installer keeps only the first line).
cp "$dir/branding/issue" /opt/void-mklive/data/issue # It names the Das OS version instead of agetty's \r (the kernel version).
sed "s/@VERSION@/$version/g" "$dir/branding/issue" >/opt/void-mklive/data/issue
# Size, also patched into this container's mklive copy: # Size, also patched into this container's mklive copy:
# - the live initrd only has to find and mount the image, the GPU drivers and # - the live initrd only has to find and mount the image, the GPU drivers and
+1 -1
View File
@@ -1,4 +1,4 @@
Das OS Server \r (\l) Das OS Server @VERSION@ (\l)
Log in as "live" with the password "live", then run: sudo das-server-install Log in as "live" with the password "live", then run: sudo das-server-install
@@ -164,22 +164,24 @@ list_disks() {
fi fi
lsblk -dpno NAME,TYPE,RO,SIZE,MODEL | while read -r name type ro size model; do lsblk -dpno NAME,TYPE,RO,SIZE,MODEL | while read -r name type ro size model; do
[[ $type == disk && $ro == 0 && $name != "$live" ]] || continue [[ $type == disk && $ro == 0 && $name != "$live" ]] || continue
[[ $name == /dev/zram* || $name == /dev/loop* ]] && continue [[ $name == /dev/zram* || $name == /dev/loop* || $name == /dev/fd* ]] && continue
printf '%s\t%s %s\n' "$name" "$size" "${model:-}" printf '%s\t%s %s\n' "$name" "$size" "${model:-}"
done done
} }
ask_language() { ask_language() {
local choice local choice
# The default console font shows Cyrillic as Latin look-alikes, so load one
# with Cyrillic before the first "Українська". sudo runs us on its own pty
# (tty says /dev/pts/N), so name the console; serial and ssh have TERM other
# than linux and no font to set.
[[ $TERM == linux ]] && { setfont -C /dev/tty0 cyr-sun16 2>/dev/null || true; }
choice=$(dialog --backtitle "Das OS Server" --title "Das OS Server" \ choice=$(dialog --backtitle "Das OS Server" --title "Das OS Server" \
--default-item "$lang" --menu "Language / Мова:" 10 50 2 \ --default-item "$lang" --menu "Language / Мова:" 10 50 2 \
en "English" uk "Українська" 3>&1 1>&2 2>&3) || cancelled en "English" uk "Українська" 3>&1 1>&2 2>&3) || cancelled
lang=$choice lang=$choice
if [[ $lang == uk ]]; then if [[ $lang == uk ]]; then
LOCALE=uk_UA.UTF-8 LOCALE=uk_UA.UTF-8
# The default console font has no Cyrillic (a font needs a Unicode table,
# .psfu); there is no font to set on serial or ssh
case $(tty) in /dev/tty[0-9]*) setfont cyr-sun16 2>/dev/null || true ;; esac
fi fi
} }
@@ -404,8 +406,9 @@ disable_service() {
configure() { configure() {
local home local home
# The live image's /etc/issue tells how to log in to the live system # The live image's /etc/issue tells how to log in to the live system: keep
printf 'Das OS Server \\r (\\l)\n\n' >"$target/etc/issue" # its first line, with the Das OS version
printf '%s\n\n' "$(head -n1 /etc/issue)" >"$target/etc/issue"
echo "$HOST_NAME" >"$target/etc/hostname" echo "$HOST_NAME" >"$target/etc/hostname"
if ! grep -q "[[:space:]]$HOST_NAME\$" "$target/etc/hosts"; then if ! grep -q "[[:space:]]$HOST_NAME\$" "$target/etc/hosts"; then
printf '127.0.1.1\t%s\n' "$HOST_NAME" >>"$target/etc/hosts" printf '127.0.1.1\t%s\n' "$HOST_NAME" >>"$target/etc/hosts"
+1 -1
View File
@@ -1,6 +1,6 @@
# Template file for 'das-server-installer' # Template file for 'das-server-installer'
pkgname=das-server-installer pkgname=das-server-installer
version=0.4.0 version=0.5.0
revision=1 revision=1
depends="bash dialog das-install-common btrfs-progs dosfstools gptfdisk parted depends="bash dialog das-install-common btrfs-progs dosfstools gptfdisk parted
rsync util-linux grub grub-x86_64-efi efibootmgr" rsync util-linux grub grub-x86_64-efi efibootmgr"
+2 -2
View File
@@ -1,9 +1,9 @@
# Template file for 'das-server' # Template file for 'das-server'
pkgname=das-server pkgname=das-server
version=0.3.0 version=0.4.0
revision=1 revision=1
depends="openssh chrony dhcpcd NetworkManager docker docker-compose nftables depends="openssh chrony dhcpcd NetworkManager docker docker-compose nftables
fail2ban socklog-void python3 curl lazydocker lazygit mc tmux htop fail2ban socklog-void python3 curl lazydocker lazygit mc tmux htop ncdu
das-snapshots das-update das-helpers das-shell xtools-minimal" das-snapshots das-update das-helpers das-shell xtools-minimal"
short_desc="Das OS server: packages and secure defaults for SSH, firewall and Docker" short_desc="Das OS server: packages and secure defaults for SSH, firewall and Docker"
maintainer="Das <anry.das@gmail.com>" maintainer="Das <anry.das@gmail.com>"
@@ -17,7 +17,7 @@ from textual.widgets import (Button, Checkbox, Footer, Header, Input, Label, Lis
from . import banner, widgets from . import banner, widgets
from .canvas import TOOLS, Canvas from .canvas import TOOLS, Canvas
from .i18n import t, title 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 = { TOOL_NAMES = {
"pen": ("Олівець", "Pen"), "eraser": ("Гумка", "Eraser"), "line": ("Лінія", "Line"), "pen": ("Олівець", "Pen"), "eraser": ("Гумка", "Eraser"), "line": ("Лінія", "Line"),
@@ -657,7 +657,8 @@ class StartScreen(Screen):
CSS = """ CSS = """
#list { width: 46; border-right: solid $primary; } #list { width: 46; border-right: solid $primary; }
#start_preview { padding: 0 1; } #start_preview { padding: 0 1; }
.buttons { height: 3; dock: bottom; } #start_main { height: 1fr; }
.buttons { height: auto; }
.buttons Button { margin-right: 1; } .buttons Button { margin-right: 1; }
""" """
BINDINGS = [ BINDINGS = [
@@ -671,7 +672,7 @@ class StartScreen(Screen):
def compose(self): def compose(self):
yield Header() yield Header()
with Horizontal(): with Horizontal(id="start_main"):
yield ListView(id="list") yield ListView(id="list")
yield VerticalScroll(Static(id="start_preview")) yield VerticalScroll(Static(id="start_preview"))
with Horizontal(classes="buttons"): with Horizontal(classes="buttons"):
@@ -769,6 +770,7 @@ class BannerApp(App):
def __init__(self): def __init__(self):
# The terminal's own 16 colors: the picture looks as it will at login # The terminal's own 16 colors: the picture looks as it will at login
console_mode()
super().__init__(ansi_color=True) super().__init__(ansi_color=True)
def on_mount(self): def on_mount(self):
@@ -275,6 +275,10 @@ class _Bash:
current = style current = style
if isinstance(p, Lit): if isinstance(p, Lit):
out.append(_ps1_text(self.glyphs(p.text))) 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): elif isinstance(p, Esc):
out.append(p.code) out.append(p.code)
elif isinstance(p, Dyn): elif isinstance(p, Dyn):
@@ -13,7 +13,7 @@ from textual.widgets import Button, Checkbox, Footer, Header, Input, Label, List
from . import prompt from . import prompt
from .cli_prompt import apply as apply_design, current from .cli_prompt import apply as apply_design, current
from .i18n import t 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) # Settings of each segment type: (key, kind, Ukrainian label, English label)
COLOR_KEYS = [("fg", "color", "Колір", "Color"), ("bold", "bool", "Жирний", "Bold")] COLOR_KEYS = [("fg", "color", "Колір", "Color"), ("bold", "bool", "Жирний", "Bold")]
@@ -83,6 +83,7 @@ class PromptApp(App):
def __init__(self, design=None): def __init__(self, design=None):
# The terminal's own 16 colors, as the prompt will use them # The terminal's own 16 colors, as the prompt will use them
console_mode()
super().__init__(ansi_color=True) super().__init__(ansi_color=True)
self.design, self.source = (design, None) if design else current() self.design, self.source = (design, None) if design else current()
self.design = prompt.normalize(self.design) self.design = prompt.normalize(self.design)
@@ -15,9 +15,39 @@ from textual.widgets import Button, Input, Label, Select
from . import colors from . import colors
from .i18n import t from .i18n import t
from .prompt import CONSOLE_GLYPHS as PROMPT_CONSOLE_GLYPHS
NONE = "-" # Select has no None value 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): def color_options(allow_none=True):
names = { names = {
@@ -35,6 +35,11 @@ class PresetTest(unittest.TestCase):
self.assertNotIn("──", text(d)) self.assertNotIn("──", text(d))
self.assertIn("─[main*]─[.venv]─[jobs:2]", text(d, git="main*", venv=".venv", jobs=2)) 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): def test_unknown_segments_are_dropped(self):
d = prompt.normalize({"segments": [{"type": "nope"}, {"type": "cwd"}]}) d = prompt.normalize({"segments": [{"type": "nope"}, {"type": "cwd"}]})
self.assertEqual([s["type"] for s in d["segments"]], ["cwd"]) self.assertEqual([s["type"] for s in d["segments"]], ["cwd"])
+1 -1
View File
@@ -1,7 +1,7 @@
# Template file for 'das-shell' # Template file for 'das-shell'
# In-tree package: sources are in files/ (FILESDIR). # In-tree package: sources are in files/ (FILESDIR).
pkgname=das-shell pkgname=das-shell
version=0.1.0 version=0.2.0
revision=1 revision=1
create_wrksrc=yes create_wrksrc=yes
hostmakedepends="python3" hostmakedepends="python3"