Here's the awk script we'll be talking about
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
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).
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 "\033[36m%-20s\033[0m %s\n", $1, $2
Chunking the string out based on that rule gives us the following items.
\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.