interrupt (function)

Interrupt is very concise but powerful function within glassthought-bash-env

# Interrupt current process without quitting the current shell.
#
# This is useful to be able to write methods that can halt a process without
# exiting the current shell.
#
# For example allows writing verify methods that don't have to be checked
# for return codes, or allowing getting some value from a function captured
# without having to be concerned about the return code.
#
# Further documentation: https://www.glassthought.com/notes/tjajxxsqb4u6fpousg23w29/
interrupt(){
  # >&2 reference: https://stackoverflow.com/a/23550347/7858768, redirects the
  # output to stderr instead of stdout. So that when we interrupt the process
  # within subshell that are captured by some other process, we display the
  # interrupt message to stderr (instead of the echo.red being captured).
  >&2 echo.red "Interrupting: ${1}"

  kill -INT -$$
}
export -f interrupt

Use cases:

Use case: making more robust getter methods

Without interrupt: example getter method with return check
some_getter_that_is_not_happy_with_return(){
  echo "some-value (BashPID=${BASHPID})"
  return 1
}

main() {
  echo "main BASHPID: ${BASHPID}"

  return_1=$(some_getter_that_is_not_happy_with_return)

  # We have to have this verbose check for return code.
  if [[ $? -ne 0 ]]; then
    echo "return_1: ${return_1}"
    echo.red "unhappy finish"
    return 1
  fi

  echo "return_1: ${return_1}"
  echo.green "happy finish"
}

main "${@}"
main BASHPID: 12756
return_1: some-value (BashPID=12757)
unhappy finish
With interrupt much more concise
some_getter_that_is_not_happy_with_interrupt(){
  echo "some-value"
  interrupt "Did not get the value (BASHPID=${BASHPID})"
}

main() {
  echo "main BASHPID: ${BASHPID}"

  # No need to check for return code as, the function call will 
  # interrupt the flow if there is an issue.
  # Allowing us to write much less boiler plate of code 
  # and focus on the logic.
  return_1=$(some_getter_that_is_not_happy_with_interrupt)

  echo "return_1: ${return_1}"
  echo.green "happy finish"
}

main "${@}"

Output:

main BASHPID: 13001
Interrupting: Did not get the value (BASHPID=13002)

Verify methods: that actually stop the flow

Verify example
verify.file_exists(){
  if [ ! -f "${1}" ]; then
    interrupt "File ${1} does not exist"
  fi
}

main() {
  verify.file_exists /tmp/i_dont_exist

  echo "I am still here"
}

main "${@}"
Interrupting: File /tmp/i_dont_exist does not exist

Backlinks