Skip to content

Instantly share code, notes, and snippets.

@sstephenson
Last active January 30, 2017 01:40

Revisions

  1. sstephenson revised this gist Apr 9, 2013. 1 changed file with 7 additions and 7 deletions.
    14 changes: 7 additions & 7 deletions super.bash
    Original file line number Diff line number Diff line change
    @@ -41,20 +41,20 @@ chain_function() {
    if is_function "$prefix_name"; then
    chain_function "$prefix_name" "$prefix"
    fi

    rename_function "$name" "$prefix_name"
    }

    super_function() {
    local name="$1"
    local body="$(function_body "$name")"

    local wrapped_body='local __last_super_function="$__super_function"
    __super_function="__super_$FUNCNAME"
    local __super_result=0
    { '"$body"'; } || __super_result="$?"
    __super_function="$__last_super_function"
    return "$__super_result"'
    local wrapped_body='
    local __last_super_function="$__super_function"
    __super_function="__super_$FUNCNAME"
    local __super_result=0
    {'"$body"';} || __super_result="$?"
    __super_function="$__last_super_function"
    return "$__super_result"'

    if ! is_function "__super_$name"; then
    define_function "__super_$name" 'echo "super: superfunction not found" >&2; return 1'
  2. sstephenson created this gist Apr 9, 2013.
    16 changes: 16 additions & 0 deletions gistfile1.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,16 @@
    #!/usr/bin/env bash

    source super.bash

    foo() {
    echo hello
    }
    super_function foo

    foo() {
    super
    echo world
    }
    super_function foo

    foo # prints "hello\nworld"
    75 changes: 75 additions & 0 deletions super.bash
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,75 @@
    is_function() {
    [ "$(type -t "$1" || true)" = "function" ]
    }

    function_body() {
    local name="$1"
    if is_function "$name"; then
    local body="$(declare -f "$name")"
    body="${body#*{}"
    echo "${body%\}}"
    else
    echo "no such function \`$name'" >&2
    return 1
    fi
    }

    define_function() {
    local name="$1"
    local body="$2"
    eval "${name}() { ${body}; }"
    }

    alias_function() {
    local src="$1"
    local dst="$2"
    define_function "$dst" "$(function_body "$src")"
    }

    rename_function() {
    local src="$1"
    local dst="$2"
    alias_function "$src" "$dst"
    unset -f "$src"
    }

    chain_function() {
    local name="$1"
    local prefix="$2"
    local prefix_name="${prefix}${name}"

    if is_function "$prefix_name"; then
    chain_function "$prefix_name" "$prefix"
    fi

    rename_function "$name" "$prefix_name"
    }

    super_function() {
    local name="$1"
    local body="$(function_body "$name")"

    local wrapped_body='local __last_super_function="$__super_function"
    __super_function="__super_$FUNCNAME"
    local __super_result=0
    { '"$body"'; } || __super_result="$?"
    __super_function="$__last_super_function"
    return "$__super_result"'

    if ! is_function "__super_$name"; then
    define_function "__super_$name" 'echo "super: superfunction not found" >&2; return 1'
    fi

    chain_function "$name" __super_
    define_function "__super_$name" "$wrapped_body"
    define_function "$name" '"__super_$FUNCNAME" "$@"'
    }

    super() {
    if is_function "$__super_function"; then
    "$__super_function" "$@"
    else
    echo "super: must be called from inside a superfunction" >&2
    return 1
    fi
    }