diff options
author | Singustromo <singustromo@disroot.org> | 2023-07-03 15:23:56 +0200 |
---|---|---|
committer | Singustromo <singustromo@disroot.org> | 2023-07-03 15:25:18 +0200 |
commit | 3eb73e6d65c344cd99df2d89173b57e22be270a4 (patch) | |
tree | 4382b69d07e7eb6517df321b039885df4c5c4b9b | |
parent | cc8e4967c027083a8cc8406ef3d0baa44864834e (diff) | |
download | bash-framework-3eb73e6d65c344cd99df2d89173b57e22be270a4.tar.gz bash-framework-3eb73e6d65c344cd99df2d89173b57e22be270a4.zip |
Changed library structure
-rw-r--r-- | lib/array/contains.sh | 11 | ||||
-rwxr-xr-x | lib/bootstrap.sh | 48 | ||||
-rw-r--r-- | lib/io/log.sh (renamed from lib/util/log.sh) | 4 | ||||
-rw-r--r-- | lib/io/message.sh | 36 | ||||
-rw-r--r-- | lib/io/print_spaces.sh | 5 | ||||
-rw-r--r-- | lib/string/count_spaces.sh | 5 | ||||
-rw-r--r-- | lib/string/is_number.sh | 5 | ||||
-rw-r--r-- | lib/string/slash_replacement.sh | 18 | ||||
-rw-r--r-- | lib/system/exit_codes.sh | 20 | ||||
-rw-r--r-- | lib/util/command.sh | 18 | ||||
-rw-r--r-- | lib/util/exit_codes.sh | 21 | ||||
-rw-r--r-- | lib/util/function.sh | 24 | ||||
-rw-r--r-- | lib/util/function/copy.sh | 6 | ||||
-rw-r--r-- | lib/util/function/exists.sh | 4 | ||||
-rw-r--r-- | lib/util/function/inject_code.sh | 12 | ||||
-rw-r--r-- | lib/util/function/list.sh | 8 | ||||
-rw-r--r-- | lib/util/function/rename.sh | 6 | ||||
-rw-r--r-- | lib/util/slice.sh | 15 | ||||
-rw-r--r-- | lib/util/uuid_generate.sh (renamed from lib/string/uuid_generate.sh) | 2 | ||||
-rw-r--r-- | lib/var/is_number.sh | 5 | ||||
-rw-r--r-- | lib/var/sanitize.sh (renamed from lib/string/sanitize.sh) | 2 | ||||
-rw-r--r-- | lib/var/slash_replacement.sh | 14 | ||||
-rwxr-xr-x | your-script.sh | 11 |
23 files changed, 182 insertions, 118 deletions
diff --git a/lib/array/contains.sh b/lib/array/contains.sh index ddfa89b..f311935 100644 --- a/lib/array/contains.sh +++ b/lib/array/contains.sh @@ -1,7 +1,8 @@ +# This is an alternative to the default defined in bootstrap.sh Array::contains() { - local element - for element in "${@:2}"; do - [[ "$element" = "$1" ]] && return - done - false; return + local element + for element in "${@:2}"; do + [ "$element" = "$1" ] && return + done + false; return } diff --git a/lib/bootstrap.sh b/lib/bootstrap.sh index 1dc9559..993bfd0 100755 --- a/lib/bootstrap.sh +++ b/lib/bootstrap.sh @@ -4,16 +4,7 @@ ### BOOTSTRAP FUNCTIONS ### ########################### -# Kills the script with previous exit code and optional error message -System::die() { - local return_value="$?" - - if [ $# -gt 0 ]; then - (( return_value )) && printf "FATAL ERROR: %b" "$@" - (( ! return_value )) && printf "%b" "$@" - fi - exit "$return_value" -} +Array::contains() { [[ " ${@:2} " =~ " $1 " ]]; } File::absolute_path() { local file="${1:?no filepath}" @@ -23,26 +14,36 @@ File::absolute_path() { return fi local file_basename="${file##*/}" - local file_path="$(realpath "$file")" + local file_path="$(realpath "$file" >/dev/null 2>&1)" local file_path="${file_path%/*}" [ -r "$file_path/$file_basename" ] || return printf "%s\n" "$file_path/$file_basename" } +# Kills the script with previous exit code and optional error message +System::die() { + local return_value="$?" + + if [ $# -gt 0 ]; then + (( return_value )) && printf "FATAL ERROR: %b\n" "$*" + (( ! return_value )) && printf "%b\n" "$*" + fi + exit "$return_value" +} + System::SourceFile() { local libPath="${1:?no file provided}"; shift - libPath="$(File::absolute_path "$libPath")" || return - + libPath="$(File::absolute_path "$libPath")" \ + || return + ## already imported? -> let's return # if declare -f "$libPath" &> /dev/null && - if [ "${_VOID_ALLOW_FILERELOAD}" == 'false' ] \ - && [ -n "${_VOID_IMPORTS[*]}" ] \ - && Array::contains "$libPath" "${_VOID_IMPORTS[@]}" - then - true; return - fi + [ -n "${_VOID_IMPORTS[*]}" ] \ + && Array::contains "$libPath" "${_VOID_IMPORTS[@]}" \ + && [ "${_VOID_ALLOW_FILERELOAD}" == 'false' ] \ + && return # Check syntax /usr/bin/env bash -n "$libPath" \ @@ -52,8 +53,8 @@ System::SourceFile() { System::SourcePath() { local file libPath="${1:?no path specified}" - shift + if [ -d "$libPath" ]; then for file in "$libPath"/*.sh; do System::SourceFile "$file" "$@" || return @@ -92,8 +93,7 @@ System::ImportOne() { System::Import() { local libPath for libPath in "$@"; do - System::ImportOne "$libPath" \ - || System::die "Unable to import '$libPath'\n" + System::ImportOne "$libPath" || return done } @@ -121,10 +121,10 @@ declare -g -r _VOID_ROOT="${_VOID_LIBPATH%/*}" declare -g -a _VOID_IMPORTS -: ${_VOID_ALLOW_FILERELOAD:=false} +: "${_VOID_ALLOW_FILERELOAD:=false}" import() { - eval "System::Import $@" + eval "System::Import $*" } System::Bootstrap && declare -g -r _VOID_BOOTSTRAPPED=true diff --git a/lib/util/log.sh b/lib/io/log.sh index f32d1a0..d384fae 100644 --- a/lib/util/log.sh +++ b/lib/io/log.sh @@ -1,9 +1,7 @@ -#! /usr/bin/env bash - # Prints debug messages to fd2 # expands escape sequences # depends: $DEBUG == 1|true -Util::log() { +IO::log() { { [[ "$DEBUG" == '1' || "$DEBUG" == "true" ]] && [ -n "$*" ]; } || { true; return; } local line_no="${BASH_LINENO[0]}" i=2 out="(${FUNCNAME[1]}:_LNO_) " # called function while [ -n "${FUNCNAME[$i]}" ]; do # caller functions diff --git a/lib/io/message.sh b/lib/io/message.sh new file mode 100644 index 0000000..03ff59e --- /dev/null +++ b/lib/io/message.sh @@ -0,0 +1,36 @@ +#! /usr/bin/env bash + +: "${MSG_PREFIX_ERR:-[!!!]}" +: "${MSG_PREFIX_WARN:-[!]}" +: "${MSG_PREFIX_INFO:-[*]}" + +# Prints normal user messages (cli) +# $1: Type: e,err, i, info (optional) +# $2: no_nl (optional) +# $2-$X: Text +IO:message() { + local fd_out='1' prefix output newline=true + [ -n "$*" ] || return + case $1 in + (e|err|error) + prefix="$MSG_PREFIX_ERR" + fd_out=2; shift ;; + (w|warn|warning) prefix="$MSG_PREFIX_WARN"; shift ;; + (i|info) prefix="$MSG_PREFIX_INFO"; shift ;; + esac + [ "$1" == 'no_nl' ] && { newline=false; shift; } + + local first_line=true + for msg in "$@"; do + [ "${#prefix}" -gt 0 ] && [ "$newline" == "true" ] \ + && [ "$first_line" == "false" ] && { + for (( i=0; i<${#prefix}; i++ )); do output+=" "; done + } + output+="$msg\n" + first_line=false + done + + [ "$no_newline" = true ] && output="${output//'\n'/}\n" + [ "$fd_out" = '2' ] && printf "%s%b" "$prefix" "$output" >&2 && return + printf "%s%b" "$prefix" "$output" +} diff --git a/lib/io/print_spaces.sh b/lib/io/print_spaces.sh new file mode 100644 index 0000000..3790e12 --- /dev/null +++ b/lib/io/print_spaces.sh @@ -0,0 +1,5 @@ +IO::print_spaces() { + local howMany="${1:?specifiy a count}" + [[ "$howMany" =~ ^[0-9]*$ && "$howMany" -gt 0 ]] || return + ( printf "%*s" "$howMany" ) +} diff --git a/lib/string/count_spaces.sh b/lib/string/count_spaces.sh deleted file mode 100644 index f9e4511..0000000 --- a/lib/string/count_spaces.sh +++ /dev/null @@ -1,5 +0,0 @@ -String::count_spaces() { - local howMany="${1:?nothing to count}" - [[ "$howMany" -gt 0 ]] || return - ( printf "%*s" "$howMany" ) -} diff --git a/lib/string/is_number.sh b/lib/string/is_number.sh deleted file mode 100644 index e11191d..0000000 --- a/lib/string/is_number.sh +++ /dev/null @@ -1,5 +0,0 @@ -String::is_number() { - local input="${1:?no input}" - local regex='^-?[0-9]+([.][0-9]+)?$' - [[ "$input" =~ $regex ]] || return -} diff --git a/lib/string/slash_replacement.sh b/lib/string/slash_replacement.sh deleted file mode 100644 index f6f4be8..0000000 --- a/lib/string/slash_replacement.sh +++ /dev/null @@ -1,18 +0,0 @@ -# Workaround for a Bash bug that causes string replacement to fail when a \ is in the string -# - -String::slashes_replace() { - local stringToMark="${1:?no input}" - - local slash="\\" - local slashReplacement='_%SLASH%_' - printf "%s" "${stringToMark/$slash$slash/$slashReplacement}" -} - -String::slashes_restore() { - local stringToMark="${1:?no input}" - - local slash="\\" - local slashReplacement='_%SLASH%_' - printf "%s" "${stringToMark/$slashReplacement/$slash}" -} diff --git a/lib/system/exit_codes.sh b/lib/system/exit_codes.sh new file mode 100644 index 0000000..659d723 --- /dev/null +++ b/lib/system/exit_codes.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# +# These exit codes are from /usr/include/sysexits.h + +SYSEXIT_OK=0 # successful termination +SYSEXIT_USAGE=64 # command line usage error +SYSEXIT_DATAERR=65 # data format error +SYSEXIT_NOINPUT=66 # cannot open input +SYSEXIT_NOUSER=67 # addressee unknown +SYSEXIT_NOHOST=68 # host name unknown +SYSEXIT_UNAVAILABLE=69 # service unavailable +SYSEXIT_SOFTWARE=70 # internal software error +SYSEXIT_OSERR=71 # system error (e.g., can't fork) +SYSEXIT_OSFILE=72 # critical OS file missing +SYSEXIT_CANTCREAT=73 # can't create (user) output file +SYSEXIT_IOERR=74 # input/output error +SYSEXIT_TEMPFAIL=75 # temp failure; user is invited to retry +SYSEXIT_PROTOCOL=76 # remote error in protocol +SYSEXIT_NOPERM=77 # permission denied +SYSEXIT_CONFIG=78 # configuration error diff --git a/lib/util/command.sh b/lib/util/command.sh index 1f5a3ae..e1ba46a 100644 --- a/lib/util/command.sh +++ b/lib/util/command.sh @@ -1,19 +1,17 @@ # no dependencies Command::get_type() { - local name="$1" - local typeMatch=$(type -t "$name" 2> /dev/null || true) - echo "$typeMatch" + local name="${1:?no name specified}" + local _type=$(type -t "$name" 2> /dev/null || true) + printf "%s" "$_type" } Command::exists(){ - local name="$1" - local typeMatch=$(Command::GetType "$name") - [[ "$typeMatch" == "alias" || "$typeMatch" == "function" || "$typeMatch" == "builtin" ]] + local _type=$(Command::get_type "$1") + [[ "$_type" == "alias" || "$_type" == "function" || "$_type" == "builtin" ]] } -Alias::exists(){ - local name="$1" - local typeMatch=$(Command::GetType "$name") - [[ "$typeMatch" == "alias" ]] +Command::is_alias(){ + local _type=$(Command::get_type "$1") + [[ "$_type" == "alias" ]] } diff --git a/lib/util/exit_codes.sh b/lib/util/exit_codes.sh deleted file mode 100644 index 2ee1895..0000000 --- a/lib/util/exit_codes.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# exit codes -# Those values are come from /usr/include/sysexits.h -# - -EX_OK=0 # successful termination -EX_USAGE=64 # command line usage error -EX_DATAERR=65 # data format error -EX_NOINPUT=66 # cannot open input -EX_NOUSER=67 # addressee unknown -EX_NOHOST=68 # host name unknown -EX_UNAVAILABLE=69 # service unavailable -EX_SOFTWARE=70 # internal software error -EX_OSERR=71 # system error (e.g., can't fork) -EX_OSFILE=72 # critical OS file missing -EX_CANTCREAT=73 # can't create (user) output file -EX_IOERR=74 # input/output error -EX_TEMPFAIL=75 # temp failure; user is invited to retry -EX_PROTOCOL=76 # remote error in protocol -EX_NOPERM=77 # permission denied -EX_CONFIG=78 # configuration error diff --git a/lib/util/function.sh b/lib/util/function.sh deleted file mode 100644 index 15313c5..0000000 --- a/lib/util/function.sh +++ /dev/null @@ -1,24 +0,0 @@ -# no dependencies - -Function::exists(){ - local name="${1:?no function name provided}" - declare -f "$name" &> /dev/null -} - -Function::list_fuzzy() { - local startsWith="${1:?no search string provided}" - compgen -A 'function' "$startsWith" || true -} - -Function::inject_code() { - local functionName="${1:?no function name provided}" - local injectBefore="${2:-}" - local injectAfter="${3:-}" - [[ -n "$InjectBefore" && -n "$InjectAfter" ]] || return - local body="$(declare -f "$functionName")" - [ -n "$body" ] || return - body="${body#*{}" # trim start - body="${body%\}}" # trim end - local enter=$'\n' - eval "${functionName}() { ${enter}${injectBefore}${body}${injectAfter}${enter} }" -} diff --git a/lib/util/function/copy.sh b/lib/util/function/copy.sh new file mode 100644 index 0000000..87b138f --- /dev/null +++ b/lib/util/function/copy.sh @@ -0,0 +1,6 @@ +import util/slice + +Function::copy() { + declare -F $1 > /dev/null || return + eval "$(printf "%s()\n" "$2"; declare -f $1 | Util::slice -1)" +} diff --git a/lib/util/function/exists.sh b/lib/util/function/exists.sh new file mode 100644 index 0000000..9c0c4d2 --- /dev/null +++ b/lib/util/function/exists.sh @@ -0,0 +1,4 @@ +Function::exists() { + local name="${1:?no function name provided}" + declare -f "$name" &> /dev/null +} diff --git a/lib/util/function/inject_code.sh b/lib/util/function/inject_code.sh new file mode 100644 index 0000000..31961b1 --- /dev/null +++ b/lib/util/function/inject_code.sh @@ -0,0 +1,12 @@ +Function::inject_code() { + local functionName="${1:?no function name provided}" + local injectBefore="${2:-}" + local injectAfter="${3:-}" + [[ -n "$InjectBefore" && -n "$InjectAfter" ]] || return + local body="$(declare -f "$functionName")" + [ -n "$body" ] || return + body="${body#*\{}" # trim start + body="${body%\}}" # trim end + local enter=$'\n' + eval "${functionName}() { ${enter}${injectBefore}${body}${injectAfter}${enter} }" +} diff --git a/lib/util/function/list.sh b/lib/util/function/list.sh new file mode 100644 index 0000000..08bc5b9 --- /dev/null +++ b/lib/util/function/list.sh @@ -0,0 +1,8 @@ +# Returns a list of declared functions separated by a new line +Function::list() { + local line + [ -n "$1" ] && { builtin compgen -A 'function' "$1"; return; } + while read -r line; do + printf "%b\n" "${line//declare -f /}" + done <<< "$(builtin declare -F)" +} diff --git a/lib/util/function/rename.sh b/lib/util/function/rename.sh new file mode 100644 index 0000000..08b8b6d --- /dev/null +++ b/lib/util/function/rename.sh @@ -0,0 +1,6 @@ +import util/function/copy + +Function::rename() { + Function::copy "$1" "$2" \ + && unset -f "$1" +} diff --git a/lib/util/slice.sh b/lib/util/slice.sh new file mode 100644 index 0000000..6d68114 --- /dev/null +++ b/lib/util/slice.sh @@ -0,0 +1,15 @@ +# similiar to /bin/head +# prints stdin until n'th occurence of c +# -n -> prints stdin from n'th occurence of c +# returns nothing, if delimiter does not exist in stdin +# $2: n +# $3: c (delimiter) +Util::slice() { + local n="${1:-0}" c="${2:-$'\n'}" arr=() + [[ "$n" =~ ^\-?[0-9]*$ ]] || return + + local appendix="-n $n" + [ "${n::1}" == '-' ] && appendix="-s ${n:1}" + eval "builtin readarray -d '$c' $appendix _arr" + printf "%b" "${_arr[@]}" +} diff --git a/lib/string/uuid_generate.sh b/lib/util/uuid_generate.sh index 0cba82e..a98fd5d 100644 --- a/lib/string/uuid_generate.sh +++ b/lib/util/uuid_generate.sh @@ -1,4 +1,4 @@ -String::uuid_generate() { +Util::uuid_generate() { ## https://gist.github.com/markusfisch/6110640 local N B C='89ab' diff --git a/lib/var/is_number.sh b/lib/var/is_number.sh new file mode 100644 index 0000000..39c4dae --- /dev/null +++ b/lib/var/is_number.sh @@ -0,0 +1,5 @@ +Var::is_number() { + local input="${1:?no input}" + local regex='^-?[0-9]+([.][0-9]+)?$' + [[ "$input" =~ $regex ]] || return +} diff --git a/lib/string/sanitize.sh b/lib/var/sanitize.sh index 667515d..6a1e0ac 100644 --- a/lib/string/sanitize.sh +++ b/lib/var/sanitize.sh @@ -1,4 +1,4 @@ -String::sanitize() { +Var::sanitize() { local type="${1:?no input}" printf "%s" "${type//[^a-zA-Z0-9]/_}" } diff --git a/lib/var/slash_replacement.sh b/lib/var/slash_replacement.sh new file mode 100644 index 0000000..2f36def --- /dev/null +++ b/lib/var/slash_replacement.sh @@ -0,0 +1,14 @@ +# Workaround for a Bash bug that causes +# string replacement to fail when a \ is in the string + +Var::slashes_replace() { + local stringToMark="${1:?no input}" slash="\\" + local slashReplacement='_%SLASH%_' + printf "%s" "${stringToMark/$slash$slash/$slashReplacement}" +} + +Var::slashes_restore() { + local stringToMark="${1:?no input}" slash="\\" + local slashReplacement='_%SLASH%_' + printf "%s" "${stringToMark/$slashReplacement/$slash}" +} diff --git a/your-script.sh b/your-script.sh index 2ba458d..dce2c09 100755 --- a/your-script.sh +++ b/your-script.sh @@ -6,11 +6,20 @@ readonly workdir="${workdir%/*}" . "$workdir"/lib/bootstrap.sh ## MAIN EXAMPLES ## -import util/log +import util/log util/msg util/function/list util/print_spaces + # Files not in lib/ can also be imported: # import my_file.sh +# +# import my_dir # import my_dir/my_file.sh +# +# import ../dir/... Util::log "imports:\n" "${_VOID_IMPORTS[@]}" +Function::list + +Util::print_spaces 15 + ## YOUR CODE GOES HERE ## |