#!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x export SUBCOMMAND_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands" fn-help() { declare CMD="$1" local cmd EXIT_CODE if [[ "$CMD" == "help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:help" ]]; then fn-help-all "$@" exit 0 fi pushd "$SUBCOMMAND_ROOT" > /dev/null 2>&1 for cmd in *; do if [[ "$CMD" == "${PLUGIN_COMMAND_PREFIX}:$cmd" ]]; then "$SUBCOMMAND_ROOT/$cmd" "$@" EXIT_CODE="$?" exit "$EXIT_CODE" fi done popd > /dev/null 2>&1 exit "$DOKKU_NOT_IMPLEMENTED_EXIT" } fn-help-all() { declare CMD="$1" SUBCOMMAND="$2" local CMD_OUTPUT BLUE BOLD FULL_OUTPUT NORMAL FULL_OUTPUT=true if [[ "$CMD" = "$PLUGIN_COMMAND_PREFIX:help" ]] ; then BOLD="$(tput bold)" NORMAL="\033[m" BLUE="\033[0;34m" CYAN="\033[1;36m" if [[ -n "$SUBCOMMAND" ]] && [[ "$SUBCOMMAND" != "--all" ]]; then fn-help-contents-subcommand "$SUBCOMMAND" "$FULL_OUTPUT" return "$?" fi echo -e "${BOLD}usage${NORMAL}: dokku $PLUGIN_COMMAND_PREFIX[:COMMAND]" echo '' echo -e "${BOLD}List your $PLUGIN_COMMAND_PREFIX services.${NORMAL}" echo '' echo -e "${BLUE}Example:${NORMAL}" echo '' echo " \$ dokku $PLUGIN_COMMAND_PREFIX:list" echo '' fn-help-list-example | column -c5 -t -s, echo '' echo -e "dokku ${BOLD}${PLUGIN_COMMAND_PREFIX}${NORMAL} commands: (get help with ${CYAN}dokku ${PLUGIN_COMMAND_PREFIX}:help SUBCOMMAND${NORMAL})" echo '' fn-help-contents | sort | column -c2 -t -s, echo '' elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then fn-help-contents else cat< /dev/null' RETURN INT TERM EXIT pushd "$SUBCOMMAND_ROOT" > /dev/null 2>&1 for cmd in *; do fn-help-contents-subcommand "$cmd" || true done } fn-help-contents-subcommand() { declare SUBCOMMAND="$1" FULL_OUTPUT="$2" local UNCLEAN_FILE="${TMPDIR}cmd-unclean" CLEAN_FILE="${TMPDIR}cmd-clean" local BOLD CMD_OUTPUT CYAN EXAMPLE LIGHT_GRAY NORMAL rm -rf "$UNCLEAN_FILE" "$CLEAN_FILE" cat "$SUBCOMMAND_ROOT/$SUBCOMMAND" > "$UNCLEAN_FILE" fn-help-subcommand-sanitize "$UNCLEAN_FILE" "$CLEAN_FILE" if [[ "$(fn-help-is-subcommand-unimplemented "$CLEAN_FILE")" == true ]]; then return 1 fi args="$(fn-help-subcommand-args "$CLEAN_FILE" "$FULL_OUTPUT")" cmd_line="$(echo -e "${SUBCOMMAND} ${args}" | sed -e 's/[[:space:]]*$//')" desc="$(grep desc "$CLEAN_FILE" | head -1)" eval "$desc" BLUE="\033[0;34m" BOLD="$(tput bold)" CYAN="\033[1;36m" NORMAL="\033[m" LIGHT_GRAY="\033[2;37m" LIGHT_RED="\033[1;31m" CMD_OUTPUT="$(echo -e " ${PLUGIN_COMMAND_PREFIX}:${cmd_line}, ${LIGHT_GRAY}${desc}${NORMAL}")" if [[ "$FULL_OUTPUT" != "true" ]]; then echo "$CMD_OUTPUT" return 0 fi echo -e "${BOLD}usage:${NORMAL} dokku ${PLUGIN_COMMAND_PREFIX}:${cmd_line}" echo '' echo -e "${BOLD}${desc}${NORMAL}" echo '' ARGS="$(fn-help-subcommand-list-args "$CLEAN_FILE")" if [[ -n "$ARGS" ]]; then echo -e "${CYAN}arguments:${NORMAL}" echo '' echo "$ARGS" | column -c2 -t -s, echo '' fi FLAGS="$(fn-help-subcommand-list-flags "$CLEAN_FILE")" if [[ -n "$FLAGS" ]]; then echo -e "${BLUE}flags:${NORMAL}" echo '' echo "$FLAGS" | column -c2 -t -s, echo '' fi EXAMPLE="$(fn-help-subcommand-example "$CLEAN_FILE")" if [[ -n "$EXAMPLE" ]]; then echo -e "${LIGHT_RED}examples:${NORMAL}" echo '' echo "$EXAMPLE" echo '' fi return 0 } fn-help-is-subcommand-unimplemented() { declare FUNC_FILE="$1" local UNIMPLEMENTED UNIMPLEMENTED="$(grep "Not yet implemented" "$FUNC_FILE" | head -1 || true)" if [[ -n "$UNIMPLEMENTED" ]]; then echo true else echo false fi } fn-help-list-example() { # shellcheck disable=SC2034 declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" cat<* ]] && line="\n ${BOLD}${line}${NORMAL}" # shellcheck disable=SC2001 [[ "$line" == " "* ]] && line=" ${OTHER_GRAY}$(echo "$line" | sed -e 's/^[[:space:]]*//')${NORMAL}" echo -e "${NEWLINE}${line}" LAST_LINE="sentence" NEWLINE="\n" fi done } fn-help-subcommand-list-args() { declare FUNC_FILE="$1" local EXAMPLE LIGHT_GRAY NORMAL FLAGS=$(grep "#A" "$FUNC_FILE" | cut -d'A' -f2- | sed -e 's/^[[:space:]]*//' || true) if [[ -z "$FLAGS" ]]; then return 0 fi NORMAL="\033[m" LIGHT_GRAY="\033[2;37m" _fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}" done } fn-help-subcommand-list-flags() { declare FUNC_FILE="$1" local EXAMPLE LIGHT_GRAY NORMAL FLAGS=$(grep "#F" "$FUNC_FILE" | cut -d'F' -f2- | sed -e 's/^[[:space:]]*//' || true) if [[ -z "$FLAGS" ]]; then return 0 fi NORMAL="\033[m" LIGHT_GRAY="\033[2;37m" _fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}" done } fn-help-subcommand-sanitize() { declare FUNC_FILE="$1" OUTGOING_FUNC_FILE="$2" local FUNCTION_FOUND=false local IFS OIFS touch "$OUTGOING_FUNC_FILE" OIFS="$IFS" IFS=, while read -r p; do IFS="$OIFS" if [[ "$p" == *"-cmd \"\$@\""* ]] || [[ "$p" == "" ]]; then continue fi if [[ "$FUNCTION_FOUND" == true ]]; then echo "$p" >> "$OUTGOING_FUNC_FILE" continue fi if [[ "$p" == *"()"* ]]; then FUNCTION_FOUND=true echo "$p" >> "$OUTGOING_FUNC_FILE" continue fi done < "$FUNC_FILE" } _fn-help-apply-shell-expansion() { declare desc="Expand environment variables for a shell command" declare data="$1" declare delimiter="__apply_shell_expansion_delimiter__" declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter" eval "$command" }