diff --git a/extra/arch-linux.sh b/extra/arch-linux.sh new file mode 100755 index 0000000..6aba612 --- /dev/null +++ b/extra/arch-linux.sh @@ -0,0 +1,229 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Keep select menus one item per line for screen readers. +export COLUMNS=1 + +missingRequired=() +installPlan=() + +add_missing_package() { + local package="$1" + local existing + + for existing in "${missingRequired[@]}"; do + [[ "$existing" == "$package" ]] && return + done + missingRequired+=("$package") +} + +add_install_package() { + local package="$1" + local existing + + for existing in "${installPlan[@]}"; do + [[ "$existing" == "$package" ]] && return + done + installPlan+=("$package") +} + +command_exists() { + command -v "$1" &> /dev/null +} + +python_import_works() { + local code="$1" + + command_exists python3 && python3 -c "$code" &> /dev/null +} + +has_any_command() { + local commandName + + for commandName in "$@"; do + if command_exists "$commandName"; then + return 0 + fi + done + return 1 +} + +prompt_install() { + local prompt="$1" + shift + local packages=("$@") + local choice + + printf '%s\n' "$prompt" + printf 'Packages: %s\n' "${packages[*]}" + PS3="Select an option: " + select choice in "Yes" "Exit installer"; do + case "$choice" in + "Yes") + for package in "${packages[@]}"; do + add_install_package "$package" + done + return + ;; + "Exit installer") + echo "Exiting without installing packages." + exit 1 + ;; + *) + echo "Please choose 1 or 2." + ;; + esac + done +} + +install_packages() { + if command_exists yay; then + yay -S --needed "$@" + else + sudo pacman -S --needed "$@" + fi +} + +prompt_install_choice() { + local prompt="$1" + shift + local choice + local index + local reply + local options=("Skip" "$@" "Exit installer") + local packages + + printf '%s\n' "$prompt" + while true; do + for index in "${!options[@]}"; do + printf '%d) %s\n' "$((index + 1))" "${options[$index]}" + done + read -r -p "Select a package to install [1]: " reply + if [[ -z "$reply" ]]; then + reply=1 + fi + if [[ ! "$reply" =~ ^[0-9]+$ ]] || (( reply < 1 || reply > ${#options[@]} )); then + echo "Please choose a listed option." + continue + fi + choice="${options[$((reply - 1))]}" + case "$choice" in + "Skip") + return + ;; + "Exit installer") + echo "Exiting without installing packages." + exit 1 + ;; + *) + read -r -a packages <<< "$choice" + for package in "${packages[@]}"; do + add_install_package "$package" + done + return + ;; + esac + done +} + +check_required_dependencies() { + command_exists dialog || add_missing_package dialog + command_exists i3 || add_missing_package i3-wm + command_exists jq || add_missing_package jq + command_exists python3 || add_missing_package python + command_exists rsync || add_missing_package rsync + command_exists yad || add_missing_package yad + command_exists xdotool || add_missing_package xdotool + command_exists xdg-open || add_missing_package xdg-utils + + if ! python_import_works 'import i3ipc'; then + add_missing_package python-i3ipc + fi + + if ! python_import_works 'import gi; gi.require_version("Atk", "1.0"); gi.require_version("Gdk", "3.0"); gi.require_version("Gio", "2.0"); gi.require_version("GLib", "2.0"); gi.require_version("Gtk", "3.0"); from gi.repository import Atk, Gdk, Gio, GLib, Gtk'; then + add_missing_package python-gobject + fi + + if ! command_exists pandoc && ! command_exists markdown; then + add_missing_package discount + fi +} + +check_provider_dependencies() { + local emailChoices=(thunderbird evolution) + local browserChoices=(firefox chromium epiphany midori seamonkey vivaldi) + local screenReaderChoices=(orca) + + if command_exists yay; then + emailChoices+=(betterbird) + browserChoices+=(brave-bin) + screenReaderChoices+=(cthulhu) + fi + + if ! has_any_command betterbird evolution thunderbird; then + prompt_install_choice "Missing email client. Select one to install." "${emailChoices[@]}" + fi + + if ! has_any_command brave chromium epiphany firefox google-chrome-stable google-chrome-unstable microsoft-edge-stable microsoft-edge-beta microsoft-edge-dev midori seamonkey vivaldi; then + prompt_install_choice "Missing web browser. Select one to install." "${browserChoices[@]}" + fi + + if ! has_any_command emacs geany gedit kate kwrite l3afpad leafpad libreoffice mousepad pluma; then + prompt_install_choice "Missing graphical text editor. Select one to install." geany gedit kate kwrite l3afpad leafpad libreoffice-fresh mousepad pluma + fi + + if ! has_any_command caja nemo nautilus pcmanfm pcmanfm-qt thunar; then + prompt_install_choice "Missing file manager. Select one to install." pcmanfm thunar caja nemo nautilus pcmanfm-qt + fi + + if ! has_any_command mate-terminal lxterminal gnome-terminal terminator xfce4-terminal tilix ptyxis kgx sakura roxterm termit guake tilda qterminal konsole && { ! command_exists xterm || ! command_exists fenrir; }; then + prompt_install_choice "Missing supported accessible terminal. Select one to install." mate-terminal lxterminal gnome-terminal terminator xfce4-terminal tilix ptyxis kgx sakura qterminal konsole "xterm fenrir" + fi + + if ! has_any_command cthulhu orca; then + prompt_install_choice "Missing screen reader. Select one to install." "${screenReaderChoices[@]}" + fi +} + +add_optional_dependencies() { + command_exists bc || add_install_package bc + command_exists notify-send || add_install_package libnotify + command_exists pamixer || add_install_package pamixer + command_exists playerctl || add_install_package playerctl + command_exists scrot || add_install_package scrot + command_exists sox || add_install_package sox + command_exists udiskie || add_install_package udiskie + command_exists xclip || add_install_package xclip + command_exists xprintidle || add_install_package xprintidle + command_exists xset || add_install_package xorg-xset + + echo "Skipping optional packages that need manual choice or are intentionally not installed automatically:" + echo " dex" + echo " tesseract" + echo " xzoom" +} + +if ! command_exists pacman && ! command_exists yay; then + echo "This helper is for Arch Linux systems with pacman or yay." + exit 1 +fi + +check_required_dependencies + +if [[ ${#missingRequired[@]} -gt 0 ]]; then + prompt_install "Missing required I38 dependencies. Add them to the install list?" "${missingRequired[@]}" +fi + +check_provider_dependencies +add_optional_dependencies + +if [[ ${#installPlan[@]} -gt 0 ]]; then + echo "Installing selected packages:" + printf ' %s\n' "${installPlan[@]}" + install_packages "${installPlan[@]}" +else + echo "No packages selected for installation." +fi + +echo "I38 dependency check complete."