views:

239

answers:

2

I have a Bourne Shell script that has several functions in it, and allows to be called in the following way:

my.sh <func_name> <param1> <param2>

Inside func_name() will be called with param1 and param2.

I want to create a "help" function that would just list all available functions, even without parameters.

The question: how do I get a list of all function names in a script from inside the script?

I'd like to avoid having to parse it and look for function patterns. Too easy to get wrong.

Thanks, Alex

update: the code. Wanted my help() function be like main() - a function added to the code is added to the help automatically.

#!/bin/sh

# must work with "set -e"

foo ()
{
    echo foo: -$1-$2-$3-
    return 0
}

# only runs if there are parameters
# exits
main ()
{
    local cmd="$1"
    shift
    local rc=0
    $cmd "$@" || rc=$?
    exit $rc
}

if [[ "$*" ]]
then
    main "$@"
    die "how did we get here?"
fi
+1  A: 

The best thing to do is make an array (you are using bash) that contains functions that you want to advertise and have your help function iterate over and print them.

Calling set alone will produce the functions, but in their entirety. You'd still have to parse that looking for things ending in () to get the proverbial symbols.

Its also probably saner to use something like getopt to turn --function-name into function_name with arguments. But, well, sane is relative and you have not posted code :)

Your other option is to create a loadable for bash (a fork of set) that accomplishes this. Honestly, I'd prefer going with parsing before writing a loadable for this task.

Tim Post
@Tim +1 for your suggestion.@n-alexanderI think there is no way to get meta-data on functions. You could parse, but you don't want to do that.
ring bearer
you mean using the same array for calling the functions and for printing them? This is what I'd do in C. In shell I was hoping to be able to just add a function and not have to change any more code. But thanks
n-alexander
@n-alexander - Barring writing your own bash internal to export only 'symbols' , you're going to have to make two changes per function. I know it seems like you _should_ be able to `just get` the functions since bash knows about them, but there is no included interface to do so. You've actually got me thinking of making a loadable to do this.
Tim Post
+1  A: 

You can get a list of functions in your script by using the grep command on your own script. In order for this approach to work, you will need to structure your functions a certain way so grep can find them. Here is a sample:

$ cat my.sh
#!/bin/sh

function func1() # Short description
{
    echo func1 parameters: $1 $2
}

function func2() # Short description
{
    echo func2 parameters: $1 $2
}

function help() # Show a list of functions
{
    grep "^function" $0
}

if [ "_$1" = "_" ]; then
    help
else
    "$@"
fi

Here is an interactive demo:

$ my.sh 
function func1() # Short description
function func2() # Short description
function help() # Show a list of functions


$ my.sh help
function func1() # Short description
function func2() # Short description
function help() # Show a list of functions


$ my.sh func1 a b
func1 parameters: a b

$ my.sh func2 x y
func2 parameters: x y

If you have "private" function that you don't want to show up in the help, then omit the "function" part:

my_private_function()
{
    # Do something
}
Hai Vu
the way of doxygen :) This is good since it allows for a description to be printed, not just function name. But no enforcement, a forgotten comment is a forgotten function. Thanks
n-alexander
actually, this looks nice and simple. Use of "function" to differentiate between public and private is nice, and it's robust enough for my purposes
n-alexander
if you're interested, your solution with eval messes up spaces in parameters, i.e. my.sh func1 "1 1" 2 3 will call func1 with $1=1 $2=1 $3=2 $4=3 instead of $1="1 1", etc. Avoiding eval helps
n-alexander
n-alexander: Thanks for the tip regarding dropping the eval--it was unnecessary and incorrect. Regarding your first comment: if you forgot a function's comment, it is still showing up in the help.
Hai Vu