* Changed name for _log function to _msg, added bail() function.

* Created _ansi function library to set terminal properties like
  cursor position and text color.
* Created _if function library, a set of simple if statements.
  Added _if_array_contains, _if_is_integer, _if_is defined,
  if_has_value
This commit is contained in:
ayakael 2018-01-06 20:30:09 -09:00
parent 5f446594ee
commit fca165b274
No known key found for this signature in database
GPG key ID: 575626A4AE5F4026
9 changed files with 476 additions and 141 deletions

View file

@ -1,9 +1,19 @@
# bash-libs
# bunc
&copy; 2017 Antoine Martin \<antoine.martin@protonmail.com\>, provided under GNU General Public License v3.0.
A collection of bash libraries that I tend to use in my scripts
A set of bash functions
## log
A systemd-esque cli bash feedback function
## _msg
Messaging framework for scripts.
## _if functions
Set of if functions to make life easier
* _if_array_contains True if variable exists in array as element
* _if_is_integer True is variable is integer. Can be multiple
* _if_is_defined True if variable is defined (Not working)
* _if_has_value True if variable has non-zero value (Not working)
## _ansi
Sets terminal properties such as cursor position and text color using ANSI
escape sequences.

188
lib/ansi.sh Normal file
View file

@ -0,0 +1,188 @@
#!/bin/bash
# doc ansi {
#
# NAME
# ansi
#
# DESCRIPTION
# Sets terminal properties such as cursor position and text color.
#
# USAGE
# _ansi <command> [<arg>]
#
# COMMAND
# lt <unit>
# Moves cursor left
#
# dn <unit>
# Moves cursor down
#
# up <unit>
# Moves cursor up
#
# rt <unit>
# Moves cursor right
#
# mc <column>;<line>
# Moves cursor to <column> and <line>
#
# sc
# Saves cursor position
#
# rc
# Restores cursor position
#
# cl
# Clears the line
#
# cs
# Clears the screen
#
# fg <color>
# Sets foreground to defined color
#
# bf <color>
# Sets foreground to bold and defined color
#
# bg <color>
# Sets background to defined color
#
# rs
# Resets text to terminal default
#
# COLORS
# blk
# Color black
#
# red
# Color red
#
# grn
# Color green
#
# yel
# Color yellow
#
# blu
# Color blue
#
# mag
# Color magenta
#
# cyn
# Color cyan
#
# gry
# Color grey
#
# }
_cmd_to_ansi() {
local CMD="${1}"; shift
local cmdoptArray=("${@}")
local ansiArray=(A B C D H s u K 2J m)
for no in {0..12}; do
if [ "${CMD}" == "${cmdoptArray[${no}]}" ]; then
[[ ${no} -ge 9 ]] && local no=9
echo ${ansiArray[${no}]}
fi
done
}
_color_to_ansi() {
local COL=${1}; shift
local coloptArray=(${@})
for no in {0..7}; do
if [ "${COL}" == "${coloptArray[${no}]}" ]; then
echo $(( ${no} + 30 ))
fi
done
}
_arg_to_ansi() {
local CMD=${1}; shift
local ARG=${1}; shift
local coloptArray=(${@})
if [ "${CMD}" == "bf" ]; then
echo "1;$(_color_to_ansi ${ARG} ${coloptArray[@]})"
elif [ "${CMD}" == "fg" ]; then
echo "$(_color_to_ansi ${ARG} ${coloptArray[@]})"
elif [ "${CMD}" == "bg" ]; then
echo "$(( $(_color_to_ansi ${ARG} ${coloptArray[@]}) + 10 ))"
elif [ "${CMD}" == "rs" ]; then
echo "0"
else
echo "${ARG}"
fi
}
_ansi() {
local CMD=${1}
local ARG=${2}
# Possible input arrays
# All commands
local cmdoptArray=(up dn rt lt mc sc rc cl cs fg bf bg rs)
# No argument commands
local cmdopt_noargArray=(sc rc cl cs rs)
# One argument commands
local cmdopt_intArray=(lt dn up rtc)
# Coord only array
local cmdopt_coordArray=(mc)
# Color only commands
local cmdopt_colorArray=(fg bf bg)
# All colors
local coloptArray=(blk red grn yel blu mag cyn gry)
# cmd content sanity
if [ -z ${CMD+x} ]; then
_msg ECHO "_ansi(): Command not defined"
elif ! _if_array_contains ${CMD} ${cmdoptArray[@]}; then
_msg ECHO "_ansi(): ${CMD} not a command"
fi
# arg quantity sanity
# no arg commands
if _if_array_contains ${CMD} ${cmdopt_noargArray[@]}; then
if [ -z ${ARG+x} ]; then
_msg ECHO "_ansi(): ${CMD} expected no arguments"
return 1
fi
# 1 arg commands
elif _if_array_contains ${CMD} ${cmdopt_1argArray[@]}; then
if [ -z ${ARG+x} ]; then
_msg ECHO "_ansi(): ${CMD} expected 1 argument"
return 1
fi
# arg content sanity
# integer commands
elif _if_array_contains ${CMD} ${cmdopt_intArray[@]}; then
if ! _if_is_integer ${ARG}; then
_msg ECHO "_ansi(): ${CMD} expected integer as argument"
return 1
fi
# coord commands
elif _if_array_contains ${CMD} ${cmdopt_coordArray[@]}; then
if ! _if_integer $(echo ${ARG} | sed 's|;| |'); then
_msg ECHO "_ansi(): ${CMD} expected integers as argument"
fi
# color commands
elif _if_array_contains ${CMD} ${cmdopt_colorArray[@]}; then
if ! _if_array_contains ${ARG} ${coloptArray[@]}; then
_msg ECHO "_ansi(): ${CMD} expected argument to match ${coloptArray[@]}"
return 1
fi
fi
echo -e "\033[$(_arg_to_ansi ${CMD} ${ARG} ${coloptArray[@]})$(_cmd_to_ansi ${CMD} ${cmdoptArray[@]})"
}

