docs: add recipe help example

This commit is contained in:
Daylin Morgan 2022-09-24 17:53:30 -05:00
parent d6bd8a0247
commit 43aba3fbee
7 changed files with 206 additions and 8 deletions

View file

@ -1,7 +1,7 @@
MAKEFLAGS += --no-print-directory MAKEFLAGS += --no-print-directory
COLS ?= 60 COLS ?= 60
ROWS ?= 20 ROWS ?= 20
EXAMPLES := check embedded EXAMPLES := check embedded recipe-help
CASTS := $(addsuffix /demo.cast, $(EXAMPLES)) CASTS := $(addsuffix /demo.cast, $(EXAMPLES))
all: $(CASTS) all: $(CASTS)

View file

@ -1,10 +1,14 @@
# Examples # Examples
[`Check`](./check) [Confirm](./check)
: Perform a basic confirmation test with the user and exit with error code 1 if input is N/n. : Perform a basic confirmation test with the user and exit with error code 1 if input is N/n.
[`Embedded`](./embedded) [Embedded Scripts](./embedded)
: Use the builtin functions to write multi-line python/bash scripts directly in your `Makefile` : Use the builtin functions to write multi-line python/bash scripts directly in your `Makefile`
[Recipe Help](./recipe-help)
: Display the target, docstring and recipe for a given target then exit.

View file

