sadedot/scripts/common.sh

361 lines
10 KiB
Bash
Executable File

#!/usr/bin/env bash
displayDialogBox() {
case $dialogBox in
whiptail) useWhiptail "$@" ;;
dialog) useDialog "$@" ;;
plain) usePlainText "$@" ;;
?) echo "Unknown dialogBox variable" >&2 && exit 1 ;;
esac
}
useDialog() {
if [[ "$1" == "--checklist" || "$1" == "--menu" ]]; then
useDialogListOrMenu "$@"
exit
fi
inputbox=false; passwordbox=false; infobox=false
str=$(getLastArgument "$@")
if [ "$str" = "VALUES" ]; then
argc="$#"; i=1
for item in "$@"; do
if [ $i -eq $((argc-1)) ]; then
str="$item"
fi
[ "$item" = "--inputbox" ] && inputbox=true
[ "$item" = "--passwordbox" ] && passwordbox=true
[ "$item" = "--infobox" ] && infobox=true
((i++))
done
fi
width=$(calcWidthDialog "$str")
height=$(calcHeightDialog "$str" "$width")
if [ $inputbox = true ] || [ $passwordbox = true ]; then
width=$((width+15))
height=$((height+2))
fi
[ $infobox = true ] && height=$((height-2))
formatOptions "$@"
if [ "$found" = false ]; then
dialog "$@" ${height} ${width}
else
dialog "${options[@]}"
fi
}
useWhiptail() {
if [[ "$1" == "--checklist" || "$1" == "--menu" ]]; then
useWhiptailListOrMenu "$@"
exit
fi
[ "$1" = "--infobox" ] && tty | grep -q "/dev/pts" && local TERM=ansi
inputbox=false; infobox=false
str=$(getLastArgument "$@")
if [ "$str" = "VALUES" ]; then
argc="$#"; i=1
for item in "$@"; do
if [ $i -eq $((argc-1)) ]; then
str="$item"
fi
[ "$item" = "--inputbox" ] && inputbox=true
[ "$item" = "--infobox" ] && infobox=true
((i++))
done
fi
width=$(calcWidthWhiptail "$str")
height=$(calcHeightWhiptail "$str")
[ $inputbox = true ] && [ "$width" -lt 30 ] && width=$((width+5))
[ $infobox = true ] && height=$((height-1))
formatOptions "$@"
if [ "$found" = false ]; then
height=0; width=0
whiptail "$@" ${height} ${width}
else
whiptail "${options[@]}"
fi
}
printLine() {
printf '\n\n%s' "----------------------------------------"
}
printHelp() {
tput bold
tput setaf 3
echo -ne "\n\n$1"
tput sgr0
printf '\n%s' "----------------------------------------"
}
usePlainText() {
if [ "$1" = "--menu" ]; then
usePlainTextMenu "$@"
exit
elif [ "$1" == "--checklist" ]; then
usePlainTextList "$@"
exit
fi
clear
inputbox=false; infobox=false; msgbox=false; passwordbox=false; yesno=false
for item in "$@"; do
case $item in
--title) shift && shift ;;
--inputbox) inputbox=true ;;
--infobox) infobox=true ;;
--msgbox) msgbox=true ;;
--passwordbox) passwordbox=true ;;
--yesno) yesno=true ;;
esac
done
tput bold
printf '%s\n' "${2:2}"
tput sgr0
if [ $inputbox = true ]; then
printLine && printf "\n"
read -r readVar < /dev/tty
printf '%s' "$readVar" 1>&2
elif [ $passwordbox = true ]; then
printLine && printf "\n"
read -r -s readVar < /dev/tty
printf '%s' "$readVar" 1>&2
elif [ $yesno = true ]; then
printLine
printf '\n%s' "[y/n] "
read -n 1 -r -s readVar < /dev/tty
while echo "$readVar" | grep -vqE '[yYnN]'; do
printf "\033[A"
printf '\n%s' "You need to type 'y' or 'n'"
printf '\n%s' "[y/n] "
read -n 1 -r -s readVar < /dev/tty
done
[[ "$readVar" =~ ^[Yy]$ ]] && return 0 || return 1
elif [ $msgbox = true ]; then
printLine
printf '\n%s' "Press a key to continue... "
read -n 1 -r -s < /dev/tty
fi
}
usePlainTextMenu() {
clear
tput bold
shift; printf '%s\n' "${1:2}"; shift; shift
tput sgr0
local i=1; for item in "$@"; do
echo "$item" | grep -qE '[0-9]+' && continue
printf '%s\n' "$i) $item"
((i++))
done
printLine
printf '\n%s' "[1..$((i-1))] "
read -n ${#i} -r -s readVar < /dev/tty
while echo "$readVar" | grep -vqE '[0-9]+' || [[ $readVar -le 0 || $readVar -ge $i ]]; do
printf "\033[A"
printf '\n%s' "You need to choose a number between 1 and $((i-1))"
printf '\n%s' "[1..$((i-1))] "
read -n ${#i} -r -s readVar < /dev/tty
done
printf "\n"
printf '%s' "$readVar" 1>&2
}
usePlainTextList() {
clear
tput bold
shift; msg="${1:2}"; printf '%s\n' "$msg"; shift; shift
tput sgr0
options=()
local i=2; j=0; for item in "$@"; do
if [ $((i%3)) -eq 0 ]; then
printf '%s\n' "$((++j))) $item"
else
[[ "$item" != "OFF" && "$item" != "ON" ]] && options+=("$item")
fi
((i++))
done
helpmsg="To select an element you must enter its number."
helpmsg="${helpmsg} Also, you can deselect an item by re-entering its number."
helpmsg="${helpmsg}\nTo finalize the selection press ENTER."
printHelp "$helpmsg"
printf '\n%s' "[1..$j] "
isNewline=false
selectedOptions=()
while [ $isNewline = false ]; do
read -n ${#j} -r -s readVar < /dev/tty
while echo "$readVar" | grep -vqE '[0-9]+' || [[ $readVar -le 0 || $readVar -gt $j ]]; do
[ "${#readVar}" -eq 0 ] && isNewline=true && break
printf "\033[A"
printf '\n%s' "You need to choose a number between 1 and $j)"
printf '\n%s' "[1..$j] "
read -n ${#j} -r -s readVar < /dev/tty
done
[ $isNewline = true ] && break
clear
tput bold
printf '%s\n' "$msg"
tput sgr0
local i=2; j=0; for item in "$@"; do
if [ $((i%3)) -eq 0 ]; then
printf '%s\n' "${selectedOptions[@]}" | grep -Fxq "${options[$j]}"
retVal=$?
if [ $((++j)) -eq "$readVar" ] && [ $retVal -eq 0 ]; then
IFS=' ' read -r -a selectedOptions <<< "${selectedOptions[@]//${options[$((readVar-1))]}/}"
printf '%s\n' "$j) $item"
elif [ "$j" -eq "$readVar" ] || [ $retVal -eq 0 ]; then
tput setab 2
printf '%s\n' "$j) $item"
[ $retVal -ne 0 ] && selectedOptions+=("${options[$((readVar-1))]}")
tput sgr0
else
printf '%s\n' "$j) $item"
fi
fi
((i++))
done
printHelp "$helpmsg"
printf '\n%s' "[1..$j] "
done
printf "\n"
if [ ${#selectedOptions[@]} -gt 0 ]; then
echo "${selectedOptions[@]}"
fi
}
getLastArgument() {
local i=0
for i; do :; done
echo "$i"
}
formatOptions() {
options=(); found=false; isListOrMenu=false
[[ "$1" == "--checklist" || "$1" == "--menu" ]] && isListOrMenu=true
for item in "$@"; do
if [ "$item" = "VALUES" ]; then
options+=("${height}")
options+=("${width}")
[ $isListOrMenu = true ] && options+=("${listHeight}")
found=true
continue
fi
options+=("${item}")
done
}
getListOrMenuOptions() {
maxLen=0; i=1; j=1; notFound=true; msgLen=-1; argsQty=0; isList=false; height=0
[ "$1" = "--checklist" ] && isList=true
for item in "$@"; do
[ "${item:0:2}" = "--" ] && continue
[ $i -eq $j ] && [ $msgLen = -1 ] && msgLen=${#item}
if [ $notFound = true ]; then
[[ "${item}" == "VALUES" ]] && ((i+=3))
[[ "${item}" == +([0-9]) ]] && ((i++))
[ "$i" -le 3 ] && continue
fi
notFound=false
if [ $((j % 3)) -eq 0 ]; then
strLen=${#item}
[ "$strLen" -gt $maxLen ] && maxLen=$strLen
((argsQty++))
[ $isList = false ] && ((j++))
fi
((j++))
done
if [ "$msgLen" -gt 52 ]; then
height=$(echo "$msgLen" | awk '{
x = $1 / 57
printf "%d", (x == int(x)) ? x : int(x) + 1
}')
msgLen=52
fi
maxLen=$((maxLen+15)) && [ "$maxLen" -ge "$msgLen" ] || maxLen=$((msgLen+3))
[ "$dialogBox" = "whiptail" ] && heightOffset=9 || heightOffset=8
argsQty=$((argsQty+heightOffset)) && [ "$argsQty" -le 20 ] || argsQty=20
listHeight=$((argsQty-heightOffset)) && [ "$argsQty" -ge 10 ] || listHeight=$((argsQty-heightOffset))
height=$((argsQty+height)); width=$maxLen
formatOptions "$@"
}
useDialogListOrMenu() {
getListOrMenuOptions "$@"
dialog --no-tags "${options[@]}"
}
useWhiptailListOrMenu() {
getListOrMenuOptions "$@"
whiptail --notags --separate-output "${options[@]}"
}
calcWidthWhiptail() {
width=${#1}
[ "$width" -gt 60 ] && echo 60 || echo $((width+2))
}
calcWidthDialog() {
count=1; found=false; option=1
while IFS= read -r -N 1 c; do
if [[ "$c" == $'\n' ]]; then
[ $count -ge $option ] && option=$count
found=true
count=-1
fi
((count++))
done < <(echo -ne "$1")
[ $option -ge "$count" ] && count=option
[ $((count)) -gt 60 ] && echo 60 || echo $((count+4))
}
calcHeightWhiptail() {
newlines=$(echo -ne "$1" | grep -c $'\n')
height=$(echo "${#1}" "$newlines" | awk '{
x = (($1 - $2 + ($2 * 60)) / 60)
printf "%d", (x == int(x)) ? x : int(x) + 1
}')
echo $((6+height))
}
calcHeightDialog() {
newlines=$(echo -ne "$1" | grep -c $'\n')
strlen=$((${#1}-1))
width=$(($2-4))
height=$(echo "$strlen" "$((newlines-1))" "$width" | awk '{
z = ($1 - $2) / $3
y = (z == int(z)) ? int(z) : int(z) + 1
n = ($2 / 1.3)
x = y + ((n - int(n) < 0.5) ? int(n) : int(n) + 1)
printf "%d", x
}')
echo $((5+height))
}
checkCancel() {
[ $? -eq 0 ] && return 1
displayDialogBox --msgbox "\n$1" VALUES
return 0
}
setDialogBox() {
export dialogBox=${1}
}
getDialogBox() {
echo "$dialogBox"
}
setLogToFile() {
export logToFile=${1}
export logFolder=${2}
}
debug() {
if [[ -n $logToFile && $logToFile = true ]]; then
tee -a "$logFolder/sadedot.log" > /dev/null
else
tee > /dev/null
fi
}