From 6a59720ef56f11409103f38717cd75ecb61f3dbc Mon Sep 17 00:00:00 2001 From: pvincent Date: Mon, 13 Apr 2026 11:02:20 +0400 Subject: [PATCH] functions.bash --- README.md | 2 +- install.sh | 42 +++++++-------- lib/functions.bash | 113 +++++++++++++++++++++++++++++++++++++++++ lib/functions.sh | 50 ------------------ tools/idem_apt_install | 72 +++++++++++++------------- tools/wget_semver | 2 +- 6 files changed, 172 insertions(+), 109 deletions(-) create mode 100644 lib/functions.bash delete mode 100644 lib/functions.sh diff --git a/README.md b/README.md index 26a7d4a..f2324d3 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Any feedback would be appreciated. [contact@artcode.re](mailto:contact@artcode.r ## useful library -* source /opt/miaou-bash/lib/functions.sh +* source /opt/miaou-bash/lib/functions.bash ## bindkeys diff --git a/install.sh b/install.sh index def256c..e9c0786 100755 --- a/install.sh +++ b/install.sh @@ -9,15 +9,15 @@ readonly MAIN_TAR_GZ_URL="https://git.artcode.re/miaou/miaou-bash/archive/main.t ## FUNCTIONS function push_directory { - pushd "$1" || (echo "unable to push directory <$1>" && exit 1) + pushd "$1" || (echo "unable to push directory <$1>" && exit 1) } function pop_directory { - popd || (echo "unable to pop from previous directory" && exit 1) + popd || (echo "unable to pop from previous directory" && exit 1) } function root_required { - [ "$(id -u)" -ne 0 ] && echo 'root privilege required' && exit 1 + [ "$(id -u)" -ne 0 ] && echo 'root privilege required' && exit 1 } ## MAIN @@ -25,28 +25,28 @@ function root_required { root_required if [[ $CURDIR != '/opt/miaou-bash' ]]; then - # download and fullfill /opt/miaou-bash, then run it from folder + # download and fullfill /opt/miaou-bash, then run it from folder - if [[ -L /opt/miaou-bash ]]; then - /opt/miaou-bash/install.sh - else - rm -rf /opt/miaou-bash + if [[ -L /opt/miaou-bash ]]; then + /opt/miaou-bash/install.sh + else + rm -rf /opt/miaou-bash - push_directory "$(mktemp -d)" - curl --no-progress-meter -O $MAIN_TAR_GZ_URL - tar -xzf main.tar.gz - mv miaou-bash /opt/ - pop_directory - rm -rf "$TEMP" + push_directory "$(mktemp -d)" + curl --no-progress-meter -O $MAIN_TAR_GZ_URL + tar -xzf main.tar.gz + mv miaou-bash /opt/ + pop_directory + rm -rf "$TEMP" - push_directory /opt/miaou-bash && ./install.sh + push_directory /opt/miaou-bash && ./install.sh - fi + fi else - MIAOU_BASH_DIR=$CURDIR - export MIAOU_BASH_DIR - source "$MIAOU_BASH_DIR/lib/functions.sh" - "$MIAOU_BASH_DIR/tools/idem_apt_install" "${REQUIRED_PKGS[@]}" - ./init.sh + MIAOU_BASH_DIR=$CURDIR + export MIAOU_BASH_DIR + source "$MIAOU_BASH_DIR/lib/functions.bash" + "$MIAOU_BASH_DIR/tools/idem_apt_install" "${REQUIRED_PKGS[@]}" + ./init.sh fi diff --git a/lib/functions.bash b/lib/functions.bash new file mode 100644 index 0000000..4421929 --- /dev/null +++ b/lib/functions.bash @@ -0,0 +1,113 @@ +## library of useful functions, usually prefixed with '_' + +## =============== +## ARRAY Functions +## =============== + +function _array_contains { + local -n array=$1 + local element=$2 + [[ " ${array[@]} " =~ " ${element} " ]] && return 0 || return 1 +} + +function _array_intersect { + local -n arr1=$1 + local -n arr2=$2 + local -n result=$3 + + declare -A include + for item in "${arr2[@]}"; do include["$item"]=1; done + + result=() + for item in "${arr1[@]}"; do [[ -n ${include["$item"]} ]] && result+=("$item"); done +} + +function _array_subtract { + local -n arr1=$1 # First array + local -n arr2=$2 # Array to subtract + local -n result=$3 # Output array + + [[ ${#arr2[@]} == 0 ]] && result=("${arr1[@]}") && return + + declare -A exclude + for item in "${arr2[@]}"; do exclude["$item"]=1; done + + result=() + for item in "${arr1[@]}"; do [[ -z ${exclude["$item"]} ]] && result+=("$item"); done +} + +## ============== +## TEXT Functions +## ============== + +function _pluralize_simple { + echo -n "$1 " + [[ $1 -eq 1 || $1 -eq -1 ]] && echo ${2} || echo ${2}s +} + +## ============== +## READ Functions +## ============== + +function _confirm_destructive { + local message="${1:-This cannot be undone!}" + echo "⚠️ WARNING: $message" + read -p "Type YES to confirm: " response + case "$response" in + [yY][eE][sS] | [yY]) return 0 ;; + *) echo "canceled!" && return 1 ;; + esac +} + +## ============== +## Deprecated: FIXME: to remove +## ============== + +## +# return 0 (true) if array (passed by name) contains element +# usage: +# ARRAY=( a b c ) +# containsElement ARRAY 'a' => 0 +function containsElement { + isArray "$1" || (echo >&2 "ERROR: <$1> not an array!" && return 2) + array_inter="$1[@]" + array=("${!array_inter}") + for i in "${array[@]}"; do [[ "$i" == "$2" ]] && return 0; done + return 1 +} + +## return 0 (true) if arg1 (passed by name) is an array +function isArray { + [[ "$(declare -p "$1" 2>/dev/null)" =~ "declare -a" ]] || return 1 +} + +function isDebian { + grep ^ID=debian /etc/os-release +} + +function isArch { + grep ^ID=arch /etc/os-release +} + +function os-release { + grep ^ID= /etc/os-release | cut -d '=' -f2 +} + +function askConfirmation { + case "$1" in + y | Y | yes | YES) + QUESTION="(Y/n)?" + DEFAULT=0 + ;; + *) + QUESTION="(y/N)?" + DEFAULT=1 + ;; + esac + read -rp "$QUESTION : " choice + case "$choice" in + y | Y | yes | YES) return 0 ;; #true + n | no | N | NO) return 1 ;; #false + *) return $DEFAULT ;; + esac +} diff --git a/lib/functions.sh b/lib/functions.sh deleted file mode 100644 index 40f64c7..0000000 --- a/lib/functions.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -## -# return 0 (true) if array (passed by name) contains element -# usage: -# ARRAY=( a b c ) -# containsElement ARRAY 'a' => 0 -function containsElement { - isArray "$1" || (echo >&2 "ERROR: <$1> not an array!" && return 2) - array_inter="$1[@]" - array=("${!array_inter}") - for i in "${array[@]}"; do [[ "$i" == "$2" ]] && return 0; done - return 1 -} - -## return 0 (true) if arg1 (passed by name) is an array -function isArray { - [[ "$(declare -p "$1" 2>/dev/null)" =~ "declare -a" ]] || return 1 -} - -function isDebian { - grep ^ID=debian /etc/os-release -} - -function isArch { - grep ^ID=arch /etc/os-release -} - -function os-release { - grep ^ID= /etc/os-release | cut -d '=' -f2 -} - -function askConfirmation { - case "$1" in - y | Y | yes | YES) - QUESTION="(Y/n)?" - DEFAULT=0 - ;; - *) - QUESTION="(y/N)?" - DEFAULT=1 - ;; - esac - read -rp "$QUESTION : " choice - case "$choice" in - y | Y | yes | YES) return 0 ;; #true - n | no | N | NO) return 1 ;; #false - *) return $DEFAULT ;; - esac -} diff --git a/tools/idem_apt_install b/tools/idem_apt_install index 3432b56..651a6d5 100755 --- a/tools/idem_apt_install +++ b/tools/idem_apt_install @@ -1,53 +1,53 @@ #!/bin/bash function usage { - local BASECMD - BASECMD=$(basename "$0") - echo "usage: $BASECMD " - case $(os-release) in - debian) - echo 'idempotent debian package installation : update if necessary, install only if not yet done' - ;; - arch) - echo 'idempotent archlinux package installation : update if necessary, install only if not yet done' - ;; - esac + local BASECMD + BASECMD=$(basename "$0") + echo "usage: $BASECMD " + case $(os-release) in + debian) + echo 'idempotent debian package installation : update if necessary, install only if not yet done' + ;; + arch) + echo 'idempotent archlinux package installation : update if necessary, install only if not yet done' + ;; + esac - exit 1 + exit 1 } BASEDIR=$(dirname "$0") -source "$BASEDIR"/../lib/functions.sh +source "$BASEDIR"/../lib/functions.bash [ "$(id -u)" -ne 0 ] && echo 'root privilege required' && exit 2 [[ $# -lt 1 ]] && usage case $(os-release) in debian | ubuntu | linuxmint) - if [ "$(date --date='-12 hours' +%s)" -gt "$(date -d "$(stat -c %y /var/lib/apt/lists/partial)" +%s)" ]; then - echo "updating repositoring..." - apt-get update - fi + if [ "$(date --date='-12 hours' +%s)" -gt "$(date -d "$(stat -c %y /var/lib/apt/lists/partial)" +%s)" ]; then + echo "updating repositoring..." + apt-get update + fi - for i in "$@"; do - if ! dpkg -l "$i" 2>/dev/null | grep -q ^ii; then - sudo apt-get install -y "$i" - elif [ -n "${VERBOSE+x}" ] && $VERBOSE; then - echo "apt package <$i> already installed!" - fi - done - ;; + for i in "$@"; do + if ! dpkg -l "$i" 2>/dev/null | grep -q ^ii; then + sudo apt-get install -y "$i" + elif [ -n "${VERBOSE+x}" ] && $VERBOSE; then + echo "apt package <$i> already installed!" + fi + done + ;; arch) - sudo pacman -Syyu --noconfirm - for i in "$@"; do - if ! pacman -Ql "$i" &>/dev/null; then - sudo pacman -S --noconfirm "$i" - elif [ -n "${VERBOSE+x}" ] && $VERBOSE; then - echo "pacman package <$i> already installed!" - fi - done - ;; + sudo pacman -Syyu --noconfirm + for i in "$@"; do + if ! pacman -Ql "$i" &>/dev/null; then + sudo pacman -S --noconfirm "$i" + elif [ -n "${VERBOSE+x}" ] && $VERBOSE; then + echo "pacman package <$i> already installed!" + fi + done + ;; *) - echo "unknown os release <$(os-release)>!" && exit 2 - ;; + echo "unknown os release <$(os-release)>!" && exit 2 + ;; esac diff --git a/tools/wget_semver b/tools/wget_semver index f6516a2..8d9289e 100755 --- a/tools/wget_semver +++ b/tools/wget_semver @@ -42,7 +42,7 @@ function get_artcode { if [ -z "$(command -v git)" ]; then echo "INSTALLING PACKAGE required" - source "$MIAOU_BASH_DIR/lib/functions.sh" + source "$MIAOU_BASH_DIR/lib/functions.bash" "$CURDIR/tools/idem_apt_install" git fi