View file

@ -1,104 +0,0 @@
#!/bin/bash
# doc color {
#
# NAME
# color
#
# DESCRIPTION
# Sets color variables for easy color change
#
# USAGE
# _color <command> [<arg>]
#
# COMMAND
# fg <color>
# Sets foreground to defined color
#
# bfg <color>
# Set foreground to bold and defined color
#
# bg <color>
# Sets background to defined color
#
# rs
# Resets text to terminal default
#
# COLORS
# blk
# Color black
#
# red
# Color red
#
# grn
# Color green
#
# yel
# Color yellow
#
# blu
# Color blue
#
# mag
# Color magenta
#
# cyn
# Color cyan
#
# gry
# Color grey
#
# }
cmdoptArray=(fg bfg bg rs)
coloptArray=(blk red grn yel blu mag cyn gry)
_color_to_ansi() {
local COL=${1}
for no in {0..7}; do
if [ "${COL}" == "${coloptArray[${no}]}" ]; then
echo $(( ${no} + 30 ))
fi
done
}
_color() {
local CMD=${1}
local COL=${2}
# Sanity check for COMMAND argument
if [ -z ${1+x} ]; then
_msg ECHO "_color(): Command not defined"
elif ! _if_array_contains "${CMD}" "${cmdoptArray[@]}"; then
_msg ECHO "_color(): ${CMD} not a command"
fi
# Sanity check for COLOR argument
[ ! "${CMD}" == "rs" ] && {
if [ -z ${2+x} ]; then
_msg ECHO "_color(): Color not defined"
elif ! _if_array_contains "${COL}" "${coloptArray[@]}"; then
_msg ECHO "_color(): ${COL} not a color"
fi
}
# Converts color to associated ANSI value
ANSI="$(_color_to_ansi ${COL})"
case ${CMD} in
bfg)
local BOLD="1;"
;;
bg)
local ANSI=$(( ${ANSI} + 10 ))
;;
rs)
local ANSI=0
;;
esac
echo -e "\033[${BOLD}${ANSI}m"
}

57
lib/if.sh Normal file
View file

