70 %
Chris Biscardi

Make help task

Here's the awk script we'll be talking about

awk
BEGIN {FS = ":.*?## "}
/^[a-zA-Z_-]+:.*?## / {
sub("\\\\n",sprintf("\n%22c"," "), $2)
printf "\033[36m%-20s\033[0m %s\n", $1, $2
}

Place it in a help command in the beginning of your Makefile

make
help: ## Show this help.
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

.PHONY is needed because we're not looking to cache any of our steps. We could specify file dependencies for the build step, but cargo already does such a great job of incrementally building, it doesn't matter much.

We start off by our tasks by basically copy /pasting this help task into the file. Make doesn't come with any --help output, so this task defines an awk script that parses the file looking for task names followed by comments. The BEGIN segment sets the FS, or file separator, variable to :.*?## which is a regex. Choosing a file separator is a large part of what makes awk work. This example hands us the name of the task as $1 and the comment as $2, effectively splitting the line on that regex.

After that, we include an awk body that tests against a fuller version of the regex. If the regex passes, we execute the code inside the curly braces, if not then we don't.

Inside the body of our script, we substitute escaped newlines for actual newlines in the doc comments. The %22c is a 22 character offset, which is slightly larger than the space we're using to align the output in the next line (20 characters).

substitution
awk
sub("\\\\n",sprintf("\n%22c"," "), $2)

While sprintf formats a string in-place printf formats a string and then outputs it to stdout. This next line formats the name of the task and the documentation in a table where the first column is 20 characters wide. Also note that the slashes and square brackets are ansi escape codes, in this case they're codes for specifying colors for the text following them. All of the escape codes we care about have the form \033[NNNm where NNN is a number.

printf-escape-codes
awk
printf "\033[36m%-20s\033[0m %s\n", $1, $2

Chunking the string out based on that rule gives us the following items.

text
\033[36m
%-20s
\033[0m
%s\n

\033[36m uses the number 36 to set the text color (often referred to as the foreground color) to a blue.

%-20s is a placeholder for a string (%s) where the string is at least 20 characters long and left-justified. This creates an effect of printing a table.

\033[0m uses 0 to reset the formatting for the following text.

%s\n creates another spot to insert a string.

Finally, when we use this script in the Makefile, we take advantage of the MAKEFILE_LIST variable which gives us a list of all the Makefiles that were used.