@ -0,0 +1,139 @@
{"version": 2, "width": 60, "height": 20, "timestamp": 1664059901, "env": {"SHELL": "/usr/bin/zsh", "TERM": "xterm-256color"}}
[0.008451, "o", "\u001b[H\u001b[2J\u001b[3J"]
[0.008952, "o", "bash >> "]
[0.009359, "o", "ma"]
[0.189924, "o", "ke"]
[0.280056, "o", " -"]
[0.370134, "o", "f "]
[0.460177, "o", "re"]
[0.550458, "o", "ci"]
[0.640486, "o", "pe"]
[0.730615, "o", "-h"]
[0.820777, "o", "el"]
[0.910842, "o", "p/"]
[1.091156, "o", "re"]
[1.181306, "o", "ci"]
[1.271522, "o", "pe"]
[1.361548, "o", "-h"]
[1.451772, "o", "el"]
[1.542044, "o", "p."]
[1.631969, "o", "mk"]
[1.722108, "o", " h"]
[1.812243, "o", "el"]
[1.992584, "o", "p\r\n"]
[3.024383, "o", "\u001b[1;36musage:\u001b[0m\r\n\tmake <recipe>\r\n\tmake help <recipe>\r\n\r\n\u001b[1;33m deps-only\u001b[0m │ \u001b[2ma task/target with dependencies\u001b[0m\r\n\u001b[1;33m foo\u001b[0m │ \u001b[2ma dummy rule that depends on the local files\u001b[0m\r\n\u001b[1;33m h, help\u001b[0m │ \u001b[2mshow this help\u001b[0m\r\n\r\n"]
[5.031848, "o", "\u001b[H\u001b[2J\u001b[3Jbash >> "]
[5.033617, "o", "ma"]
[5.214025, "o", "ke"]
[5.304303, "o", " -"]
[5.394401, "o", "f "]
[5.484589, "o", "re"]
[5.574811, "o", "ci"]
[5.66483, "o", "pe"]
[5.755019, "o", "-h"]
[5.84516, "o", "el"]
[5.93541, "o", "p/"]
[6.115387, "o", "re"]
[6.205505, "o", "ci"]
[6.295713, "o", "pe"]
[6.385951, "o", "-h"]
[6.476085, "o", "el"]
[6.566208, "o", "p."]
[6.656285, "o", "mk"]
[6.746562, "o", " h"]
[6.836615, "o", "el"]
[7.016942, "o", "p "]
[7.106926, "o", "he"]
[7.19701, "o", "lp"]
[7.287225, "o", "\r\n"]
[8.317848, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
[8.324713, "o", " \u001b[1;33mh help\u001b[0m\r\n\u001b[38m ────────────────────────────────────────────────────────\u001b[0m\r\n $(call py,help_py) || { echo \"exiting early!\"; exit 1; }\r\n\r\n"]
[8.328735, "o", "exiting early!\r\n"]
[8.328871, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
[10.331577, "o", "\u001b[H\u001b[2J\u001b[3J"]
[10.331816, "o", "bash >> "]
[10.333573, "o", "ma"]
[10.514271, "o", "ke"]
[10.604555, "o", " -"]
[10.694653, "o", "f "]
[10.784848, "o", "re"]
[10.87526, "o", "ci"]
[10.965322, "o", "pe"]
[11.055364, "o", "-h"]
[11.145456, "o", "el"]
[11.23557, "o", "p/"]
[11.415828, "o", "re"]
[11.505942, "o", "ci"]
[11.596096, "o", "pe"]
[11.68623, "o", "-h"]
[11.776544, "o", "el"]
[11.866685, "o", "p."]
[11.95676, "o", "mk"]
[12.046838, "o", " h"]
[12.136847, "o", "el"]
[12.317252, "o", "p "]
[12.407456, "o", "de"]
[12.497528, "o", "ps"]
[12.587592, "o", "-o"]
[12.677666, "o", "nl"]
[12.767817, "o", "y\r\n"]
[13.818205, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
[13.827472, "o", "\u001b[1;33m deps-only\u001b[0m │ \u001b[2ma task/target with dependencies\u001b[0m\r\n \u001b[38mdeps\u001b[0m: \u001b[2mfoo\u001b[0m\r\n\r\n"]
[13.832182, "o", "exiting early!\r\n"]
[13.83243, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
[15.835429, "o", "\u001b[H\u001b[2J\u001b[3J"]
[15.83575, "o", "bash >> "]
[15.837618, "o", "ma"]
[16.018125, "o", "ke"]
[16.108476, "o", " -"]
[16.198731, "o", "f "]
[16.289003, "o", "re"]
[16.379138, "o", "ci"]
[16.469105, "o", "pe"]
[16.559388, "o", "-h"]
[16.649374, "o", "el"]
[16.739538, "o", "p/"]
[16.919813, "o", "re"]
[17.009951, "o", "ci"]
[17.100097, "o", "pe"]
[17.19021, "o", "-h"]
[17.280433, "o", "el"]
[17.370612, "o", "p."]
[17.460651, "o", "mk"]
[17.550888, "o", " h"]
[17.641021, "o", "el"]
[17.821304, "o", "p "]
[17.911452, "o", "fo"]
[18.001558, "o", "o\r\n"]
[19.029965, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
[19.039573, "o", "\u001b[1;33m foo\u001b[0m │ \u001b[2ma dummy rule that depends on the local files\u001b[0m\r\n \u001b[38mdeps\u001b[0m: \u001b[2mcheck embedded functions.sh index.md Makefile recipe-help\u001b[0m\r\n\u001b[38m ────────────────────────────\u001b[0m\r\n @echo 'this is a dummy rule'\r\n\r\n"]
[19.044473, "o", "exiting early!\r\n"]
[19.044637, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
[21.047851, "o", "\u001b[H\u001b[2J\u001b[3J"]
[21.048155, "o", "bash >> "]
[21.050062, "o", "ma"]
[21.230577, "o", "ke"]
[21.320832, "o", " -"]
[21.410896, "o", "f "]
[21.501092, "o", "re"]
[21.591208, "o", "ci"]
[21.681347, "o", "pe"]
[21.77147, "o", "-h"]
[21.861573, "o", "el"]
[21.951884, "o", "p/"]
[22.13224, "o", "re"]
[22.222235, "o", "ci"]
[22.312372, "o", "pe"]
[22.40265, "o", "-h"]
[22.49285, "o", "el"]
[22.582874, "o", "p."]
[22.672961, "o", "mk"]
[22.763162, "o", " h"]
[22.853371, "o", "el"]
[23.033526, "o", "p "]
[23.123576, "o", "ba"]
[23.214792, "o", "r\r\n"]
[24.264812, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
[24.271227, "o", " \u001b[1;33mbar\u001b[0m\r\n\u001b[38m ─────────────────────────────────────\u001b[0m\r\n @echo 'some rule with no help string'\r\n\r\n"]
[24.275046, "o", "exiting early!\r\n"]
[24.275205, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]

View file

@ -0,0 +1,12 @@
---
asciinema: true
---
# Recipe Help
<div id="demo-cast"></div>
```make title="recipe-help.mk"
--8<-- "docs/examples/recipe-help/recipe-help.mk"
```

View file

@ -0,0 +1,24 @@
## deps-only | a task/target with dependencies
.PHONY: deps-only
deps-only: foo
## foo | a dummy rule that depends on the local files
.PHONY: foo
foo: $(wildcard *)
@echo 'this is a dummy rule'
# bar but no docstring
.PHONY: bar
bar:
@echo 'some rule with no help string'
define USAGE
{a.header}usage:{a.end}
make <recipe>
make help <recipe>
endef
.DEFAULT_GOAL = help
include $(shell git rev-parse --show-toplevel)/task.mk

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
source "$(dirname "${BASH_SOURCE[0]}")/../functions.sh"
cmd 'make -f recipe-help/recipe-help.mk help'
cmd 'make -f recipe-help/recipe-help.mk help help'
cmd 'make -f recipe-help/recipe-help.mk help deps-only'
cmd 'make -f recipe-help/recipe-help.mk help foo'
cmd 'make -f recipe-help/recipe-help.mk help bar'
sleep 1

18
task.mk
View file

@ -1,7 +1,7 @@
# }> [github.com/daylinmorgan/task.mk] <{ # # }> [github.com/daylinmorgan/task.mk] <{ #
# Copyright (c) 2022 Daylin Morgan # Copyright (c) 2022 Daylin Morgan
# MIT License # MIT License
# version: v22.9.19-13-g63eb8ac-dev # version: v22.9.19-17-gd6bd8a0-dev
# #
# task.mk should be included at the bottom of your Makefile with `-include .task.mk` # task.mk should be included at the bottom of your Makefile with `-include .task.mk`
# See below for the standard configuration options that should be set prior to including this file. # See below for the standard configuration options that should be set prior to including this file.
@ -15,6 +15,7 @@ MSG_STYLE ?= faint
DIVIDER ?= DIVIDER ?=
DIVIDER_STYLE ?= default DIVIDER_STYLE ?= default
HELP_SEP ?= HELP_SEP ?=
WRAP ?= 100
# python f-string literals # python f-string literals
EPILOG ?= EPILOG ?=
USAGE ?={ansi.header}usage{ansi.end}:\n make <recipe>\n USAGE ?={ansi.header}usage{ansi.end}:\n make <recipe>\n
@ -50,7 +51,8 @@ tconfirm = $(call py,confirm_py,$(1))
_update-task.mk: _update-task.mk:
$(call tprint,{a.b_cyan}Updating task.mk{a.end}) $(call tprint,{a.b_cyan}Updating task.mk{a.end})
curl https://raw.githubusercontent.com/daylinmorgan/task.mk/main/task.mk -o .task.mk curl https://raw.githubusercontent.com/daylinmorgan/task.mk/main/task.mk -o .task.mk
export MAKEFILE_LIST MAKE TASK_MAKEFILE_LIST := $(filter-out $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)),$(MAKEFILE_LIST))
export MAKEFILE_LIST MAKE TASK_MAKEFILE_LIST
ifndef INHERIT_SHELL ifndef INHERIT_SHELL
SHELL := $(shell which bash) SHELL := $(shell which bash)
endif endif
@ -138,13 +140,17 @@ def recipe_help_header(goal):
return f" {ansi.style(goal,'goal')}" return f" {ansi.style(goal,'goal')}"
def get_goal_deps(goal="task.mk"): def get_goal_deps(goal="task.mk"):
make = os.getenv("MAKE", "make") make = os.getenv("MAKE", "make")
database = subprocess.check_output([make, "-p", "-n"], universal_newlines=True) cmd = [make, "-p", "-n", "-i"]
for file in os.getenv("TASK_MAKEFILE_LIST", "").split():
cmd.extend(["-f", file])
database = subprocess.check_output(cmd, universal_newlines=True)
dep_pattern = re.compile(r"^" + goal + ":(.*)?") dep_pattern = re.compile(r"^" + goal + ":(.*)?")
for line in database.splitlines(): for line in database.splitlines():
match = dep_pattern.search(line) match = dep_pattern.search(line)
if match and match.groups()[0]: if match and match.groups()[0]:
return wrap( return wrap(
f"{ansi.style('deps','default')}: {ansi.style(match.groups()[0].strip(),'msg')}", f"{ansi.style('deps','default')}: {ansi.style(match.groups()[0].strip(),'msg')}",
width=cfg.wrap,
initial_indent=" ", initial_indent=" ",
subsequent_indent=" ", subsequent_indent=" ",
) )
@ -224,11 +230,11 @@ def print_arg_help(help_args):
print(f"{ansi.style('task.mk recipe help','header')}\n") print(f"{ansi.style('task.mk recipe help','header')}\n")
for arg in help_args.split(): for arg in help_args.split():
print("\n".join(parse_goal(gen_makefile(), arg))) print("\n".join(parse_goal(gen_makefile(), arg)))
print()
def main(): def main():
help_args = os.getenv("HELP_ARGS") help_args = os.getenv("HELP_ARGS")
if help_args: if help_args:
print_arg_help(help_args) print_arg_help(help_args)
print(ansi.faint)
sys.exit(1) sys.exit(1)
else: else:
print_help() print_help()
@ -284,6 +290,7 @@ class Config:
sep: str sep: str
epilog: str epilog: str
usage: str usage: str
wrap: int
color2byte = dict( color2byte = dict(
black=0, black=0,
red=1, red=1,
@ -364,5 +371,6 @@ class Ansi:
else: else:
return f"{self.__dict__[style]}{text}{self.__dict__['end']}" return f"{self.__dict__[style]}{text}{self.__dict__['end']}"
a = ansi = Ansi() a = ansi = Ansi()
cfg = Config("$(DIVIDER)", "$(HELP_SEP)", f"""$(EPILOG)""", f"""$(USAGE)""") cfg = Config(
"$(DIVIDER)", "$(HELP_SEP)", f"""$(EPILOG)""", f"""$(USAGE)""",int('$(WRAP)'))
endef endef