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
This commit is contained in:
+169
-2
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user