Skip to content

Instantly share code, notes, and snippets.

@AtnNn
Last active December 23, 2015 11:49
Show Gist options
  • Save AtnNn/6631167 to your computer and use it in GitHub Desktop.
Save AtnNn/6631167 to your computer and use it in GitHub Desktop.
Mostly posix shell scripting tricks: assoc list, logging, classes, methods, inheritance, ...
set -e
set -u
main () {
init
# ...
}
# contains <haystack> <needle>
# Test if the space-separated list haystack contains needle
contains () {
local d=" $1 "
[ "${d% $2 *}" != "$d" ]
}
# any "<list>" <command>
# Test if the command is true for any element of the space seperated list
any () {
local list=$1
shift
for x in $list; do
if "$@" $x; then
return 0
fi
done
return 1
}
# lookup <dict> <key> [var]
# dict is an assoc-list composed of two seperators followed by a list of pairs
# eg: ':|foo:bar|test:123|baz:quux' or '= a=b c=d'
lookup () {
local _val=${1#*${1:1:1}$2${1:0:1}}
if [[ "$_val" = "$1" ]]; then
unset ${3:-$2}
return 1
fi
eval "${3:-$2}=$(quote "${_val%%${1:1:1}*}")"
}
uc () { echo "$*" | tr '[:lower:]' '[:upper:]' ; }
lc () { echo "$*" | tr '[:upper:]' '[:lower:]' ; }
subst () { echo "${1%%$2*}$3${1#*$2}" ; }
# Make the path absolute and prettier (with no /..)
niceabspath () {
if [[ -d "$1" ]]; then
(cd "$1" && pwd) && return
fi
local dir=$(dirname "$1")
if [[ -d "$dir" ]] && dir=$(cd "$dir" && pwd); then
echo "$dir/$(basename "$1")" | sed 's|^//|/|'
return
fi
if [[ "${1:0:1}" = / ]]; then
echo "$1"
else
echo "$(pwd)/$1"
fi
}
init () {
debug=false
log_file=
this=
stack=
}
log () {
echo "$*" >&3
test -n "$log_file" && echo "$*" >> "$log_file"
}
virtual () {
method "$@" || {
error "the $1 method is missing in $this"
}
}
can () { $2 can "$1" ; }
cannot () { not $2 can "$1" ; }
not () { ! "$@" ; }
each () {
$class each "$1"
local list="$1"
shift
method "" "$@" || {
echo "$list"
return
}
{
for object in $list; do
$object "$@"
done
return
}
}
method () {
local name="$1"
case "${2:-}" in
list_methods) echo "$name" ;;
$name) push_stack "$name"; return 1 ;;
*) return ;;
esac
}
push_stack () {
stack="$stack $1"
stack_trace=$stack
}
nomethod () {
error "No such method ${1:-''} for $this"
}
error () {
last_error="$*"
last_error_stack=$stack
return 1
}
class='eval local this; local stack="$stack"; debug_args="$*"; _class'
_class () {
$debug && echo "TRACE: $1 $debug_args"
if [ "${this##inherit *}" = "" ] && [ -n "$this" ]; then
set -- $this
this=$2
else
this=$*
push_stack "| $this"
fi
}
inherit () {
this="inherit $this"
"$@"
}
either () {
local list="$1"
shift
method "" "$@" || {
echo "$list"
return
}
{
for object in $list; do
$object "$@" && return || true
done
return 1
}
}
tmpfile () {
local _file=`mktemp`
cat >"$_file"
at_exit rm "$_file"
eval "$1=$(printf %q "$_file")"
}
at_exit () {
local cmd=
for x in "$@"; do
cmd="$cmd $(printf %q "$x")"
done
AT_EXIT_ALL=${AT_EXIT_ALL:-}'
'"$cmd"
trap exit_handler EXIT
}
exit_handler () {
eval "$AT_EXIT_ALL"
}
main "$@" 3>&1 || {
log "ERROR: ${last_error:-unknown error}"
log "ERROR: in ${last_error_stack:-}"
log "Aborting"
exit 1
} 3>&1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment