From d3bc5ba321a4f463f555de72f5a3e2d6360d0341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82?= Date: Thu, 27 Aug 2026 20:46:21 +0200 Subject: [PATCH] feat: DE/WM selection with cross-distro package mappings - 12 DE/WMs: sway, i3, Hyprland, GNOME, KDE, XFCE, Cinnamon, MATE, LXQt, bspwm, openbox, Headless - 5 distro families: void, arch, debian, alpine, fedora - Correct package names per distro (researched from archinstall + distro repos) - Shows availability table with package counts - Warns if DE/WM unavailable on selected distro --- euri_mklive/tui.py | 171 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 169 insertions(+), 2 deletions(-) diff --git a/euri_mklive/tui.py b/euri_mklive/tui.py index fb3ac52..0885449 100644 --- a/euri_mklive/tui.py +++ b/euri_mklive/tui.py @@ -35,12 +35,124 @@ COMMON_PACKAGES = { "Base": ["base-system", "sudo", "bash"], "Networking": ["NetworkManager", "dhcpcd", "openssh", "iw", "wpa_supplicant"], "Development": ["gcc", "make", "git", "python3", "cmake"], - "Desktop": ["firefox", "foot", "dmenu", "sway", "xorg-server-xwayland"], "Fonts": ["font-noto", "font-dejavu"], "Audio": ["pipewire", "wireplumber", "alsa-utils"], "Firmware": ["linux-firmware", "linux-firmware-network", "linux-firmware-amd"], } +# Cross-distro DE/WM package mapping +# Keys: distro families (void, arch, debian, alpine, fedora) +DE_WM_PACKAGES = { + "Sway": { + "desc": "Wayland tiling WM — minimal, keyboard-driven", + "server": "wayland", + "void": ["sway", "foot", "waybar", "swaybg", "swaylock", "swayidle", "xorg-server-xwayland", "wmenu", "grim", "slurp", "wl-clipboard", "dinit"], + "arch": ["sway", "foot", "waybar", "swaybg", "swaylock", "swayidle", "xorg-xwayland", "wmenu", "grim", "slurp", "wl-clipboard"], + "debian": ["sway", "foot", "waybar", "swaybg", "swaylock", "swayidle", "xwayland", "wmenu", "grim", "slurp", "wl-clipboard"], + "alpine": ["sway", "foot", "waybar", "swaybg", "swaylockd", "swayidle", "xwayland", "wmenu", "grim", "wl-clipboard", "brightnessctl"], + "fedora": ["sway", "foot", "waybar", "swaybg", "swaylock", "swayidle", "xorg-x11-server-Xwayland", "wofi", "grim", "slurp", "wl-clipboard"], + }, + "i3": { + "desc": "X11 tiling WM — keyboard-driven, highly configurable", + "server": "x11", + "void": ["i3", "i3status", "dmenu", "rofi", "dunst", "xorg", "lightdm"], + "arch": ["i3-wm", "i3status", "i3blocks", "dmenu", "rofi", "dunst", "xorg-server", "lightdm", "lightdm-gtk-greeter"], + "debian": ["i3", "i3status", "dmenu", "rofi", "dunst", "xorg", "lightdm"], + "alpine": ["i3wm", "i3status", "dmenu", "rofi", "xorg-server", "lightdm"], + "fedora": ["i3", "i3status", "dmenu", "rofi", "dunst", "xorg-x11-server-Xorg", "lightdm"], + }, + "Hyprland": { + "desc": "Wayland dynamic tiling — animations, eye candy", + "server": "wayland", + "void": [], # not in official repos + "arch": ["hyprland", "kitty", "waybar", "wofi", "dunst", "xdg-desktop-portal-hyprland", "hypridle", "hyprlock", "qt5-wayland", "qt6-wayland", "polkit"], + "debian": ["hyprland", "kitty", "waybar", "wofi", "dunst", "xdg-desktop-portal-hyprland", "xwayland", "polkit"], + "alpine": [], # not in official repos + "fedora": ["hyprland", "kitty", "waybar", "wofi", "dunst", "xdg-desktop-portal-hyprland", "hypridle", "hyprlock", "polkit"], + }, + "GNOME": { + "desc": "Full desktop — polished, Wayland by default", + "server": "wayland", + "void": ["gnome", "gnome-terminal", "gdm", "gnome-tweaks", "xorg"], + "arch": ["gnome", "gnome-extra", "gdm", "gnome-terminal", "xdg-desktop-portal-gnome"], + "debian": ["gnome", "gdm3", "gnome-terminal", "xdg-desktop-portal-gnome", "xorg"], + "alpine": ["gnome", "gdm", "gnome-terminal", "xorg-server"], + "fedora": ["gnome", "gdm", "gnome-terminal", "xdg-desktop-portal-gnome", "gnome-tweaks"], + }, + "KDE Plasma": { + "desc": "Full desktop — customizable, feature-rich", + "server": "wayland", + "void": ["plasma-desktop", "konsole", "sddm", "dolphin", "kate", "xorg"], + "arch": ["plasma-meta", "konsole", "sddm", "dolphin", "kate", "xdg-desktop-portal-kde", "xorg-server"], + "debian": ["kde-plasma-desktop", "konsole", "sddm", "dolphin", "kate", "xdg-desktop-portal-kde", "xorg"], + "alpine": ["plasma-desktop-meta", "konsole", "sddm", "oxygen", "xorg-server"], + "fedora": ["plasma-desktop", "konsole", "sddm", "dolphin", "kate", "xdg-desktop-portal-kde", "qt6-wayland"], + }, + "XFCE": { + "desc": "Lightweight desktop — traditional, fast", + "server": "x11", + "void": ["xfce4", "xfce4-terminal", "lightdm", "gvfs", "xorg"], + "arch": ["xfce4", "xfce4-goodies", "xfce4-terminal", "lightdm", "lightdm-gtk-greeter", "xorg-server"], + "debian": ["xfce4", "xfce4-goodies", "xfce4-terminal", "lightdm", "xorg", "gvfs"], + "alpine": ["xfce4", "xfce4-terminal", "lightdm", "xorg-server", "elogind"], + "fedora": ["xfce4-session", "xfce4-terminal", "lightdm", "xorg-x11-server-Xorg"], + }, + "Cinnamon": { + "desc": "Modern traditional desktop — Windows-like", + "server": "x11", + "void": ["cinnamon", "gnome-terminal", "lightdm", "nemo", "xorg"], + "arch": ["cinnamon", "gnome-terminal", "lightdm", "lightdm-gtk-greeter", "nemo", "xorg-server"], + "debian": ["cinnamon", "gnome-terminal", "lightdm", "nemo", "xorg"], + "alpine": [], # limited support + "fedora": ["cinnamon", "gnome-terminal", "lightdm", "nemo", "xorg-x11-server-Xorg"], + }, + "MATE": { + "desc": "Traditional desktop — GNOME 2 fork, lightweight", + "server": "x11", + "void": ["mate", "mate-terminal", "lightdm", "caja", "xorg"], + "arch": ["mate", "mate-extra", "mate-terminal", "lightdm", "lightdm-gtk-greeter", "caja", "xorg-server"], + "debian": ["mate-desktop-environment", "mate-terminal", "lightdm", "caja", "xorg"], + "alpine": ["mate-desktop-environment", "mate-terminal", "lightdm", "xorg-server"], + "fedora": ["mate-desktop", "mate-terminal", "lightdm", "caja", "xorg-x11-server-Xorg"], + }, + "LXQt": { + "desc": "Ultra-lightweight desktop — Qt-based", + "server": "x11", + "void": ["lxqt", "qterminal", "sddm", "openbox", "xorg"], + "arch": ["lxqt", "qterminal", "sddm", "openbox", "xorg-server"], + "debian": ["lxqt", "qterminal", "sddm", "openbox", "xorg"], + "alpine": ["lxqt-desktop", "qterminal", "sddm", "openbox", "xorg-server"], + "fedora": ["lxqt", "qterminal", "sddm", "openbox", "xorg-x11-server-Xorg"], + }, + "bspwm": { + "desc": "X11 tiling WM — binary space partitioning", + "server": "x11", + "void": ["bspwm", "sxhkd", "alacritty", "polybar", "dmenu", "rofi", "picom", "dunst", "xorg"], + "arch": ["bspwm", "sxhkd", "alacritty", "polybar", "dmenu", "rofi", "picom", "dunst", "xorg-server"], + "debian": ["bspwm", "sxhkd", "alacritty", "polybar", "dmenu", "rofi", "picom", "dunst", "xorg"], + "alpine": ["bspwm", "sxhkd", "alacritty", "polybar", "dmenu", "rofi", "xorg-server"], + "fedora": ["bspwm", "sxhkd", "alacritty", "polybar", "dmenu", "rofi", "picom", "dunst", "xorg-x11-server-Xorg"], + }, + "openbox": { + "desc": "X11 stacking WM — minimalist, scriptable", + "server": "x11", + "void": ["openbox", "alacritty", "obconf", "tint2", "rofi", "picom", "dunst", "xorg"], + "arch": ["openbox", "alacritty", "obconf", "tint2", "rofi", "picom", "dunst", "xorg-server"], + "debian": ["openbox", "alacritty", "obconf", "tint2", "rofi", "picom", "dunst", "xorg"], + "alpine": ["openbox", "alacritty", "obconf", "tint2", "rofi", "xorg-server"], + "fedora": ["openbox", "alacritty", "obconf", "tint2", "rofi", "picom", "dunst", "xorg-x11-server-Xorg"], + }, + "Headless (no DE)": { + "desc": "Server / minimal — no graphical environment", + "server": "none", + "void": [], + "arch": [], + "debian": [], + "alpine": [], + "fedora": [], + }, +} + def _check_fakeroot() -> bool: """Check if fakeroot is available.""" @@ -296,6 +408,7 @@ def confirm_build(cfg: dict) -> bool: table.add_row("Arch", cfg["arch"]) table.add_row("Init", cfg["init"]) table.add_row("Libc", cfg["libc"]) + table.add_row("DE/WM", cfg.get("de_wm", "none")) table.add_row("Packages", str(len(cfg.get("packages", [])))) table.add_row("ISO name", cfg["iso"]["name"]) table.add_row("Version", cfg["iso"]["version"]) @@ -319,6 +432,50 @@ def confirm_build(cfg: dict) -> bool: return questionary.confirm("Start build?", default=True).ask() or sys.exit(0) +def select_de_wm(distro: str) -> tuple[str, list[str]]: + """Pick a DE or window manager — returns (name, distro-specific packages).""" + console.print("[bold]Step 5b: Desktop Environment / Window Manager[/]\n") + + # map distro to family + distro_family = { + "void": "void", "arch": "arch", "artix": "arch", + "debian": "debian", "ubuntu": "debian", + "alpine": "alpine", + "fedora": "fedora", "rocky": "fedora", "almalinux": "fedora", + }.get(distro, "arch") + + # show table + de_table = Table(show_header=True, border_style="dim", pad_edge=False) + de_table.add_column("#", style="cyan", width=3) + de_table.add_column("DE/WM", style="bold") + de_table.add_column("Type") + de_table.add_column("Description") + for i, (name, info) in enumerate(DE_WM_PACKAGES.items(), 1): + pkgs = info.get(distro_family, []) + status = f"[green]{len(pkgs)} pkgs[/]" if pkgs else "[red]unavailable[/]" + server = info.get("server", "") + de_table.add_row(str(i), name, server, f"{info['desc']} ({status})") + console.print(de_table) + console.print() + + names = list(DE_WM_PACKAGES.keys()) + choice = questionary.select( + "Pick a DE/WM:", + choices=names, + ).ask() + if choice is None: + sys.exit(0) + + pkgs = DE_WM_PACKAGES.get(choice, {}).get(distro_family, []) + if not pkgs: + console.print(f" [yellow]Warning:[/] {choice} is not available in {distro} repos.") + console.print(f" [dim]Continuing without DE/WM packages.[/]\n") + else: + console.print(f" [green]{len(pkgs)} packages[/] for {choice} on {distro}\n") + + return choice, pkgs + + def build_progress(cfg: dict, func, *args, **kwargs): """Run a function with a rich progress spinner.""" from rich.progress import Progress, SpinnerColumn, TextColumn @@ -347,15 +504,25 @@ def run_interactive() -> dict: libc = select_libc(distro) arch = select_arch() pkgs = select_packages() + de_name, de_pkgs = select_de_wm(distro) iso = configure_iso() + # merge packages: base groups + DE/WM + seen = set() + merged = [] + for p in pkgs + de_pkgs: + if p not in seen: + seen.add(p) + merged.append(p) + cfg = { "distro": distro, "arch": arch, "init": init, "libc": libc, "hostname": iso["hostname"], - "packages": pkgs, + "packages": merged, + "de_wm": de_name, "services": [], "users": [], "iso": {