HiveBrain v1.2.0
Get Started
← Back to all entries
patternbashMinor

Two similar shell functions that run different programs

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
shelldifferenttwothatprogramsfunctionssimilarrun

Problem

I have a script that contains two shell functions:

runhaskells() {
    local DIR=$PWD
    local TARGET="cabal.sandbox.config"
    while [[ ! -e $DIR/$TARGET -a $DIR != "/" ]]; do
        DIR=$(dirname $DIR)
    done
    if [[ $DIR != "/" ]]; then
        local DB=$(sed -ne '/^package-db: */{s///p;q;}' "$DIR/$TARGET")
        runhaskell -no-user-package-db -package-db="$DB" "$@"
    else
        runhaskell "$@"
    fi
} 

ghcs() {
    local DIR=$PWD
    local TARGET="cabal.sandbox.config"
    while [[ ! -e $DIR/$TARGET -a $DIR != "/" ]]; do
        DIR=$(dirname $DIR)
    done
    if [[ $DIR != "/" ]]; then
        local DB=$(sed -ne '/^package-db: */{s///p;q;}' "$DIR/$TARGET")
        ghc -no-user-package-db -package-db="$DB" "$@"
    else
        ghc "$@"
    fi
}


which obviously is a repeat of each other except for the fact that it calls a different program in each function. The first function calls the runhaskell program while the second function calls the ghc program.

How can I DRY this script (either zsh or bash syntax is fine for me) with the end goal that I should be able to call either function at the command line?

Solution

Two simple bash solutions I can think of are:

-
Use a shell script and $0/$BASH_SOURCE to determine the calling name and a symlink from one name to the other.

-
Two small wrapper functions.

h() {
    local DIR=$PWD
    local TARGET="cabal.sandbox.config"
    while [[ ! -e $DIR/$TARGET -a $DIR != "/" ]]; do
        DIR=$(dirname $DIR)
    done
    if [[ $DIR != "/" ]]; then
        local DB=$(sed -ne '/^package-db: */{s///p;q;}' "$DIR/$TARGET")
        set -- "${@:1:1}" -no-user-package-db -package-db="$DB" "${@:2}"
        # or this is the order of original arguments and added arguments don't matter
        set -- "$@" -no-user-package-db -package-db="$DB"
    fi

    "$@"
}

runhaskells() {
    h runhaskell "$@"
}

ghcs() {
    h ghc "$@"
}


Slightly DRYier version of the above which uses bash's FUNCNAME array.

h() {
        local DIR=$PWD
        local TARGET="cabal.sandbox.config"
        while [[ ! -e $DIR/$TARGET -a $DIR != "/" ]]; do
            DIR=$(dirname $DIR)
        done
        if [[ $DIR != "/" ]]; then
            local DB=$(sed -ne '/^package-db: */{s///p;q;}' "$DIR/$TARGET")
            set -- "${@:1:1}" -no-user-package-db -package-db="$DB" "${@:2}"
            # or this is the order of original arguments and added arguments don't matter
            set -- "$@" -no-user-package-db -package-db="$DB"
        fi

        "${FUNCNAME[1]%s}" "$@"
    }

    runhaskells() {
        h "$@"
    }

    ghcs() {
        h "$@"
    }

Code Snippets

h() {
    local DIR=$PWD
    local TARGET="cabal.sandbox.config"
    while [[ ! -e $DIR/$TARGET -a $DIR != "/" ]]; do
        DIR=$(dirname $DIR)
    done
    if [[ $DIR != "/" ]]; then
        local DB=$(sed -ne '/^package-db: */{s///p;q;}' "$DIR/$TARGET")
        set -- "${@:1:1}" -no-user-package-db -package-db="$DB" "${@:2}"
        # or this is the order of original arguments and added arguments don't matter
        set -- "$@" -no-user-package-db -package-db="$DB"
    fi

    "$@"
}

runhaskells() {
    h runhaskell "$@"
}

ghcs() {
    h ghc "$@"
}
h() {
        local DIR=$PWD
        local TARGET="cabal.sandbox.config"
        while [[ ! -e $DIR/$TARGET -a $DIR != "/" ]]; do
            DIR=$(dirname $DIR)
        done
        if [[ $DIR != "/" ]]; then
            local DB=$(sed -ne '/^package-db: */{s///p;q;}' "$DIR/$TARGET")
            set -- "${@:1:1}" -no-user-package-db -package-db="$DB" "${@:2}"
            # or this is the order of original arguments and added arguments don't matter
            set -- "$@" -no-user-package-db -package-db="$DB"
        fi

        "${FUNCNAME[1]%s}" "$@"
    }

    runhaskells() {
        h "$@"
    }

    ghcs() {
        h "$@"
    }

Context

StackExchange Code Review Q#75613, answer score: 3

Revisions (0)

No revisions yet.