#!/bin/bash installed() { command -v "$1" >/dev/null 2>&1 } installed2() { dpkg --list | grep -qw "ii $1" } apt_install() { sudo apt install -y --autoremove "$*" } require() { sw=() for package in "$@"; do if ! installed "$package" && ! installed2 "$package"; then sw+=("$package") fi done if [ ${#sw[@]} -gt 0 ]; then info "This packages will be installed in your system:\n${sw[*]}" #TODO use local install script if possible apt_install "${sw[*]}" [ $? -gt 0 ] && die "installation cancelled" 201 fi } require2() { sw=() for package in "$@"; do if ! installed "$package" && ! installed2 "$package"; then sw+=("$package") fi done if [ ${#sw[@]} -gt 0 ]; then die "This packages must be installed in your system:\n${sw[*]}" 200 fi } title() { [ "$1" ] && title="$1" || title="$(grep -m 1 -oP "(?<=^##makedesc:\s).*$" ${BASH_SOURCE[1]})" info info "===============================================" info "$title" info "===============================================" info } unpak_targz() { require tar tar -xzf "$1" -C "$2" } symlink() { ln -sf "$1" "$2" } download() { require wget wget "$1" -O "$2" } clone() { require git git clone $* } clone_quick() { require git git clone $* --depth=1 --single-branch } abspath() { echo $(realpath -q "${1/#\~/$HOME}") } is_writable() { [ -w "$(abspath $1)" ] } is_dir() { [ -d "$(abspath $1)" ] } is_file() { [ -f "$(abspath $1)" ] } is_function() { declare -F "$1" > /dev/null } regex_match() { printf "%s" "$1" | grep -qP "$2" } in_array() { local find=$1 shift for e in "$@"; do [[ "$e" == "$find" ]] && return 0 done return 1 } implode() { local d=${1-} local f=${2-} if shift 2; then printf %s "$f" "${@/#/$d}" fi } IINFO="( i )" INOTE="( * )" IWARN="( # )" IERROR="( ! )" IFATAL="( @ )" ISUCCESS="( ! )" IASK="( ? )" IDEBUG="(DBG)" IVRB="( + )" BOLD="\e[1m" DIM="\e[2m" NOTBOLD="\e[22m" # sometimes \e[21m NOTDIM="\e[22m" NORMAL="\e[20m" RESET="\e[0m" FRESET="\e[39m" FBLACK="\e[30m" FWHITE="\e[97m" FRED="\e[31m" FGREEN="\e[32m" FYELLOW="\e[33m" FBLUE="\e[34m" FLRED="\e[91m" FLGREEN="\e[92m" FLYELLOW="\e[93m" FLBLUE="\e[94m" BRESET="\e[49m" BBLACK="\e[40m" BWHITE="\e[107m" BRED="\e[41m" BGREEN="\e[42m" BYELLOW="\e[43m" BBLUE="\e[44m" BLRED="\e[101m" BLGREEN="\e[102m" BLYELLOW="\e[103m" BLBLUE="\e[104m" dt() { echo "[$(date +'%H:%M:%S')] " } ask() { IFS= read -rp "$(print ${BOLD}${BBLUE}${FWHITE}${IASK}${BRESET}\ ${BOLD}$1 ): " $2 } print() { echo -e "$*${RESET}" } debug() { if [ "$2" ]; then print "${DIM}${BOLD}${RESET}${DIM}${FUNCNAME[1]:-?}():${BASH_LINENO:-?}\t$1 " else print "${DIM}${BOLD}${RESET}${DIM}$1 " fi } verbose() { print "${BOLD}${IVRB}${RESET}${FYELLOW} $1 " } info() { print "${BOLD}${FWHITE}${BLBLUE}${IINFO}${RESET}${FWHITE} $1 " } note() { print "${BOLD}${DIM}${FWHITE}${INOTE}${RESET} $1 " } success() { print "${BOLD}${BGREEN}${FWHITE}${ISUCCESS}${BRESET}$FGREEN $1 " } warn() { print "${BOLD}${BYELLOW}${FBLACK}${IWARN}${BRESET}${FYELLOW} Warning:${RESET} $1 " } error() { print "${BOLD}${BLRED}${FWHITE}${IERROR} Error: ${BRESET}${FLRED} $1 " >&2 } fatal() { print "${BOLD}${BRED}${FWHITE}${IFATAL} FATAL: $1 " >&2 print_stacktrace } die() { error "${1:-halted}" exit ${2:-100} } print_stacktrace() { STACK="" local i local stack_size=${#FUNCNAME[@]} debug "Callstack:" # for (( i=$stack_size-1; i>=1; i-- )); do for (( i=1; i<$stack_size; i++ )); do local func="${FUNCNAME[$i]}" [ x$func = x ] && func=MAIN local linen="${BASH_LINENO[$(( i - 1 ))]}" local src="${BASH_SOURCE[$i]}" [ x"$src" = x ] && src=non_file_source debug " at $func $src:$linen" done }