Displaying usage comments in functions intended to be used interactively

I have a number of functions defined in my .bashrc, intented to be used interactively in a terminal. I generally preceded them with a comment describing its intended usage:

# Usage: foo [bar]
# Foo's a bar into a baz
foo() {
  ...
}

This is fine if browsing the source code, but it’s nice to run type in the terminal to get a quick reminder of what the function does. However this (understandably) doesn’t include comments:

$ type foo
foo is a function
foo ()
{
    ...
}

Which got me thinking “wouldn’t it be nice if these sort of comments persisted so that type could display them?” And in the spirit of Python’s docstrings I came up with this:

foo() {
  : Usage: foo [bar]
  : "Foo's a bar into a baz"
  ...
}

$ type foo
foo is a function
foo ()
{
    : Usage: foo [bar];
    : "Foo's a bar into a baz";
    ...
}

Now the usage is included right in the type output! Of course as you can see quoting becomes an issue which could be error-prone, but it’s a nicer user experience when it works.

So my question is, is this a terrible idea? Are there better alternatives (like a man/info for functions) for providing users of Bash functions with additional context?

Ideally I’d still like the usage instructions to be located nearby the function definition so that people viewing the source code also get the benefit, but if there’s a “proper” way to do this I’m open to alternatives.

Edit these are all fairly simple helper-style functions and I’m just looking to get a little extra context interactively. Certainly for more complex scripts that parse flags I’d add a --help option, but for these it would be somewhat burdensome to add help flags to everything. Perhaps that’s just a cost I should accept, but this : hack seems to work reasonably well without making the source much harder to read our edit.

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

I don’t think that there is just one good way to do this.

Many functions, scripts, and other executables provide a help message if the user provides -h or --help as an option:

$ foo() {
[[ "$1" =~ (-h|--help) ]] && { cat <<EOF
Usage: foo [bar]
Foo's a bar into a baz
EOF
return;
}
: ...other stuff...
}

For example:

$ foo -h
Usage: foo [bar]
Foo's a bar into a baz

$ foo --help
Usage: foo [bar]
Foo's a bar into a baz

Solution 2

I’ve never quite convinced myself to take the plunge and use : commands as pseduo-comments. In particular, I’ve always been worried about the fact that the “comments” are actually arguments that get evaluated, and could potentially have side-effects (or just break things, such as an errant '). I still like the idea’s simplicity, but haven’t ever found the tradeoff quite justifiable.

My hesitation with providing usage text via a --help flag or similar has always been the cruft that comes along with it. As soon as you start accepting flags you quickly get into full-fledged argument parsing which typically (in Bash) requires quite a lot of boilerplate.

To partially bridge this gap I pulled together a small utility that wraps getopts in order to reduce this boilerplate. It still takes up a few lines, so I wouldn’t use it in otherwise-tiny functions, but it’s a lot more concise than using getopts directly. Here’s an example usage with a -h flag (getopts only supports single-letter options):

foo() {
  local _usage='foo [-a] [-b] [-f val] [-v val] [args ...]'
  eval "$(parse_opts 'f:v:abh')"
  if (( h )); then
    echo "Usage: $_usage"
    return 0
  fi
  echo "f=$f v=$v a=$a b=$b -- $#: $*"
}

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply