Skip to content

Instantly share code, notes, and snippets.

@rsperl
Last active April 17, 2024 23:02
Show Gist options
  • Star 48 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save rsperl/d2dfe88a520968fbc1f49db0a29345b9 to your computer and use it in GitHub Desktop.
Save rsperl/d2dfe88a520968fbc1f49db0a29345b9 to your computer and use it in GitHub Desktop.
self-documenting makefile with colors
SHELL=/bin/bash
# to see all colors, run
# bash -c 'for c in {0..255}; do tput setaf $c; tput setaf $c | cat -v; echo =$c; done'
# the first 15 entries are the 8-bit colors
# define standard colors
ifneq (,$(findstring xterm,${TERM}))
BLACK := $(shell tput -Txterm setaf 0)
RED := $(shell tput -Txterm setaf 1)
GREEN := $(shell tput -Txterm setaf 2)
YELLOW := $(shell tput -Txterm setaf 3)
LIGHTPURPLE := $(shell tput -Txterm setaf 4)
PURPLE := $(shell tput -Txterm setaf 5)
BLUE := $(shell tput -Txterm setaf 6)
WHITE := $(shell tput -Txterm setaf 7)
RESET := $(shell tput -Txterm sgr0)
else
BLACK := ""
RED := ""
GREEN := ""
YELLOW := ""
LIGHTPURPLE := ""
PURPLE := ""
BLUE := ""
WHITE := ""
RESET := ""
endif
# set target color
TARGET_COLOR := $(BLUE)
POUND = \#
.PHONY: no_targets__ info help build deploy doc
no_targets__:
.DEFAULT_GOAL := help
colors: ## show all the colors
@echo "${BLACK}BLACK${RESET}"
@echo "${RED}RED${RESET}"
@echo "${GREEN}GREEN${RESET}"
@echo "${YELLOW}YELLOW${RESET}"
@echo "${LIGHTPURPLE}LIGHTPURPLE${RESET}"
@echo "${PURPLE}PURPLE${RESET}"
@echo "${BLUE}BLUE${RESET}"
@echo "${WHITE}WHITE${RESET}"
job1: ## help for job 1
@echo "job 1 started"
@$(MAKE) job2
@echo "job 1 finished"
job2: ## help for job 2
@echo "job 2"
job%: ## help for job with wildcard
@echo "job $@"
help:
@echo ""
@echo " ${BLACK}:: ${RED}Self-documenting Makefile${RESET} ${BLACK}::${RESET}"
@echo ""
@echo "Document targets by adding '$(POUND)$(POUND) comment' after the target"
@echo ""
@echo "Example:"
@echo " | job1: $(POUND)$(POUND) help for job 1"
@echo " | @echo \"run stuff for target1\""
@echo ""
@echo "${BLACK}-----------------------------------------------------------------${RESET}"
@grep -E '^[a-zA-Z_0-9%-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "${TARGET_COLOR}%-30s${RESET} %s\n", $$1, $$2}'
# vim:noexpandtab:ts=8:sw=8:ai
@Unviray
Copy link

Unviray commented Oct 5, 2020

Does -Txterm is a necessary parameter? What happens if I'm using non-xterm terminal?

@sergeyklay
Copy link

sergeyklay commented Jan 7, 2021

ifneq (,$(findstring xterm,${TERM}))
	GREEN := $(shell tput -Txterm setaf 2)
	RESET := $(shell tput -Txterm sgr0)
else
	GREEN := ""
	RESET := ""
endif

@rsperl
Copy link
Author

rsperl commented Jan 7, 2021

Thanks for the suggestion! I updated the gist to allow for non-xterm TERM.

@sergeyklay
Copy link

You're welcome :)

@audetcameron
Copy link

audetcameron commented Apr 19, 2021

I'm not really good with the grep command but is there a way to make it so the command color can be split by the command definition using a colon? example
image
however colors would be white and show all the colors would remain the same.

ps, awesome gist by the way. :)

@rsperl
Copy link
Author

rsperl commented Apr 20, 2021

I think this is what you are looking for -- change the line

	@grep -E ...| awk 'BEGIN {FS = ":.*?## "}; {printf "${TARGET_COLOR}%-30s${RESET} %s\n", $$1, $$2}'

to add ":" after $$1 so that it is

	@grep -E ... | awk 'BEGIN {FS = ":.*?## "}; {printf "${TARGET_COLOR}%-30s${RESET} %s\n", $$1":", $$2}'

This gives you output that looks like

colors:                        show all the colors
job%:                          help for job with wildcard
job1:                          help for job 1
job2:                          help for job 2

@BogdanTheGeek
Copy link

Hi, Wouldn't this be more portable?

# define standard colors
ifneq (,$(findstring 256color, ${TERM}))

Had to change to the above to work with the suckless terminal, swill works fine on xterm clones

@ujlbu4
Copy link

ujlbu4 commented Sep 2, 2021

Normally -Ttype is not necessary because the default is taken from the $TERM (, so looks like we can improve it like this:

ifneq ($(TERM),)
    GREEN        := $(shell tput setaf 2)
    RESET        := $(shell tput sgr0)
else
    GREEN        := ""
    RESET        := ""
endif

^ if TERM is defined let tput decide which type to use, otherwise keep it empty

@4F2E4A2E
Copy link

O macOS, I had to set RESET to RESET := $(shell printf "\033[0;10m") to escape (B char being printed.

See: https://unix.stackexchange.com/questions/470499/what-is-the-ansi-escape-equivalent-of-tput-sgr0

@kerns
Copy link

kerns commented Aug 31, 2022

Very cool. Is there an easy way to reuse this setup in the head of bash scripts? Would be nice if scripts could share the same colors used in a Makefile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment