imports/dream.sh
2025-05-23 21:24:10 +02:00

913 lines
23 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# NOTE:
# ──────────────────────────────────────< distros.sh >──────────────────────────────────────
# ╭──────────────────────────────╮
# │ User variables and functions │
# ╰──────────────────────────────╯
distro=""
ubuntu="false"
debian="false"
arch="false"
fedora="false"
alpine="false"
opensuse="false"
# Basic Colors
BLACK=$'\e[30m'
RED=$'\e[31m'
GREEN=$'\e[32m'
YELLOW=$'\e[33m'
BLUE=$'\e[34m'
MAGENTA=$'\e[35m'
CYAN=$'\e[36m'
WHITE=$'\e[37m'
# Bright Colors
BRIGHT_BLACK=$'\e[90m'
BRIGHT_RED=$'\e[91m'
BRIGHT_GREEN=$'\e[92m'
BRIGHT_YELLOW=$'\e[93m'
BRIGHT_BLUE=$'\e[94m'
BRIGHT_MAGENTA=$'\e[95m'
BRIGHT_CYAN=$'\e[96m'
BRIGHT_WHITE=$'\e[97m'
# Background Colors (standard)
BG_BLACK=$'\e[40m'
BG_RED=$'\e[41m'
BG_GREEN=$'\e[42m'
BG_YELLOW=$'\e[43m'
BG_BLUE=$'\e[44m'
BG_MAGENTA=$'\e[45m'
BG_CYAN=$'\e[46m'
BG_WHITE=$'\e[47m'
# Background Bright Colors
BG_BRIGHT_BLACK=$'\e[100m'
BG_BRIGHT_RED=$'\e[101m'
BG_BRIGHT_GREEN=$'\e[102m'
BG_BRIGHT_YELLOW=$'\e[103m'
BG_BRIGHT_BLUE=$'\e[104m'
BG_BRIGHT_MAGENTA=$'\e[105m'
BG_BRIGHT_CYAN=$'\e[106m'
BG_BRIGHT_WHITE=$'\e[107m'
# Styles
BOLD=$'\e[1m'
ITALIC=$'\e[3m'
UNDERLINE=$'\e[4m'
BLINK=$'\e[5m' # May not work in all terminals
INVERT=$'\e[7m' # Invert foreground/background
STRIKE=$'\e[9m' # Strikethrough
# Reset
NC=$'\e[0m' # Reset all styles/colors
# INFO:
# ↓ should get set in the install script itself
# ↓
# echo with $PACKAGE and first argument, if 2 exist
echo_pkg() {
# if arg 2 does not exist, use normal echo
if [[ -z $2 ]]; then
case "$1" in
build)
echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-build:${NC}${BRIGHT_BLUE} Building $PACKAGE ${NC}"
;;
clone)
echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-clone:${NC}${BRIGHT_YELLOW} Cloning $PACKAGE sources..${NC}"
;;
install)
echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-install:${NC}${BRIGHT_GREEN} Installing $PACKAGE now!${NC}"
;;
*)
echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}:${NC}${YELLOW} $1 ${NC}"
;;
esac
else
case "$1" in
deps | dep | dependencies)
echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-${pkger:-dependencies}:${BRIGHT_YELLOW} $2 ${NC}"
;;
*)
echo "${BOLD}${BRIGHT_RED}${PACKAGE:-PKG}-$1:${NC}${BRIGHT_YELLOW} $2 ${NC}"
;;
esac
fi
}
# alias for echo_pkg
echo-pkg() {
echo_pkg "$@"
}
echo-error() {
echo "${BOLD}${RED}${UNDERLINE}ERROR:${NC}${BRIGHT_RED} $1 ${NC}" >&2
}
command-exists() {
command -v "$@" >/dev/null 2>&1
}
silentexec() {
"$@" >/dev/null 2>&1
}
run-silent() {
if [[ -z $silent ]] || ! $silent; then
"$@"
else
silentexec "$@"
fi
}
# if given an array, it checks if the command is available, and if not - installs all packages in that array one by one
check-and-install() {
local pkg=$1
# echo "DEBUG:: GOT ARRAY :: ${@}"
# INFO: if it's not a list, then just check and install the package..
if [[ -z $2 ]]; then
spin bold yellow "Installing $pkg"
if ! command-exists "$pkg"; then
if run pkg-install "$pkg"; then
check bold "$(pen green bold 'Installed') $pkg"
else
throw bold red "Error installing $pkg"
fi
else
check bold "$pkg $(pen grey bold 'was already installed')"
# echo_pkg deps "skipping $pkg - as it's ${RED}already installed.."
fi
else
local pkgs="${#@}"
# ─< else go though the list of items and do the same >───────────────────────────────────
pen grey "Packages to install: $(pen green bold $pkgs)"
for pkg in "$@"; do
if ! command-exists $pkg; then
spin bold "$(pen bold yellow Installing) $pkg"
if run --err err pkg-install $pkg; then
upclear
check "$(pen bold green Installed) $pkg"
else
upclear
throw "Something went wrong! Could not install $(pen bold red $pkg)"
echo-error "${err:-}"
fi
else
check "$pkg $(pen grey already installed)"
fi
done
fi
}
# ─< Check if the user is root and set sudo variable if necessary >───────────────────────
check_env() {
if [ "$(id -u)" -ne 0 ]; then
if command-exists sudo; then
_sudo="sudo -E"
pen blue "Testing your access.."
$_sudo echo "${GREEN}${BOLD}Aye, it works!${NC}"
else
echo-error "No sudo found and you're not root! Can't install packages."
return 69
fi
else
pen bold red "Root access confirmed."
_sudo=""
fi
checkFileAge() {
local file="$1"
[[ ! -e "$file" ]] && return 2 # File doesn't exist
if [[ $(find "$file" -mtime +7 -print) ]]; then
return 69 # File is older than 1 week
else
return 0 # File is within 1 week
fi
}
}
# CAUTION:
# ╭──────────────────────────────────────────────────────────────────────╮
# │ This can break really quickly, since the pkg-remove function removes │
# │ without confirmation! use with CAUTION!! │
# ╰──────────────────────────────────────────────────────────────────────╯
_setup() {
case "$1" in
debian | ubuntu)
pkg-install() {
# $_sudo apt-get install --assume-yes "$@"
if command-exists nala; then
pkger=nala
$_sudo nala install --assume-yes "$@"
else
pkger=apt-get
$_sudo apt-get install --assume-yes "$@"
fi
}
# CAUTION:
pkg-remove() {
if command-exists nala; then
pkger=nala
$_sudo nala remove --assume-yes "$@"
$_sudo nala autoremove --assume-yes
$_sudo nala autopurge --assume-yes
else
pkger=apt-get
$_sudo apt-get remove --assume-yes "$@"
$_sudo apt-get autoremove --assume-yes
fi
}
;;
fedora)
pkg-install() {
pkger=dnf
$_sudo dnf -y install "$@"
}
# CAUTION:
pkg-remove() {
pkger=dnf
$_sudo dnf -y remove "$@"
}
;;
arch)
pkg-install() {
if command-exists paru; then
pkger=paru
paru -S --color always --noconfirm --needed "$@"
elif command-exists yay; then
pkger=yay
yay -S --color always --noconfirm --needed "$@"
else
pkger=pacman
$_sudo pacman -S --color always --noconfirm --needed "$@"
fi
}
# CAUTION:
pkg-remove() {
if command-exists paru; then
pkger=paru
paru -R --color always --noconfirm "$@"
elif command-exists yay; then
pkger=yay
yay -R --color always --noconfirm "$@"
else
pkger=pacman
$_sudo pacman -R --color always --noconfirm "$@"
fi
}
;;
opensuse)
pkg-install() {
pkger=zypper
$_sudo zypper in "$@"
}
# CAUTION:
pkg-remove() {
pkger=zypper
$_sudo zypper rem "$@"
}
;;
alpine)
pkg-install() {
pkger=apk
apk add "$@"
}
# CAUTION:
pkg-remove() {
pkger=apk
apk remove "$@"
}
;;
esac
}
# ─< Distribution detection and installation >────────────────────────────────────────
get_packager() {
# ─< define fallback function >───────────────────────────────────────────────────────────
fallback() {
local pkger=""
for pkg in apt-get dnf pacman apk zypper; do
if command-exists $pkg; then
printf "Using ${RED}${pkg}${NC} method.."
pkger="$pkg"
break
fi
done
case "$pkger" in
apt-get)
ubuntu="true"
debian="true"
distro="debian"
;;
dnf)
fedora="true"
distro="fedora"
;;
apk)
alpine="true"
distro="alpine"
;;
pacman)
arch="true"
distro="arch"
;;
zypper)
opensuse="true"
distro="opensuse"
;;
*)
pen red bold "Can not detect distribution correctly!"
return 69
;;
esac
}
if [ -e /etc/os-release ]; then
upclear
pen bold grey "Detecting distribution..."
. /etc/os-release
# ─< Convert $ID and $ID_LIKE to lowercase >──────────────────────────────────────────────
ID=$(printf "%s" "$ID" | tr '[:upper:]' '[:lower:]')
ID_LIKE=$(printf "%s" "$ID_LIKE" | tr '[:upper:]' '[:lower:]')
case "$ID" in
ubuntu | pop | zorin | kubuntu | linuxmintubuntu)
ubuntu="true"
distro="ubuntu"
;;
debian | kali | linuxmint | elementary | neon | kdeneon | deepin)
debian="true"
distro="debian"
;;
fedora | centos | rhel | rocky | almalinux)
fedora="true"
distro="fedora"
;;
alpine)
alpine="true"
distro="alpine"
;;
arch | manjaro | garuda | endeavour)
arch="true"
distro="arch"
;;
opensuse*)
opensuse="true"
distro="opensuse"
;;
*)
if [ "${ID_LIKE#*debian}" != "$ID_LIKE" ]; then
debian="true"
distro="debian"
elif [ "${ID_LIKE#*ubuntu}" != "$ID_LIKE" ]; then
ubuntu="true"
distro="ubuntu"
elif [ "${ID_LIKE#*arch}" != "$ID_LIKE" ]; then
arch="true"
distro="arch"
elif [ "${ID_LIKE#*fedora}" != "$ID_LIKE" ]; then
fedora="true"
distro="fedora"
elif [ "${ID_LIKE#*suse}" != "$ID_LIKE" ]; then
opensuse="true"
distro="opensuse"
else
pen bold red "Unsupported distribution: $ID"
spin bold "Trying other methods.."
sleep 1
run fallback && check "Got packager.." || throw "No chance helping you now buddy!"
fi
;;
esac
else
pen red bold "Unable to detect distribution - /etc/os-release not found."
spin bold "Trying other methods.."
sleep 1
if run fallback; then
upclear
check "Got packager.."
else
upclear
throw "No chance helping you now buddy!"
fi
fi
}
# INFO:
# ╭────────────────────────────────────────────────────────────────────────────────────────╮
# │ Automated setup for refreshing repositories and overall getting the variables to setup │
# ╰────────────────────────────────────────────────────────────────────────────────────────╯
dist_setup() {
case "$distro" in
debian)
repen bold "Found $(pen red bold $distro)"
_setup debian
# Codename support
if [ -n $VERSION_CODENAME ]; then
export $VERSION_CODENAME=$VERSION_CODENAME
# case "$VERSION_CODENAME" in
# trixie) trixie=true ;;
# bookworm) bookworm=true ;;
# bullseye) bullseye=true ;;
# buster) buster=true ;;
# esac
fi
;;
ubuntu)
repen bold "Found $(pen yellow bold $distro)"
_setup ubuntu
# Codename support
if [ -n $VERSION_CODENAME ]; then
export $VERSION_CODENAME=$VERSION_CODENAME
# case "$VERSION_CODENAME" in
# noble) noble=true ;;
# jammy) jammy=true ;;
# focal) focal=true ;;
# bionic) bionic=true ;;
# esac
fi
;;
fedora)
repen bold "Found $(pen blue bold $distro)"
_setup fedora
# Add version-specific var like: fedora_40=true
fedora_version="fedora_${VERSION_ID//./_}"
eval "$fedora_version=true"
;;
arch)
repen bold "Found $(pen blue bold $distro)"
_setup arch
if command-exists yay || command_exists paru; then
aur=true
else
aur=false
fi
;;
alpine)
repen bold "Found $(pen blue bold $distro)"
_setup $distro
;;
opensuse)
repen bold "Found $(pen green bold $distro)"
_setup $distro
;;
esac
}
update-package-list() {
local USER="${USER:-$(whoami)}"
repo::check() {
check "${distro}-repositories up to date" || throw "Error while updating $distro repositories.."
}
case "$distro" in
ubuntu | debian)
spin bold red "Refreshing $distro sources.."
run $_sudo apt-get update || repo::check
;;
fedora)
spin blue bold "Refreshing $distro repositories.."
run $_sudo dnf update || repo::check
;;
arch)
if command-exists pacman; then
if ! $aur; then
pen grey bold "If this is your first time after boot (or simmilarly soon) then this might take a while.."
spin bold grey "You don't have an AUR helper, gonna install one for ya!"
local paruBuildDir="/opt/builds"
silentexec $_sudo mkdir -p "$paruBuildDir"
# echo "${YELLOW}Installing paru as AUR helper...${NC}"
run $_sudo pacman -S --needed --noconfirm base-devel git || throw "Error installing dependencies.."
local url="https://aur.archlinux.org/paru-bin.git"
cd "$paruBuildDir" # && echo "${YELLOW} Cloning paru from ${NC}https://aur.archlinux.org/paru-bin.git"
run $_sudo git clone $url paru || throw "Error cloning sources from $url"
run $_sudo chown -R "$USER": "$paruBuildDir/paru"
cd "$paruBuildDir/paru"
local err
if run --err err makepkg --noconfirm -si; then
check "Successfully installed $(pen red bold paru)"
else
throw "Couldn't install paru!"
echo-error "${err:-}"
fi
if command-exists paru; then
pen green bold "Paru is installed"
else
echo-error "Something went wrong when installing paru!"
fi
fi
fi
spin blue bold "Refreshing $distro repositories.."
sleep 0.01
if command-exists paru; then
run paru -Sy || repo::check
elif command-exists yay; then
run yay -Sy || repo::check
else
run $_sudo pacman -Sy || repo::check
fi
;;
opensuse)
run $_sudo zypper ref || repo::check
;;
alpine) run $_sudo apk update || repo::check ;;
*)
echo-error "Unsupported distribution: ${BRIGHT_RED}$distro"
return 69
;;
esac
}
# NOTE:
# ────────────────────────────────────< end distros.sh >────────────────────────────────────
# ───────────────────────────────────────< beddu.sh >───────────────────────────────────────
#
# shellcheck disable=all
#
# beddu.sh - A lightweight bash framework for interactive scripts and pretty output
# Version: v1.1.0
#
# Copyright © 2025 Manuele Sarfatti
# Licensed under the MIT license
# See https://github.com/mjsarfatti/beddu
readonly _q='?'
readonly _a=''
readonly _o='◌'
readonly _O='●'
readonly _mark='✓'
readonly _warn='!'
readonly _cross='✗'
readonly _spinner='⣷⣯⣟⡿⢿⣻⣽⣾' # See for alternatives: https://antofthy.gitlab.io/info/ascii/Spinners.txt
readonly _spinner_frame_duration=0.15
up() {
printf "\033[A"
}
down() {
printf "\033[B"
}
bol() {
printf "\r"
}
eol() {
printf "\033[999C"
}
cl() {
printf "\033[2K"
}
upclear() {
up
bol
cl
}
line() {
printf "\n"
}
show_cursor() {
printf "\033[?25h"
}
hide_cursor() {
printf "\033[?25l"
}
pen() {
local new_line="\n"
local text="${*: -1}"
local args=("${@:1:$#-1}")
local format_code=""
local reset_code="\033[0m"
for arg in "${args[@]}"; do
arg=${arg,,}
case "$arg" in
-n) new_line="" ;;
bold) format_code+="\033[1m" ;;
italic) format_code+="\033[3m" ;;
underline) format_code+="\033[4m" ;;
black) format_code+="\033[30m" ;;
red) format_code+="\033[31m" ;;
green) format_code+="\033[32m" ;;
yellow) format_code+="\033[33m" ;;
blue) format_code+="\033[34m" ;;
purple) format_code+="\033[35m" ;;
cyan) format_code+="\033[36m" ;;
white) format_code+="\033[37m" ;;
grey | gray) format_code+="\033[90m" ;;
[0-9]*)
if [[ "$arg" =~ ^[0-9]+$ ]] && [ "$arg" -ge 0 ] && [ "$arg" -le 255 ]; then
format_code+="\033[38;5;${arg}m"
fi
;;
*) ;;
esac
done
printf "%b%s%b%b" "${format_code}" "${text}" "${reset_code}" "${new_line}"
}
run() {
local outvar_name errvar_name
local -n outvar errvar # Declare namerefs (will be assigned below if needed)
local cmd
while [[ $# -gt 0 ]]; do
case "$1" in
--out)
outvar_name="$2"
shift 2
;;
--err)
errvar_name="$2"
shift 2
;;
*)
cmd=("$@")
break
;;
esac
done
[[ -n "${outvar_name}" ]] && local -n outvar="${outvar_name}"
[[ -n "${errvar_name}" ]] && local -n errvar="${errvar_name}"
local stdout_file stderr_file
stdout_file=$(mktemp)
stderr_file=$(mktemp)
"${cmd[@]}" >"${stdout_file}" 2>"${stderr_file}"
local exit_code=$?
[[ -n "${outvar_name}" ]] && outvar="$(<"$stdout_file")"
[[ -n "${errvar_name}" ]] && errvar="$(<"$stderr_file")"
rm -f "${stdout_file}" "${stderr_file}"
return $exit_code
}
check() {
if spinning; then
spop
upclear
fi
pen -n green "${_mark:-} "
pen "$@"
}
repen() {
upclear
pen "$@"
}
trap "spop; show_cursor" EXIT INT TERM
_spinner_pid=""
_frame_duration="${_spinner_frame_duration:-0.1}"
spin() {
local message=("$@")
local spinner="${_spinner:-⣷⣯⣟⡿⢿⣻⣽⣾}"
if spinning; then
spop --keep-cursor-hidden
fi
(
hide_cursor
trap "exit 0" USR1
line
pen -n cyan "${spinner:0:1} "
pen "${message[@]}"
while true; do
for ((i = 0; i < ${#spinner}; i++)); do
frame="${spinner:$i:1}"
up
bol
pen -n cyan "${frame} "
pen "${message[@]}"
sleep "$_frame_duration"
done
done
) &
_spinner_pid=$!
}
spop() {
local keep_cursor_hidden=false
[[ "$1" == "--keep-cursor-hidden" ]] && keep_cursor_hidden=true
if spinning; then
kill -USR1 "${_spinner_pid}" 2>/dev/null
sleep "$_frame_duration"
if ps -p "${_spinner_pid}" >/dev/null 2>&1; then
kill "${_spinner_pid}" 2>/dev/null
fi
if [[ "$keep_cursor_hidden" == false ]]; then
show_cursor
fi
_spinner_pid=""
fi
}
spinning() {
[[ -n "${_spinner_pid}" ]]
}
throw() {
if spinning; then
spop
upclear
fi
pen -n red "${_cross:-} "
pen "$@"
}
warn() {
if spinning; then
spop
upclear
fi
pen -n yellow bold italic "${_warn:-!} "
pen italic "$@"
}
choose() {
local -n outvar="$1"
local prompt
local options=("${@:3}")
local current=0
local count=${#options[@]}
prompt=$(
pen -n blue "${_q:-?} "
pen -n "${2} "
pen gray "[↑↓]"
)
hide_cursor
trap 'show_cursor; return' INT TERM
pen "$prompt"
while true; do
local index=0
for item in "${options[@]}"; do
if ((index == current)); then
pen -n blue "${_O:-} "
pen "${item}"
else
pen gray "${_o:-} ${item}"
fi
((index++))
done
read -s -r -n1 key
if [[ $key == $'\e' ]]; then
read -s -r -n2 -t 0.0001 escape
key+="$escape"
fi
case "$key" in
$'\e[A' | 'k')
((current--))
[[ $current -lt 0 ]] && current=$((count - 1))
;;
$'\e[B' | 'j')
((current++))
[[ $current -ge "$count" ]] && current=0
;;
'q')
upclear
pen red bold "User exited the session with exit code 69!"
pen red "This is $(pen bold red 'NOT') an accident!"
exit 69
;;
'')
break
;;
esac
echo -en "\e[${count}A\e[J"
done
outvar="${options[$current]}"
}
confirm() {
local default="y"
local hint="[Y/n]"
local prompt
local response
while [[ $# -gt 0 ]]; do
case "$1" in
--default-no)
default="n"
hint="[y/N]"
shift
;;
--default-yes)
shift
;;
*) break ;;
esac
done
prompt=$(
pen -n blue "${_q:-?} "
pen -n "$1"
pen gray " $hint"
pen -n blue "${_a:-} "
)
show_cursor
while true; do
read -r -p "$prompt" response
response="${response:-$default}"
case "$response" in
[Yy] | [Yy][Ee][Ss])
upclear
pen -n blue "${_a:-} "
pen "yes"
return 0
;;
[Nn] | [Nn][Oo])
upclear
pen -n blue "${_a:-} "
pen "no"
return 1
;;
[qQ] | quit)
upclear
pen red bold "User exited the session with exit code 69!"
pen red "This is $(pen bold red 'NOT') an accident!"
exit 69
;;
*)
echo
warn "Please answer yes or no."
;;
esac
done
}
request() {
local -n outvar="$1"
local prompt
local answer
prompt=$(
pen -n blue "${_q:-?} "
pen "${2}"
pen -n blue "${_a:-} "
)
show_cursor
while true; do
read -r -p "$prompt" answer
case "$answer" in
"")
echo
warn "Please type your answer."
;;
*) break ;;
esac
done
outvar="$answer"
}
seek() {
local -n outvar="$1"
local prompt
local answer
prompt=$(
pen -n blue "${_q:-?} "
pen "${2}"
pen -n blue "${_a:-} "
)
show_cursor
read -r -p "$prompt" answer
outvar="$answer"
}
# NOTE:
# ──────────────────────────────────────< end beddu >────────────────────────────────────
if check_env; then
# ─< gets the some variables like $aur, $debian, $ubuntu, $distro... >────────────────────
get_packager
# ─< get more indepths variables like $trixie, $bookworm, $jammy, $fedora_40.. >──────────
dist_setup
# WHY:
# ╭─────────────────────────────────────────────────────────────────────────╮
# │ check if the script has run at least once, so that the sources dont │
# │ have to get updated again.. │
# ╰─────────────────────────────────────────────────────────────────────────╯
pikaCheckFile="$HOME/.cache/pika_script_detection"
if [ ! -f "$pikaCheckFile" ]; then
pen bold grey "First time importing.."
if update-package-list; then
silentexec touch "$pikaCheckFile"
fi
else
echo_pkg "Skipping repo refresh"
fi
fi