summary refs log tree commit diff
diff options
context:
space:
mode:
authorSingustromo <singustromo@disroot.org>2023-07-03 15:23:56 +0200
committerSingustromo <singustromo@disroot.org>2023-07-03 15:25:18 +0200
commit3eb73e6d65c344cd99df2d89173b57e22be270a4 (patch)
tree4382b69d07e7eb6517df321b039885df4c5c4b9b
parentcc8e4967c027083a8cc8406ef3d0baa44864834e (diff)
downloadbash-framework-3eb73e6d65c344cd99df2d89173b57e22be270a4.tar.gz
bash-framework-3eb73e6d65c344cd99df2d89173b57e22be270a4.zip
Changed library structure
-rw-r--r--lib/array/contains.sh11
-rwxr-xr-xlib/bootstrap.sh48
-rw-r--r--lib/io/log.sh (renamed from lib/util/log.sh)4
-rw-r--r--lib/io/message.sh36
-rw-r--r--lib/io/print_spaces.sh5
-rw-r--r--lib/string/count_spaces.sh5
-rw-r--r--lib/string/is_number.sh5
-rw-r--r--lib/string/slash_replacement.sh18
-rw-r--r--lib/system/exit_codes.sh20
-rw-r--r--lib/util/command.sh18
-rw-r--r--lib/util/exit_codes.sh21
-rw-r--r--lib/util/function.sh24
-rw-r--r--lib/util/function/copy.sh6
-rw-r--r--lib/util/function/exists.sh4
-rw-r--r--lib/util/function/inject_code.sh12
-rw-r--r--lib/util/function/list.sh8
-rw-r--r--lib/util/function/rename.sh6
-rw-r--r--lib/util/slice.sh15
-rw-r--r--lib/util/uuid_generate.sh (renamed from lib/string/uuid_generate.sh)2
-rw-r--r--lib/var/is_number.sh5
-rw-r--r--lib/var/sanitize.sh (renamed from lib/string/sanitize.sh)2
-rw-r--r--lib/var/slash_replacement.sh14
-rwxr-xr-xyour-script.sh11
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 ##