#!/bin/bash # If a command was specified like `make help CMD=build` then try to # gather help for that command. if [ -n "$CMD" ]; then # Get the make targets for generating different help sections short_target=".help-short--$CMD"; long_target=".help-long--$CMD"; options_target=".help-options--$CMD"; usage_target=".help-usage--$CMD"; extra_target=".help-extra--$CMD"; delim=$'\036' # ASCII 30 nl=$'\037' # Try and get the help for the command. Sections of the output will be delimited bv ASCII 30 (arbirary non-printing char) output=$(make -k $short_target .help-sep-1 $long_target .help-sep-2 $options_target .help-sep-3 $usage_target .help-sep-4 $extra_target .help-sep-5 2>/dev/null) # Clean the output for "read" by replacing newlines with ASCII 31 (also arbitrary) cleaned_output=$(echo "$output" | tr '\n' $nl ) # Read the output into an array IFS="$delim" read -r -a sections <<<"$cleaned_output" # Get the newlines back short_desc="${sections[0]}" long_desc=$(echo "${sections[1]}" | tr $nl '\n') options_text=$(echo "${sections[2]}" | tr $nl '\n') usage_text=$(echo "${sections[3]}" | tr $nl '\n') extra_text=$(echo "${sections[4]}" | tr $nl '\n') # If we found a long help description, then continue printing help. if [ -n "$long_desc" ]; then # Print a loading message since make takes a second to run. echo -n "Gathering help for $CMD command..."; # If this command has options, output them as well. if [ -n "$options_text" ]; then # The REFORMAT_OPTIONS flag turns makefile options like DO_THE_THING into # CLI options like --do-the-thing. if [ -n "$REFORMAT_OPTIONS" ]; then options_text=$(paste -s -d '\t\n' <(echo "$options_text" | awk 'NR % 2 == 1 { option = $0; gsub("_", "-", option); printf " --%s\n", tolower(option); next } { print $0 }') | column -t -s $'\t'); else options_text=$(paste -s -d '\t\n' <(echo "$options_text") | column -t -s $'\t'); fi; fi; # We're done loading, so erase the loading message. echo -ne "\r\033[K"; # Output whatever help we hot. echo -e "\033[1mNAME:\033[0m"; echo " $CMD - $short_desc"; if [ -n "$usage_text" ]; then echo; echo -e "\033[1mUSAGE:\033[0m"; echo " $usage_text"; fi; if [ -n "$long_desc" ]; then echo; echo -e "\033[1mDESCRIPTION:\033[0m"; echo " $long_desc" | fmt -w 80; fi; if [ -n "$options_text" ]; then echo; echo -e "\033[1mOPTIONS:\033[0m"; echo "$options_text"; fi; if [ -n "$extra_text" ]; then IFS= read -r first_line <<< "$extra_text" rest_of_text="$(echo "$extra_text" | tail -n +2)" echo; echo -e "\033[1m$first_line\033[0m" echo "$rest_of_text"; fi; # If there's no long help description, there's no additional help for the command. else echo "No help found for $CMD command."; fi; # If no specific help was requested, output all the available commands. else targets=$(awk '/^[^#[:space:]].*:/ {print $1}' Makefile | grep '^\.help-short--' | sed 's/:$//' | sort); if [ -n "$targets" ]; then output=$(make --no-print-directory $targets 2>/dev/null); paste <(echo "$targets" | sed "s/^\.help-short--/ $HELP_CMD_PREFIX /") <(echo "$output") | column -t -s $'\t'; echo; else echo "No help targets found."; fi fi