1

I have the following condition in a few bash functions to print their help message, but I realized that this is such an annoying repetition and wonder if there's a way around it so that the condition and call happen in a single wrapper function. So instead of this:

fn1() {
  arg=$@
  [ ! -z $arg ] || [ $arg = "--help" ] && helpit "fn1 help msg." && return

  # fn body here
}
fn2() {
  arg=$@
  [ ! -z $arg ] || [ $arg = "--help" ] && helpit "fn2 help msg." && return

  # fn body here
}

We have this:

try_help() {
  # FYI $@ is the help msg and not the params of its caller
  arg=$@
  [ ! -z $arg ] || [ $arg = "--help" ] && helpit "Delete a remote branch by name." && return 1
  return 0
}
fn1() {
  try_help "fn1 help msg." || return

  # fn body here
}
fn2() {
  try_help "fn2 help msg." || return

  # fn body here
}

Is this possible to do?

7
  • 1
    arg=$@ doesn't work the way you want, btw. It's exactly identical to arg=$*, because $@ can't be stored in a string variable at all (it can only be stored in arrays). Commented Apr 3, 2022 at 12:44
  • @CharlesDuffy so we can't forward them to the try_help for checking? Commented Apr 3, 2022 at 12:45
  • You can absolutely forward them, you just can't do it with a string variable. You could use a global/shared array, or you can just pass them on try_help's argument list. Commented Apr 3, 2022 at 12:47
  • 1
    BTW, ... && helpit "something" && return 1 is a bad idea, because it executes return 1 only if helpit has a successful exit status. Better to run ... && { helpit "something"; return 1; } so the return 1 runs even if helpit reports a failure. Commented Apr 3, 2022 at 12:51
  • 1
    ...to go more into why [ -z $arg ] is buggy: When you have an unquoted empty argument list, it turns into no arguments at all, so you get [ -z ], which is treated like [ -n "-z" ], which is why it appears to work. But it only "works" when $arg is a simple enough value; consider arg='foo bar'; you get [ -z "foo" "bar" ], which is an invalid test command so the code throws an error instead of just silently returning false as it should. Commented Apr 3, 2022 at 12:55

1 Answer 1

3

Trivially done.

helpit() { echo "$*" >&2; }
try_help() {
  local help_msg arg
  help_msg=$1; shift
  if (( $# == 0 )); then
    echo "No arguments found. Printing help:" >&2
    helpit "$help_msg"
    return 1
  fi
  for arg in "$@"; do
    case $arg in
      --)     return 0;;
      --help) helpit "$help_msg"; return 1;;
    esac
  done
  return 0
}

fn1() {
  try_help "fn1 help msg" "$@" || return
  # fn body here
}
fn2() {
  try_help "fn2 help msg" "$@" || return
  # fn body here
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.