| 1 | #!/usr/bin/env bash
 | 
| 2 | #
 | 
| 3 | # Common shell functions for task scripts.
 | 
| 4 | #
 | 
| 5 | # Usage:
 | 
| 6 | #   source $LIB_OSH/task-five.sh
 | 
| 7 | #
 | 
| 8 | #   test-foo() {  # define task functions
 | 
| 9 | #     echo foo
 | 
| 10 | #   }
 | 
| 11 | #   task-five "$@"
 | 
| 12 | 
 | 
| 13 | # Definition of a "task"
 | 
| 14 | #
 | 
| 15 | # - File invokes task-five "$@"
 | 
| 16 | #   - or maybe you can look at its source
 | 
| 17 | # - It's a shell function
 | 
| 18 | #   - Has ### docstring
 | 
| 19 | #   - Doesn't start with _
 | 
| 20 | 
 | 
| 21 | : ${LIB_OSH=stdlib/osh}
 | 
| 22 | source $LIB_OSH/byo-server.sh
 | 
| 23 | 
 | 
| 24 | 
 | 
| 25 | # List all functions defined in this file (and not in sourced files).
 | 
| 26 | _bash-print-funcs() {
 | 
| 27 |   ### Print shell functions in this file that don't start with _ (bash reflection)
 | 
| 28 | 
 | 
| 29 |   local funcs
 | 
| 30 |   funcs=($(compgen -A function))
 | 
| 31 |   # extdebug makes `declare -F` print the file path, but, annoyingly, only
 | 
| 32 |   # if you pass the function names as arguments.
 | 
| 33 |   shopt -s extdebug
 | 
| 34 |   declare -F "${funcs[@]}" | grep --fixed-strings " $0" | awk '{print $1}'
 | 
| 35 |   shopt -u extdebug
 | 
| 36 | }
 | 
| 37 | 
 | 
| 38 | _gawk-print-funcs() {
 | 
| 39 |   ### Print shell functions in this file that don't start with _ (awk parsing)
 | 
| 40 | 
 | 
| 41 |   # Using gawk because it has match()
 | 
| 42 |   # - doesn't start with _
 | 
| 43 | 
 | 
| 44 |   # space     = / ' '* /
 | 
| 45 |   # shfunc    = / %begin
 | 
| 46 |   #               <capture !['_' ' '] ![' ']*>
 | 
| 47 |   #               '()' space '{' space
 | 
| 48 |   #               %end /
 | 
| 49 |   # docstring = / %begin
 | 
| 50 |   #               space '###' ' '+
 | 
| 51 |   #               <capture dot*>
 | 
| 52 |   #               %end /
 | 
| 53 |   gawk '
 | 
| 54 |   match($0, /^([^_ ][^ ]*)\(\)[ ]*{[ ]*$/, m) {
 | 
| 55 |     #print NR " shfunc " m[1]
 | 
| 56 |     print m[1]
 | 
| 57 |     #print m[0]
 | 
| 58 |   }
 | 
| 59 | 
 | 
| 60 |   match($0, /^[ ]*###[ ]+(.*)$/, m) {
 | 
| 61 |     print NR " docstring " m[1]
 | 
| 62 |   }
 | 
| 63 | ' $0
 | 
| 64 | }
 | 
| 65 | 
 | 
| 66 | _print-funcs() {
 | 
| 67 |   if command -v gawk > /dev/null; then
 | 
| 68 |     _gawk-print-funcs
 | 
| 69 |   else
 | 
| 70 |     _bash-print-funcs
 | 
| 71 |   fi
 | 
| 72 | }
 | 
| 73 | 
 | 
| 74 | _show-help() {
 | 
| 75 |   # TODO:
 | 
| 76 |   # - Use awk to find comments at the top of the file?
 | 
| 77 |   # - Use OSH to extract docstrings
 | 
| 78 |   # - BYO_COMMAND=list-tasks will reuse that logic?  It only applies to the
 | 
| 79 |   #   current file, not anything in a different file?
 | 
| 80 | 
 | 
| 81 |   echo "Usage: $0 TASK_NAME ARGS..."
 | 
| 82 |   echo
 | 
| 83 |   echo "To complete tasks, run:"
 | 
| 84 |   echo "   source devtools/completion.bash"
 | 
| 85 |   echo
 | 
| 86 |   echo "Tasks:"
 | 
| 87 | 
 | 
| 88 |   if command -v column >/dev/null; then
 | 
| 89 |     _print-funcs | column
 | 
| 90 |   else
 | 
| 91 |     _print-funcs
 | 
| 92 |   fi
 | 
| 93 | }
 | 
| 94 | 
 | 
| 95 | task-five() {
 | 
| 96 |   # Respond to BYO_COMMAND=list-tasks, etc.  All task files need this.
 | 
| 97 |   byo-maybe-run
 | 
| 98 | 
 | 
| 99 |   case ${1:-} in
 | 
| 100 |     ''|--help|-h)
 | 
| 101 |       _show-help
 | 
| 102 |       exit 0
 | 
| 103 |       ;;
 | 
| 104 |   esac
 | 
| 105 | 
 | 
| 106 |   if ! declare -f "$1" >/dev/null; then
 | 
| 107 |     echo "$0: '$1' isn't an action in this task file.  Try '$0 --help'"
 | 
| 108 |     exit 1
 | 
| 109 |   fi
 | 
| 110 | 
 | 
| 111 |   "$@"
 | 
| 112 | }
 |