Skip to content

Instantly share code, notes, and snippets.

@cbugk
Forked from phemmer/defer.sh
Created March 5, 2024 09:55
Show Gist options
  • Select an option

  • Save cbugk/4424ac68477c5dd509ac6c5bd39a7fa0 to your computer and use it in GitHub Desktop.

Select an option

Save cbugk/4424ac68477c5dd509ac6c5bd39a7fa0 to your computer and use it in GitHub Desktop.

Revisions

  1. @phemmer phemmer revised this gist Aug 12, 2019. 3 changed files with 23 additions and 25 deletions.
    38 changes: 13 additions & 25 deletions defer.sh
    Original file line number Diff line number Diff line change
    @@ -1,29 +1,17 @@
    if [[ -z "$BASHPID" ]]; then
    echo "your bash is too old" >&2
    exit 1
    fi

    deferred=()
    deferred_pid=
    run_deferred() {
    if [[ "$deferred_pid" != $BASHPID ]]; then
    # we are a subshell, don't execute statements created in parent
    return
    fi
    function _run_deferred() {
    local _depth="$BASHPID.${#FUNCNAME[@]}"
    [[ "$_depth" != "$_deferred_depth" ]] && return
    local opt=$-
    set +e
    for (( i=${#deferred[@]} - 1; i >= 0; i-- )); do
    eval "${deferred[i]}"
    for (( i=${#_deferred[@]} - 1; i >= 0; i-- )); do
    eval "${_deferred[i]}"
    done
    [[ "$opt" == *e* ]] && set -e
    }
    defer1() {
    if [[ "$deferred_pid" != $BASHPID ]]; then
    # $deferred was inherited from a parent (we are a subshell). re-initialize it
    deferred=()
    deferred_pid=$BASHPID
    trap run_deferred EXIT
    fi
    deferred+=( "$1" )
    function _defer() {
    _deferred_depth="$BASHPID.${#FUNCNAME[@]}"
    _deferred+=( "$(printf '%q ' "$@")" )
    }
    defer() {
    defer1 "$(printf '%q ' "$@")"
    }
    # This has to be an alias so that the `trap ... RETURN` runs appropriately.
    shopt -s expand_aliases
    alias defer='declare -a _deferred; declare _deferred_depth; trap _run_deferred EXIT RETURN; _defer'
    5 changes: 5 additions & 0 deletions example.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    function foo1() { echo foo1; }
    function foo2() { defer echo foo2; foo1; }
    function foo3() { foo2; }
    function foo4() { echo foo4-begin; ( defer echo foo4-subshell; foo3; ); echo foo4-end; }
    foo4
    5 changes: 5 additions & 0 deletions output
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    foo4-begin
    foo1
    foo2
    foo4-subshell
    foo4-end
  2. @phemmer phemmer created this gist Jan 23, 2019.
    29 changes: 29 additions & 0 deletions defer.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    if [[ -z "$BASHPID" ]]; then
    echo "your bash is too old" >&2
    exit 1
    fi

    deferred=()
    deferred_pid=
    run_deferred() {
    if [[ "$deferred_pid" != $BASHPID ]]; then
    # we are a subshell, don't execute statements created in parent
    return
    fi
    set +e
    for (( i=${#deferred[@]} - 1; i >= 0; i-- )); do
    eval "${deferred[i]}"
    done
    }
    defer1() {
    if [[ "$deferred_pid" != $BASHPID ]]; then
    # $deferred was inherited from a parent (we are a subshell). re-initialize it
    deferred=()
    deferred_pid=$BASHPID
    trap run_deferred EXIT
    fi
    deferred+=( "$1" )
    }
    defer() {
    defer1 "$(printf '%q ' "$@")"
    }