: # SPDX-License-Identifier: BSD-2-Clause # NAME: # hooks.sh - provide hooks for customization # # SYNOPSIS: # hooks_add_all HOOKS [--first] func [...] # hooks_add_once HOOKS [--first] func [...] # hooks_add_default_set {all,once} # hooks_add HOOKS func [...] # hooks_get [--lifo] HOOKS # hooks_run [--lifo] HOOKS ["args"] # hooks_run_all [--lifo] HOOKS ["args"] # hooks_has HOOKS func # # add_hooks HOOKS [--first] func [...] # run_hooks HOOKS [LIFO] ["args"] # run_hooks_all HOOKS [LIFO] ["args"] # # DESCRIPTION: # The functions add_hooks and run_hooks are retained for # backwards compatability. They are aliases for hooks_add and # hooks_run. # # hooks_add_all simply adds the "func"s to the list "HOOKS". # # If the first arg is '--first' "func"s are added to the start # of the list. # # hooks_add_once does the same but only if "func" is not in "HOOKS". # hooks_add uses one of the above based on "option", '--all' (default) # or '--once'. # # hooks_add_default_set sets the default behavior of hooks_add # # hooks_get simply returns the named list of functions. # # hooks_has indicates whether "func" in in "HOOKS". # # hooks_run runs each "func" in $HOOKS and stops if any of them # return a bad status. # # hooks_run_all does the same but does not stop on error. # # If run_hooks or run_hooks_all is given a flag of '--lifo' or # 2nd argument of LIFO the hooks are run in the reverse order of # calls to hooks_add. # Any "args" specified are passed to each hook function. # # RCSid: # $Id: hooks.sh,v 1.21 2024/09/06 16:53:45 sjg Exp $ # # @(#)Copyright (c) 2000-2024 Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. # Permission to copy, redistribute or otherwise # use this file is hereby granted provided that # the above copyright notice and this notice are # left intact. # avoid multiple inclusion _HOOKS_SH=: # We want to use local if we can # if isposix-shell.sh has been sourced isPOSIX_SHELL will be set # as will local case "$local" in local|:) ;; *) if (echo ${PATH%:*}) > /dev/null 2>&1; then local=local else local=: fi ;; esac ## # hooks_add_all list func ... # # add "func"s to "list" regardless # hooks_add_all() { eval $local __h __h=$1; shift case "$1" in --first) shift eval "$__h=\"$* \$$__h\"" ;; *) eval "$__h=\"\$$__h $*\"";; esac } ## # hooks_add_once list func ... # # add "func"s to "list" if not already there # hooks_add_once() { eval $local __h __hh __first __h=$1; shift case "$1" in --first) shift; __first=:;; *) __first=;; esac eval "__hh=\$$__h" while [ $# -gt 0 ] do : __hh="$__hh" 1="$1" case "$__first $__hh " in *" $1 "*) ;; # dupe :*) __hh="$1 $__hh";; *) __hh="$__hh $1";; esac shift done eval "$__h=\"$__hh\"" } ## # hooks_add_default_set [--]{all,once} # # change the default method of hooks_add # hooks_add_default_set() { case "$1" in once|--once) HOOKS_ADD_DEFAULT=once;; *) HOOKS_ADD_DEFAULT=all;; esac } ## # hooks_add [--{all,once}] list func ... # # add "func"s to "list" # # If '--once' use hooks_add_once, # default is hooks_add_all. # hooks_add() { case "$1" in --all) shift; hooks_add_all "$@";; --once) shift; hooks_add_once "$@";; *) hooks_add_${HOOKS_ADD_DEFAULT:-all} "$@";; esac } ## # hooks_get [--lifo] list [LIFO] # # return $list # hooks_get() { eval $local __h __h2 e __l case "$1" in --lifo) __l=LIFO; shift;; esac eval "__h=\$$1" case "$__l$2" in LIFO*) __h2="$__h" __h= for e in $__h2 do __h="$e $__h" done ;; esac echo "$__h" } ## # hooks_has list func # # is func in $list ? # hooks_has() { eval $local __h eval "__h=\$$1" case " $__h " in *" $1 "*) return 0;; esac return 1 } ## # hooks_run [--all] [--lifo] list [LIFO] [args] # # pass "args" to each function in "list" # Without '--all'; if any return non-zero return that immediately # hooks_run() { eval $local __a e __h __hl __h2 __l __a=return __l= while : do case "$1" in --all) __a=:; shift;; --lifo) __l=$1; shift;; *) break;; esac done __hl=$1; shift case "$1" in LIFO) __l=--lifo; shift;; esac __h=`hooks_get $__l $__hl` for e in $__h do $e "$@" || $__a $? done } ## # hooks_run_all [--lifo] list [LIFO] [args] # # pass "args" to each function in "list" # hooks_run_all() { hooks_run --all "$@" } ## # add_hooks,run_hooks[_all] aliases # add_hooks() { hooks_add "$@" } run_hooks() { hooks_run "$@" } run_hooks_all() { hooks_run --all "$@" } case /$0 in */hooks.sh) # simple unit-test list=HOOKS flags= while : do : 1=$1 case "$1" in HOOKS|*hooks) list=$1; shift;; --*) flags="$flags $1"; shift;; *) break;; esac done for f in "$@" do : f=$f case "$f" in LIFO) ;; false|true) ;; *) eval "$f() { echo This is $f; }";; esac done echo hooks_add $flags $list "$@" hooks_add $flags $list "$@" echo hooks_run $list hooks_run $list echo hooks_run --all --lifo $list hooks_run --all --lifo $list echo hooks_run $list LIFO hooks_run $list LIFO ;; esac