@ -0,0 +1,57 @@
#!/bin/bash
# doc if {
#
# NAME
# if
#
# DESCRIPTION
# A collection of special if functions
#
# USAGE
# <function> <arg>
#
# FUNCTIONS
# _array_contains <var>" "<Array[@]>"
# Checks if variable exists in array
#
# _is_integer <var>
# Checks if variable is integer
# EXIT VALUES
# 0 Check succesful
# 1 Check failed
#
# }
_if_array_contains() {
local i=${1}; shift
local eArray=(${@})
for e in ${eArray[@]}; do
[[ "${e}" = "${i}" ]] && return 0
done
return 1
}
_if_is_integer () {
local iArray=(${@})
for i in ${iArray[@]}; do [[ ${i} =~ ^-?[0-9]+$ ]] && return 0; done
return 1
}
_if_is_defined () {
[[ ! ${!1} && ${!1-_} ]] && {
echo "$1 is not set, aborting." >&2
exit 1
}
}
_if_has_value () {
if is_defined $1; then
if [[ -n ${!1} ]]; then
return 0
fi
fi
return 1
}

View file

@ -1,6 +1,50 @@
#!/bin/bash
# doc msg {
#
# NAME
# msg
#
# DESCRIPTION
# Messaging framework for scripts
#
# USAGE
# _msg <command> <arg>
#
# COMMAND
# INDENT +/-<unit>
# Indents string.
#
# EXEC <message>
# Prints EXEC line with message
#
# OK <lines>
# Updates the status of an EXEC message to OK. Set <lines> when the EXEC
# status is higher than directly above the current line.
#
# WARN <message> <lines>
# Updates the status of an EXEC message to WARN, a non-fatal error. If the
# output to the warning command redirects to ${STDERR}. it will be
# outputted. Set <lines> when the EXEC line is higher than directly
# above the current line.
#
# FAIL <message> <lines>
# Updates the status to an EXEC message to FAIL, a fatal error. If the
# output to the failed command redirects to ${STDERR}, it will be
# outputted. The bail() function will then be executed, which defaults to
# returning with an exit code 1, than exits. Set <lines> when the EXEC line
# is higher than directly above the current line.
#
# ECHO <message>
# Prints a normal message
# }
STDERR=$(mktemp /tmp/STDERR.XXXXXXXXXX)
INDENT=0
bail() {
return 1
exit
}
_msg(){
if [ ${1} = "INDENT" ]; then
@ -12,14 +56,14 @@ _msg(){
fi
elif [ ${1} = "EXEC" ]; then
shift
echo -en "$(tput cuf "${INDENT}") [ ] ${1}\n"
echo -en "$(_ansi rt "${INDENT}") [ ] ${1}\n"
elif [ ${1} = "OK" ]; then
if [ -z "${2}" ]; then
HEIGHT=1
else
HEIGHT=$(( ${2} + 1))
fi
echo -en "$(tput cuu "${HEIGHT}")$(tput cuf "${INDENT}") [$(tput bold)$(tput setaf 2) OK $(tput sgr0)]$(tput cub 100)$(tput cud "${HEIGHT}")"
echo -en "$(_ansi up "${HEIGHT}")$(_ansi rt "${INDENT}") [$(_ansi bf grn) OK $(_ansi rs)]$(_ansi lt 100)$(_ansi dn "${HEIGHT}")"
elif [ ${1} = "WARN" ]; then
shift;
if [ -z "${2}" ]; then
@ -27,14 +71,14 @@ _msg(){
else
HEIGHT=$(( ${2} + 1))
fi
echo -en "$(tput cuu "${HEIGHT}")$(tput cuf "${INDENT}") [$(tput bold)$(tput setaf 3) WARN $(tput sgr0)]"
echo -en "\n$(tput cuf "${INDENT}") [>>>>>>] ${1} \n"
echo -en "$(_ansi up "${HEIGHT}")$(_ansi rt "${INDENT}") [$(_ansi bf yel) WARN $(_ansi rs)]"
echo -en "\n$(_ansi rt "${INDENT}") [>>>>>>] ${1} \n"
if [ -n "${STDERR}" ]; then
cat ${STDERR}
fi
rm ${STDERR}
STDERR=$(mktemp /tmp/STDERR.XXXXXXXXXX)
echo -en "$(tput cub 100)$(tput cud "${HEIGHT}")"
echo -en "$(_ansi lt 100)$(_ansi dn "${HEIGHT}")"
elif [ ${1} = "FAIL" ]; then
shift;
if [ -z "${2}" ]; then
@ -42,27 +86,18 @@ _msg(){
else
HEIGHT=$(( ${2} + 1))
fi
echo -en "$(tput cuu "${HEIGHT}")$(tput cuf "${INDENT}") [$(tput bold)$(tput setaf 1) FAIL $(tput sgr0)]"
echo -en "\n$(tput cuf "${INDENT}") [>>>>>>] ${1} \n"
echo -en "$(_ansi up "${HEIGHT}")$(_ansi rt "${INDENT}") [$(_ansi bf red) FAIL $(_ansi rs)]"
echo -en "\n$(_ansi rt "${INDENT}") [>>>>>>] ${1} \n"
if [ -n "${STDERR}" ]; then
cat ${STDERR}
fi
rm ${STDERR}
STDERR=$(mktemp /tmp/STDERR.XXXXXXXXXX)
echo -en "$(tput cuf "${INDENT}") [ ] Fatal error reported. Press any key to shutdown."
read -n 1 -s
echo -en "$(tput cub 100)$(tput cuf "${INDENT}") ["
TIME=3
while [ ${TIME} -ne 0 ]; do
sleep 1;
echo -en "||"
TIME=$(( ${TIME}-1 ))
done
echo -en "\n$(tput cub 100)$(tput cud "${HEIGHT}")"
exit
echo -en "$(_ansi lt 100)$(_ansi dn "${HEIGHT}")"
bail
elif [ ${1} = "ECHO" ]; then
shift
echo -e "$(tput cuf "${INDENT}") [======] ${1}"
echo -e "$(_ansi rt "${INDENT}") [======] ${1}"
fi
}

109
test/test-ansi.sh Normal file
View file

@ -0,0 +1,109 @@
#!/bin/bash
clean() {
exit
}
source ../lib/msg.sh
source ../lib/ansi.sh
source ../lib/if.sh
# Possible input arrays
# All commands
cmdArray=(lt dn up rt mc sc rc cl cs fg bf bg rs)
# No argument commands
cmdopt_noargArray=(sc rc cl cs rs)
# One argument commands
cmdopt_intArray=(lt dn up rtc)
# Coord only array
cmdopt_coordArray=(mc)
# Color only commands
cmdopt_colorArray=(fg bf bg)
# All colors
coloptArray=(blk red grn yel blu mag cyn gry)
_test_cmd_to_ansi() {
_msg EXEC "Testing _cmd_to_ansi function"
cmdArray=(lt dn up rt mc sc rc cl cs fg bf bg rs)
resultArray=(A B C D H s u K 2J m m m m)
for no in {0..12}; do
if ! [ "$(_cmd_to_ansi ${cmdArray[${no}]} ${cmdArray[@]})" == "${resultArray[${no}]}" ]; then
_cmd_to_ansi ${cmdArray[${no}]} ${cmdArray[@]} > ${STDERR}
_msg FAIL
fi
done
_msg OK
}
_test_color_to_ansi() {
_msg EXEC "Testing _color_to_ansi function"
cmdArray=(blk red grn yel blu mag cyn gry)
resultArray=(30 31 32 33 34 35 36 37)
for no in {0..7}; do
if ! [ "$(_color_to_ansi ${cmdArray[${no}]} ${cmdArray[@]})" == "${resultArray[${no}]}" ]; then
_color_to_ansi ${cmdArray[${no}]} ${cmdArray[@]} > ${STDERR}
_msg FAIL
fi
done
_msg OK
}
_test_arg_to_ansi() {
_msg EXEC "Testing _arg_to_ansi"
cmdArray=(fg bf bg up mc rs)
argArray=(red red red 2 '4:2' ' ')
coloptArray=(blk red grn yel blu mag cyn gry)
resultArray=(31 '1;31' 41 2 '4:2' '0')
for no in {0..5}; do
if ! [ "$(_arg_to_ansi ${cmdArray[${no}]} ${argArray[${no}]} ${coloptArray[@]})" == "${resultArray[${no}]}" ]; then
_arg_to_ansi ${cmdArray[${no}]} ${argArray[${no}]} ${coloptArray[@]} > ${STDERR}
_msg FAIL
fi
done
_msg OK
}
_test_ansi_color() {
cmdArray=(fg bf bg)
coloptArray=(blk red grn yel blu mag cyn gry)
resultArray=('\033[30m' '\033[31m' '\033[32m' '\033[1;33m' '\033[1;34m' '\033[1;35m')
for cmd in ${cmdArray[@]}; do
for col in ${coloptArray[@]}; do
echo "Testing _color $(_ansi ${cmd} ${col})${cmd} ${col}"
done
done
}
_msg ECHO "Begin ansi.sh test"
_test_cmd_to_ansi
_test_color_to_ansi
_test_arg_to_ansi
_test_ansi_color
#_msg ECHO "Testing relative cursor commands"
#_msg INDENT +1
#for cmd in lt dn up rt; do
# _msg ECHO "Testing ${cmd}"
# _msg EXEC "Testing sanity check for ${CMD} set at 0 units"
# if $(_ansi ${cmd} 0 >${STDERR} 2>&1); then
# _msg OK
# else
# _msg FAIL
# fi
# _msg EXEC "Testing sanity check for ${CMD} set at no args"
# if ! $(_ansi ${cmd} >${STDERR} 2>&1) ;then
# _msg OK
# else
# _msg FAIL
# fi
#
# _msg EXEC "Testing cursor change for ${CMD} set at 5 units"
# _ansi ${cmd} 5
#done
#for cmd in fg bfg bg; do
# for col in blk red grn yel blu mag cyn gry; do
# echo "Testing _color $(_ansi ${cmd} ${col})${cmd} ${col}$(_ansi rs)"
# done
#done
_msg ECHO "End color.sh test"

View file

@ -1,14 +0,0 @@
#!/bin/bash
source ../lib/msg.sh
source ../lib/color.sh
source ../lib/if.sh
_msg ECHO "Begin color.sh test"
for cmd in fg bfg bg; do
for col in blk red grn yel blu mag cyn gry; do
echo "Testing _color $(_color ${cmd} ${col})${cmd} ${col}$(_color rs)"
done
done
_msg ECHO "End color.sh test"

26
test/test-if.sh Normal file
View file

@ -0,0 +1,26 @@
#!/bin/bash
source "../lib/if.sh"
echo "_if_array_contains test started"
for result in 2 2 0 1; do
echo "Exit code should be ${result}"
eArray=(aa ab 0 dsa 2)
i=${result}
_if_array_contains "${i}" "${eArray[@]}"
echo $?
done
echo "_if_array_contains test ended"
echo "_if_is_integer test started"
for result in 0 1; do
echo "Exit code should be ${result}"
if [ ${result} == 0 ]; then
i=0
else
i=a
fi
_if_is_integer ${i}
echo $?
done
echo "_if_is_integer test ended"

28
test/test-msg.sh Normal file
View file

@ -0,0 +1,28 @@
#!/bin/bash
source ../lib/if.sh
source ../lib/ansi.sh
source ../lib/msg.sh
clean() {
return 0
}
echo "Starting test for log library"
_msg ECHO "Testing echo"
sleep 1
_msg EXEC "Testing EXEC w/ OK"
sleep 1
_msg OK
sleep 1
_msg EXEC "Testing EXEC w/ WARN"
sleep 1
_msg WARN "This is a WARN"
sleep 1
_msg EXEC "Testing EXEC w/ FAIL"
sleep 1
_msg FAIL "This is a FAIL"
sleep 1
_msg INDENT +1
_msg EXEC "This is EXEC w/ indent of 1"
sleep 1
_msg OK