11#! /usr/bin/env bash
22
3- # libbash 10 .0.0 - a collection of useful functions for your Bash scripts
3+ # libbash 11 .0.0 - a collection of useful functions for your Bash scripts
44#
55# Copyright (C) Georg Lauterbach
66# GitHub: https://github.com/georglauterbach/libbash
77#
8- # Underscored functions are not unset when libbash has been loaded
9- # successfully. They are required by other functions in libbash.
8+ # ---
9+ #
10+ # Upon successful loading of libbash, all functions of all loaded modules
11+ # become available and you MAY use them.
12+ #
13+ # Certain modules require other functions or variables (e.g., for logging
14+ # or error handling) that do not belong to a module directly. Such
15+ # functions are prefixed with `libbash__` and variables with `LIBBASH__`,
16+ # and you MAY use them, but you MUST NOT change them.
17+ #
18+ # Finally, there are functions and variables that do not belong to modules
19+ # and that are prefixed with `__libbash__` (and `__LIBBASH__` respectively).
20+ # You MUST NOT change or use these functions and variables.
1021
1122# cSpell: ignore Georg Lauterbach
1223
@@ -35,7 +46,7 @@ function libbash__main() {
3546 LIBBASH__DIRECTORY=$( realpath -eL " $( dirname " ${BASH_SOURCE[0]} " ) " )
3647 LIBBASH__EXIT_IN_INTERACTIVE_MODE=${LIBBASH__EXIT_IN_INTERACTIVE_MODE:- false}
3748 LIBBASH__LOADED_MODULES=()
38- LIBBASH__VERSION=10 .0.0
49+ LIBBASH__VERSION=11 .0.0
3950
4051 # ! export all variables here first, even if not
4152 # ! all modules are sourced to satisfy shellcheck
@@ -109,13 +120,14 @@ function libbash__finish() {
109120 unset LIBBASH__DIRECTORY
110121 unset LIBBASH__EXIT_IN_INTERACTIVE_MODE
111122 unset LIBBASH__LOADED_MODULES
123+ unset LIBBASH__LOG_IS_LOADED
112124 unset LIBBASH__VERSION
113125
114126 unset -f libbash__debug
115127 unset -f libbash__show_call_stack
116128
117129 unset -f __libbash__show_error
118- unset -f __libbash__exit_checked
130+ unset -f libbash__exit_checked
119131 fi
120132
121133 unset -f libbash__main
@@ -132,7 +144,7 @@ function libbash__finish() {
132144#
133145# Shows some debug information that `libbash` has collected.
134146function libbash__debug() {
135- if ! ${__LIBBASH__LOG_IS_LOADED :- false} ; then
147+ if ! ${LIBBASH__LOG_IS_LOADED :- false} ; then
136148 __libbash__show_error " Debug functionality requires the log module to be loaded and 'LOG_LEVEL' set to 'debug' or 'trace'"
137149 return 1
138150 fi
@@ -167,26 +179,16 @@ function libbash__show_call_stack() {
167179}
168180export -f libbash__show_call_stack
169181
170- # ### Show an Error
171- #
172- # Indicates an error has happened in `libbash`. Used to display
173- # errors even when the log module is not (or has not yet been)
174- # loaded.
175- function __libbash__show_error() {
176- printf " %s \e[91mERROR\e[0m %s: %s\n" \
177- " $( date +" %Y-%m-%dT%H:%M:%S.%6N%:z" || :) " " ${SCRIPT:- $(basename " ${0} " )} " " ${* } " >&2
178- }
179- export -f __libbash__show_error
180-
181182# ### Exit With Conditions
182183#
183- # This function will exit when not running interactively or when
184- # 'LIBBASH__EXIT_IN_INTERACTIVE_MODE' is set to 'true'.
184+ # This function will call `exit` when not running interactively
185+ # or when 'LIBBASH__EXIT_IN_INTERACTIVE_MODE' is set to 'true'.
186+ # Otherwise, it calls `return`.
185187#
186188# #### Arguments
187189#
188190# $1 :: the return code (optional, default=1)
189- function __libbash__exit_checked () {
191+ function libbash__exit_checked () {
190192 local CODE=${1:- 1}
191193 local METHOD=' return'
192194
@@ -197,11 +199,22 @@ function __libbash__exit_checked() {
197199 if [[ ${CODE} =~ ^[0-9]$ ]]; then
198200 " ${METHOD} " " ${CODE} "
199201 else
200- __libbash__show_error " Supplied non-number code ('${CODE} ') to __libbash__exit_checked "
202+ __libbash__show_error " Supplied non-number code ('${CODE} ') to libbash__exit_checked "
201203 " ${METHOD} " 1
202204 fi
203205}
204- export -f __libbash__exit_checked
206+ export -f libbash__exit_checked
207+
208+ # ### Show an Error
209+ #
210+ # Indicates an error has happened in `libbash`. Used to display
211+ # errors even when the log module is not (or has not yet been)
212+ # loaded.
213+ function __libbash__show_error() {
214+ printf " %s \e[91mERROR\e[0m %s: %s\n" \
215+ " $( date +" %Y-%m-%dT%H:%M:%S.%6N%:z" || :) " " ${SCRIPT:- $(basename " ${0} " )} " " ${* } " >&2
216+ }
217+ export -f __libbash__show_error
205218
206219# Load the 'cri' module
207220function libbash__load_module_cri() {
@@ -229,51 +242,55 @@ function libbash__load_module_log() {
229242 export LIBBASH__LOG_COLOR_WARN=' \e[93m'
230243 export LIBBASH__LOG_COLOR_ERROR=' \e[91m'
231244
232- export __LIBBASH__LOG_IS_LOADED=true
245+ export LIBBASH__LOG_IS_LOADED=true
246+
247+ # ### The Actual Logger
248+ #
249+ # This function is used by `log` to print the messages.
250+ function __libbash__log_generic() {
251+ local LEVEL=${1:? libbash bug: log level message format must be provided to __libbash__log_generic}
252+ local COLOR=" LIBBASH__LOG_COLOR_${LEVEL^^} "
253+ shift 1
254+
255+ # shellcheck disable=SC2059
256+ printf " %s ${! COLOR} %-5s${LIBBASH__LOG_COLOR_RESET} %s: %s\n" \
257+ " $( date +" %Y-%m-%dT%H:%M:%S.%6N%:z" || :) " " ${LEVEL^^} " " ${SCRIPT:- $(basename " ${0} " )} " " ${* } "
258+ }
259+ export -f __libbash__log_generic
233260
234261 # ### The Logging Functions
235262 #
236263 # `log` uses five different log levels and behaves as you would
237264 # expect from a log function: you provide the log level as the
238265 # first argument and the message in the consecutive ones. The
239266 # default log level is 'info'. The global log level is defined
240- # in the
267+ # in the `LOG_LEVEL` variables. The global variable `SCRIPT`
268+ # defines a prefix of the message that is being logged.
241269 #
242270 # #### Log Level
243271 #
244272 # The provided log level, as well as the environment variable
245- # `LOG_LEVEL`, Can be one of
273+ # `LOG_LEVEL`, can be one of
246274 #
247- # meaning - what to log
248- # -------------------------------------------------
249- # trace - log trace information
250- # debug - log debug information
251- # info - log informational output
252- # warn - log warnings
253- # error - log critical errors and aborts
275+ # - trace (log all messages)
276+ # - debug
277+ # - info
278+ # - warn
279+ # - error
280+ # - off (log no messages)
254281 #
255- # where a higher level includes the level below. The
256- # default log level is 'info' (2).
282+ # The default log level is 'info'.
257283 #
258284 # #### Return Codes
259285 #
260- # This function is infallible. Hence, it always returns with
261- # return code 0, even when issues appeared.
286+ # This function is infallible.
262287 #
263288 # #### Arguments
264289 #
265- # $1 :: log level
266- # $2 :: message (strictly speaking optional, no default / empty string)
290+ # $1 :: log level
291+ # ${@:1} :: message
267292 function log() {
268- function __log_generic() {
269- local LEVEL=${1:? libbash bug: log level message format must be provided to __log_generic}
270- local COLOR=" LIBBASH__LOG_COLOR_${LEVEL^^} "
271- shift 1
272-
273- # shellcheck disable=SC2059
274- printf " %s ${! COLOR} %-5s${LIBBASH__LOG_COLOR_RESET} %s: %s\n" \
275- " $( date +" %Y-%m-%dT%H:%M:%S.%6N%:z" || :) " " ${LEVEL^^} " " ${SCRIPT:- $(basename " ${0} " )} " " ${* } "
276- }
293+ [[ ${LOG_LEVEL:- } == off ]] && return 0
277294
278295 if [[ -z ${1+set} ]]; then
279296 log ' warn' " 'log' called without log level"
@@ -286,13 +303,13 @@ function libbash__load_module_log() {
286303 return 0
287304 fi
288305
289- local MESSAGE_LOG_LEVEL=" ${1} "
306+ local MESSAGE_LOG_LEVEL=${1}
290307 shift 1
291308
292- # ! scoping of dictionaries beyond `source` / in the global namespace is
293- # ! even more horrendous that normal scoping in Bash - hence, we avoid it
294- declare -A LOG_LEVEL_MAPPING=( [ " error " ]= " 0 " [ " warn " ]= " 1 " [ " info " ]= " 2 " [ " debug " ]= " 3 " [ " trace " ]= " 4 " )
295-
309+ # Scoping of dictionaries beyond `source` / in the global namespace is
310+ # even more horrendous that normal scoping in Bash - hence, we avoid it
311+ # and put the dictionary here.
312+ declare -A LOG_LEVEL_MAPPING=([off]=0 [error]=1 [warn]=2 [info]=3 [debug]=4 [trace]=5 )
296313 if [[ -z ${LOG_LEVEL_MAPPING[${LOG_LEVEL:=info}]:- } ]]; then
297314 local OLD_LOG_LEVEL=${LOG_LEVEL}
298315 export LOG_LEVEL=' debug'
@@ -302,12 +319,10 @@ function libbash__load_module_log() {
302319 [[ ${LOG_LEVEL_MAPPING[${LOG_LEVEL}]} -lt ${LOG_LEVEL_MAPPING[${MESSAGE_LOG_LEVEL}]} ]] && return 0
303320
304321 if [[ ${LOG_LEVEL_MAPPING[${MESSAGE_LOG_LEVEL}]} -lt 2 ]]; then
305- __log_generic " ${MESSAGE_LOG_LEVEL} " " ${* } " >&2
322+ __libbash__log_generic " ${MESSAGE_LOG_LEVEL} " " ${* } " >&2
306323 else
307- __log_generic " ${MESSAGE_LOG_LEVEL} " " ${* } "
324+ __libbash__log_generic " ${MESSAGE_LOG_LEVEL} " " ${* } "
308325 fi
309-
310- return 0
311326 }
312327}
313328
0 commit comments