mirror of
https://github.com/daylinmorgan/task.mk.git
synced 2024-12-22 10:00:43 -06:00
Compare commits
12 commits
234e3cee35
...
b19ddbae68
Author | SHA1 | Date | |
---|---|---|---|
b19ddbae68 | |||
3cd8b28a58 | |||
43aba3fbee | |||
d6bd8a0247 | |||
401eb1088b | |||
3defee72dc | |||
b75a3c2c98 | |||
63eb8ac754 | |||
bc4c95aab9 | |||
cc81782069 | |||
b1449d8991 | |||
bcb07718fd |
21 changed files with 592 additions and 381 deletions
16
Makefile
16
Makefile
|
@ -1,20 +1,22 @@
|
|||
VERSION ?= $(shell git describe --tags --always --dirty | sed s'/dirty/dev/')
|
||||
TEMPLATES := $(shell find src/ -type f)
|
||||
.DEFAULT_GOAL := help
|
||||
SHELL := /bin/zsh
|
||||
INHERIT_SHELL = true
|
||||
|
||||
msg = $(if $(tprint),$(call tprint,{a.bold}==> {a.magenta}$(1){a.end}),@echo '==> $(1)')
|
||||
|
||||
|
||||
### task.mk development | args: -d -ms b_green --align center
|
||||
## bootstrap | generate local dev environment
|
||||
.PHONY: bootstrap
|
||||
bootstrap:
|
||||
$(call msg,Bootstrap Environment)
|
||||
.PHONY: bootstrap env hooks
|
||||
bootstrap: env hooks
|
||||
env:
|
||||
$(call msg,Bootstrapping Environment)
|
||||
@mamba create -p ./env python jinja2 black -y
|
||||
@mamba run -p ./env pip install yartsu
|
||||
hooks:
|
||||
@git config core.hooksPath .githooks
|
||||
|
||||
docs-env:
|
||||
@mamba run -p ./env pip install mkdocs-material mkdocs-git-revision-date-localized-plugin
|
||||
## l, lint | lint the python
|
||||
.PHONY: l lint
|
||||
l lint:
|
||||
|
@ -67,7 +69,7 @@ task.mk: $(TEMPLATES) generate.py
|
|||
./generate.py $(VERSION) > task.mk
|
||||
|
||||
define USAGE
|
||||
{a.$(HEADER_STYLE)}usage:{a.end}\n make <recipe>\n
|
||||
{a.style('usage','header')}:\n make <recipe>\n
|
||||
Turn your {a.style('`Makefile`','b_magenta')} into
|
||||
the {a.italic}{a.underline}task runner{a.end} you always needed.
|
||||
See the example output below.\n
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
MAKEFLAGS += --no-print-directory
|
||||
COLS ?= 60
|
||||
ROWS ?= 20
|
||||
EXAMPLES := check embedded
|
||||
EXAMPLES := check embedded recipe-help
|
||||
CASTS := $(addsuffix /demo.cast, $(EXAMPLES))
|
||||
|
||||
all: $(CASTS)
|
||||
|
|
|
@ -1,129 +1,84 @@
|
|||
{"version": 2, "width": 48, "height": 12, "timestamp": 1663712361, "env": {"SHELL": "/usr/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.008114, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[0.00852, "o", "bash >> "]
|
||||
[0.008755, "o", "m"]
|
||||
[0.189398, "o", "a"]
|
||||
[0.279744, "o", "k"]
|
||||
[0.369775, "o", "e"]
|
||||
[0.459919, "o", " -"]
|
||||
[0.549908, "o", "f"]
|
||||
[0.639982, "o", " "]
|
||||
[0.730339, "o", "c"]
|
||||
[0.820338, "o", "h"]
|
||||
[0.910414, "o", "ec"]
|
||||
[1.090651, "o", "k"]
|
||||
[1.18077, "o", "/"]
|
||||
[1.271098, "o", "c"]
|
||||
[1.361098, "o", "h"]
|
||||
[1.451216, "o", "ec"]
|
||||
[1.541276, "o", "k"]
|
||||
[1.631388, "o", "."]
|
||||
[1.721603, "o", "m"]
|
||||
[1.811718, "o", "k"]
|
||||
[1.992079, "o", " h"]
|
||||
[2.082138, "o", "e"]
|
||||
[2.172379, "o", "l"]
|
||||
[2.262403, "o", "p"]
|
||||
[2.352473, "o", "\r\n"]
|
||||
[3.381969, "o", "\u001b[1;36musage:\u001b[0m\r\n\tmake <recipe>\r\n\t\r\n\tinteractivity w/ task.mk\r\n\r\n\u001b[1;33m check\u001b[0m │ \u001b[2mget user confirmation or exit\u001b[0m\r\n\u001b[1;33m h, help\u001b[0m │ \u001b[2mshow this help\u001b[0m\r\n\r\n"]
|
||||
[5.387545, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[5.387892, "o", "bash >> "]
|
||||
[5.390047, "o", "m"]
|
||||
[5.570645, "o", "a"]
|
||||
[5.660579, "o", "k"]
|
||||
[5.750852, "o", "e"]
|
||||
[5.841071, "o", " -"]
|
||||
[5.931225, "o", "f"]
|
||||
[6.021286, "o", " "]
|
||||
[6.111373, "o", "c"]
|
||||
[6.201586, "o", "h"]
|
||||
[6.291778, "o", "ec"]
|
||||
[6.472054, "o", "k"]
|
||||
[6.562124, "o", "/"]
|
||||
[6.652262, "o", "c"]
|
||||
[6.74248, "o", "h"]
|
||||
[6.832675, "o", "ec"]
|
||||
[6.922668, "o", "k"]
|
||||
[7.012809, "o", "."]
|
||||
[7.102973, "o", "m"]
|
||||
[7.193151, "o", "k"]
|
||||
[7.373458, "o", " c"]
|
||||
[7.463783, "o", "h"]
|
||||
[7.553761, "o", "e"]
|
||||
[7.643931, "o", "c"]
|
||||
[7.734197, "o", "k"]
|
||||
[7.824356, "o", "\r\n"]
|
||||
[8.857505, "o", "Would you like to proceed? \u001b[1;31m[Y/n]\u001b[0m "]
|
||||
[9.54018, "o", "y"]
|
||||
[9.595198, "o", "\r\n"]
|
||||
[9.598684, "o", "you said yes!\r\n"]
|
||||
[11.602689, "o", "#"]
|
||||
[11.783071, "o", " "]
|
||||
[11.873235, "o", "L"]
|
||||
[11.963465, "o", "e"]
|
||||
[12.053444, "o", "t'"]
|
||||
[12.143548, "o", "s"]
|
||||
[12.233881, "o", " "]
|
||||
[12.323915, "o", "t"]
|
||||
[12.41414, "o", "r"]
|
||||
[12.50428, "o", "y "]
|
||||
[12.684471, "o", "a"]
|
||||
[12.774773, "o", "g"]
|
||||
[12.864864, "o", "a"]
|
||||
[12.954989, "o", "i"]
|
||||
[13.045011, "o", "n "]
|
||||
[13.135204, "o", "b"]
|
||||
[13.225451, "o", "u"]
|
||||
[13.315649, "o", "t"]
|
||||
[13.405687, "o", " "]
|
||||
[13.585943, "o", "in"]
|
||||
[13.676051, "o", "s"]
|
||||
[13.766346, "o", "t"]
|
||||
[13.856324, "o", "e"]
|
||||
[13.946542, "o", "a"]
|
||||
[14.036697, "o", "d "]
|
||||
[14.126782, "o", "s"]
|
||||
[14.216944, "o", "a"]
|
||||
[14.307128, "o", "y"]
|
||||
[14.487468, "o", " "]
|
||||
[14.577551, "o", "no"]
|
||||
[14.667739, "o", " "]
|
||||
[14.757899, "o", "t"]
|
||||
[14.848007, "o", "h"]
|
||||
[14.93806, "o", "i"]
|
||||
[15.0283, "o", "s "]
|
||||
[15.118379, "o", "t"]
|
||||
[15.208471, "o", "i"]
|
||||
[15.388757, "o", "m"]
|
||||
[15.47897, "o", "e"]
|
||||
[15.569031, "o", "\r\n"]
|
||||
[16.571969, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[16.572047, "o", "bash >> "]
|
||||
[16.574017, "o", "m"]
|
||||
[16.754499, "o", "a"]
|
||||
[16.844612, "o", "k"]
|
||||
[16.93468, "o", "e"]
|
||||
[17.024972, "o", " -"]
|
||||
[17.115137, "o", "f"]
|
||||
[17.205244, "o", " "]
|
||||
[17.295415, "o", "c"]
|
||||
[17.385554, "o", "h"]
|
||||
[17.475882, "o", "ec"]
|
||||
[17.655989, "o", "k"]
|
||||
[17.746279, "o", "/"]
|
||||
[17.83643, "o", "c"]
|
||||
[17.926644, "o", "h"]
|
||||
[18.016673, "o", "ec"]
|
||||
[18.106718, "o", "k"]
|
||||
[18.197045, "o", "."]
|
||||
[18.287031, "o", "m"]
|
||||
[18.377151, "o", "k"]
|
||||
[18.55735, "o", " c"]
|
||||
[18.647478, "o", "h"]
|
||||
[18.737616, "o", "e"]
|
||||
[18.827879, "o", "c"]
|
||||
[18.917992, "o", "k"]
|
||||
[19.008133, "o", "\r\n"]
|
||||
[20.034923, "o", "Would you like to proceed? \u001b[1;31m[Y/n]\u001b[0m "]
|
||||
[22.08808, "o", "n"]
|
||||
[22.227223, "o", "\r\n"]
|
||||
{"version": 2, "width": 48, "height": 12, "timestamp": 1664060067, "env": {"SHELL": "/usr/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.008028, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[0.008412, "o", "bash >> "]
|
||||
[0.008649, "o", "ma"]
|
||||
[0.189116, "o", "ke"]
|
||||
[0.279092, "o", " -"]
|
||||
[0.369181, "o", "f "]
|
||||
[0.459296, "o", "ch"]
|
||||
[0.549434, "o", "ec"]
|
||||
[0.639704, "o", "k/"]
|
||||
[0.729786, "o", "ch"]
|
||||
[0.81994, "o", "ec"]
|
||||
[0.910178, "o", "k."]
|
||||
[1.090415, "o", "mk"]
|
||||
[1.180666, "o", " h"]
|
||||
[1.270767, "o", "el"]
|
||||
[1.360807, "o", "p\r\n"]
|
||||
[2.392643, "o", "\u001b[1;36musage:\u001b[0m\r\n\tmake <recipe>\r\n\t\r\n\tinteractivity w/ task.mk\r\n\r\n\u001b[1;33m check\u001b[0m │ \u001b[2mget user confirmation or exit\u001b[0m\r\n\u001b[1;33m h, help\u001b[0m │ \u001b[2mshow this help\u001b[0m\r\n\r\n"]
|
||||
[4.398843, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[4.398948, "o", "bash >> "]
|
||||
[4.399576, "o", "ma"]
|
||||
[4.580421, "o", "ke"]
|
||||
[4.670533, "o", " -"]
|
||||
[4.760674, "o", "f "]
|
||||
[4.850908, "o", "ch"]
|
||||
[4.940859, "o", "ec"]
|
||||
[5.031095, "o", "k/"]
|
||||
[5.121228, "o", "ch"]
|
||||
[5.211271, "o", "ec"]
|
||||
[5.301383, "o", "k."]
|
||||
[5.481587, "o", "mk"]
|
||||
[5.571714, "o", " c"]
|
||||
[5.662002, "o", "he"]
|
||||
[5.752104, "o", "ck"]
|
||||
[5.842305, "o", "\r\n"]
|
||||
[6.864798, "o", "Would you like to proceed? \u001b[1;31m[Y/n]\u001b[0m "]
|
||||
[7.488194, "o", "y"]
|
||||
[7.830894, "o", "\r\n"]
|
||||
[7.836313, "o", "you said yes!\r\n"]
|
||||
[9.840217, "o", "# "]
|
||||
[10.020704, "o", "Le"]
|
||||
[10.110897, "o", "t'"]
|
||||
[10.201077, "o", "s "]
|
||||
[10.291171, "o", "tr"]
|
||||
[10.381382, "o", "y "]
|
||||
[10.471532, "o", "ag"]
|
||||
[10.5617, "o", "ai"]
|
||||
[10.651984, "o", "n "]
|
||||
[10.742177, "o", "bu"]
|
||||
[10.922348, "o", "t "]
|
||||
[11.012569, "o", "in"]
|
||||
[11.102605, "o", "st"]
|
||||
[11.192785, "o", "ea"]
|
||||
[11.282913, "o", "d "]
|
||||
[11.373109, "o", "sa"]
|
||||
[11.463146, "o", "y "]
|
||||
[11.553266, "o", "no"]
|
||||
[11.6436, "o", " t"]
|
||||
[11.823731, "o", "hi"]
|
||||
[11.913841, "o", "s "]
|
||||
[12.003886, "o", "ti"]
|
||||
[12.094101, "o", "me"]
|
||||
[12.184197, "o", "\r\n"]
|
||||
[13.185929, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[13.185977, "o", "bash >> "]
|
||||
[13.186676, "o", "ma"]
|
||||
[13.367108, "o", "ke"]
|
||||
[13.457234, "o", " -"]
|
||||
[13.547276, "o", "f "]
|
||||
[13.637696, "o", "ch"]
|
||||
[13.727919, "o", "ec"]
|
||||
[13.817921, "o", "k/"]
|
||||
[13.908217, "o", "ch"]
|
||||
[13.998375, "o", "ec"]
|
||||
[14.08855, "o", "k."]
|
||||
[14.268802, "o", "mk"]
|
||||
[14.359106, "o", " c"]
|
||||
[14.449085, "o", "he"]
|
||||
[14.539194, "o", "ck"]
|
||||
[14.629387, "o", "\r\n"]
|
||||
[15.652945, "o", "Would you like to proceed? \u001b[1;31m[Y/n]\u001b[0m "]
|
||||
[16.544875, "o", "n"]
|
||||
[17.098374, "o", "\r\n"]
|
||||
[17.103306, "o", "make[1]: *** [check/check.mk:4: check] Error 1\r\n"]
|
||||
|
|
|
@ -1,126 +1,83 @@
|
|||
{"version": 2, "width": 60, "height": 20, "timestamp": 1663712193, "env": {"SHELL": "/usr/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.008386, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[0.008986, "o", "bash >> "]
|
||||
[0.009151, "o", "m"]
|
||||
[0.189701, "o", "a"]
|
||||
[0.280162, "o", "k"]
|
||||
[0.37038, "o", "e"]
|
||||
[0.460683, "o", " -"]
|
||||
[0.551001, "o", "f"]
|
||||
[0.641267, "o", " "]
|
||||
[0.731609, "o", "e"]
|
||||
[0.821777, "o", "m"]
|
||||
[0.912103, "o", "be"]
|
||||
[1.092658, "o", "d"]
|
||||
[1.182705, "o", "d"]
|
||||
[1.273152, "o", "e"]
|
||||
[1.363457, "o", "d"]
|
||||
[1.453758, "o", "/e"]
|
||||
[1.544059, "o", "m"]
|
||||
[1.634282, "o", "b"]
|
||||
[1.724452, "o", "e"]
|
||||
[1.814601, "o", "d"]
|
||||
[1.995155, "o", "de"]
|
||||
[2.085437, "o", "d"]
|
||||
[2.175546, "o", "."]
|
||||
[2.265856, "o", "m"]
|
||||
[2.356192, "o", "k"]
|
||||
[2.446468, "o", " h"]
|
||||
[2.536781, "o", "e"]
|
||||
[2.627101, "o", "l"]
|
||||
[2.717423, "o", "p"]
|
||||
[2.897934, "o", "\r\n"]
|
||||
[3.931131, "o", "\u001b[1;36musage:\u001b[0m\r\n\tmake <recipe>\r\n\t\r\n\texamples of embedded scripts in `\u001b[35mMakefile\u001b[0m`\r\n\r\n \u001b[1;31m examples of task.mk features \u001b[0m\r\n\u001b[38m ─────────────────────────────────────────────────────\u001b[0m\r\n\u001b[1;33m list-%\u001b[0m │ \u001b[2muse pathlib.Path to list files\u001b[0m\r\n \u001b[2mname the directory in rule (make list-src)\u001b[0m\r\n\u001b[1;33m embedded-bash\u001b[0m │ \u001b[2mbash script with pipes and make input\u001b[0m\r\n\u001b[1;33m h, help\u001b[0m │ \u001b[2mshow this help\u001b[0m\r\n\r\n"]
|
||||
[5.936874, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[5.937167, "o", "bash >> "]
|
||||
[5.939502, "o", "m"]
|
||||
[6.120169, "o", "a"]
|
||||
[6.210505, "o", "k"]
|
||||
[6.300671, "o", "e"]
|
||||
[6.390788, "o", " -"]
|
||||
[6.480981, "o", "f"]
|
||||
[6.571285, "o", " "]
|
||||
[6.661457, "o", "e"]
|
||||
[6.751758, "o", "m"]
|
||||
[6.842048, "o", "be"]
|
||||
[7.022576, "o", "d"]
|
||||
[7.112852, "o", "d"]
|
||||
[7.203064, "o", "e"]
|
||||
[7.293421, "o", "d"]
|
||||
[7.383397, "o", "/e"]
|
||||
[7.473873, "o", "m"]
|
||||
[7.564152, "o", "b"]
|
||||
[7.65431, "o", "e"]
|
||||
[7.744607, "o", "d"]
|
||||
[7.925168, "o", "de"]
|
||||
[8.015472, "o", "d"]
|
||||
[8.105767, "o", "."]
|
||||
[8.195936, "o", "m"]
|
||||
[8.286184, "o", "k"]
|
||||
[8.376537, "o", " l"]
|
||||
[8.466624, "o", "i"]
|
||||
[8.557058, "o", "s"]
|
||||
[8.64739, "o", "t"]
|
||||
[8.827942, "o", "-"]
|
||||
[8.91803, "o", "em"]
|
||||
[9.008446, "o", "b"]
|
||||
[9.098742, "o", "e"]
|
||||
[9.189059, "o", "d"]
|
||||
[9.279328, "o", "d"]
|
||||
[9.36965, "o", "ed"]
|
||||
[9.459574, "o", "\r\n"]
|
||||
[10.492826, "o", "files in embedded\r\n"]
|
||||
[10.492943, "o", "['embedded.mk', 'demo.cast', 'record.sh', 'index.md']\r\n"]
|
||||
[12.498865, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[12.498984, "o", "bash >> "]
|
||||
[12.501382, "o", "m"]
|
||||
[12.681906, "o", "a"]
|
||||
[12.7722, "o", "k"]
|
||||
[12.862501, "o", "e"]
|
||||
[12.952783, "o", " -"]
|
||||
[13.043086, "o", "f"]
|
||||
[13.13339, "o", " "]
|
||||
[13.223546, "o", "e"]
|
||||
[13.313887, "o", "m"]
|
||||
[13.40413, "o", "be"]
|
||||
[13.584464, "o", "d"]
|
||||
[13.674721, "o", "d"]
|
||||
[13.764931, "o", "e"]
|
||||
[13.855143, "o", "d"]
|
||||
[13.945476, "o", "/e"]
|
||||
[14.035801, "o", "m"]
|
||||
[14.126086, "o", "b"]
|
||||
[14.216402, "o", "e"]
|
||||
[14.306688, "o", "d"]
|
||||
[14.487263, "o", "de"]
|
||||
[14.577566, "o", "d"]
|
||||
[14.667572, "o", "."]
|
||||
[14.757974, "o", "m"]
|
||||
[14.848201, "o", "k"]
|
||||
[14.938383, "o", " e"]
|
||||
[15.02867, "o", "m"]
|
||||
[15.118961, "o", "b"]
|
||||
[15.2091, "o", "e"]
|
||||
[15.38968, "o", "d"]
|
||||
[15.479924, "o", "de"]
|
||||
[15.570276, "o", "d"]
|
||||
[15.66027, "o", "-"]
|
||||
[15.750729, "o", "b"]
|
||||
[15.84091, "o", "a"]
|
||||
[15.931277, "o", "sh"]
|
||||
[16.021429, "o", "\r\n"]
|
||||
[17.044626, "o", "Is the process running bash? We can check with ps\r\n"]
|
||||
[17.063304, "o", "bash\r\n"]
|
||||
[17.063756, "o", "What text to figlet? \r\n"]
|
||||
[20.107984, "o", "t"]
|
||||
[20.125262, "o", "a"]
|
||||
[20.276406, "o", "s"]
|
||||
[20.454083, "o", "k"]
|
||||
[20.705234, "o", "."]
|
||||
[20.931947, "o", "m"]
|
||||
[21.010096, "o", "k"]
|
||||
[21.288327, "o", "\r\n"]
|
||||
[21.292384, "o", " _ _ _ \r\n| |_ __ _ ___| | __ _ __ ___ | | __\r\n| __/ _` / __| |/ / | '_ ` _ \\| |/ /\r\n| || (_| \\__ \\ < _| | | | | | < \r\n \\__\\__,_|___/_|\\_(_)_| |_| |_|_|\\_\\\r\n \r\n"]
|
||||
[21.292754, "o", "the argument below as given in the makefile itself\r\n"]
|
||||
[21.292898, "o", "it's expanded before the script is passed to bash\r\n"]
|
||||
[21.292925, "o", "bash multiline is probably working\r\n"]
|
||||
{"version": 2, "width": 60, "height": 20, "timestamp": 1664060088, "env": {"SHELL": "/usr/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.008131, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[0.008522, "o", "bash >> "]
|
||||
[0.008683, "o", "ma"]
|
||||
[0.189166, "o", "ke"]
|
||||
[0.279481, "o", " -"]
|
||||
[0.369776, "o", "f "]
|
||||
[0.460021, "o", "em"]
|
||||
[0.550229, "o", "be"]
|
||||
[0.640359, "o", "dd"]
|
||||
[0.730591, "o", "ed"]
|
||||
[0.820572, "o", "/e"]
|
||||
[0.910745, "o", "mb"]
|
||||
[1.091087, "o", "ed"]
|
||||
[1.181312, "o", "de"]
|
||||
[1.271441, "o", "d."]
|
||||
[1.361501, "o", "mk"]
|
||||
[1.451615, "o", " h"]
|
||||
[1.541783, "o", "el"]
|
||||
[1.63204, "o", "p\r\n"]
|
||||
[2.664242, "o", "\u001b[1;36musage:\u001b[0m\r\n\tmake <recipe>\r\n\t\r\n\texamples of embedded scripts in `\u001b[35mMakefile\u001b[0m`\r\n\r\n \u001b[1;31m examples of task.mk features \u001b[0m\r\n\u001b[38m ─────────────────────────────────────────────────────\u001b[0m\r\n\u001b[1;33m list-%\u001b[0m │ \u001b[2muse pathlib.Path to list files\u001b[0m\r\n \u001b[2mname the directory in rule (make list-src)\u001b[0m\r\n\u001b[1;33m embedded-bash\u001b[0m │ \u001b[2mbash script with pipes and make input\u001b[0m\r\n\u001b[1;33m h, help\u001b[0m │ \u001b[2mshow this help\u001b[0m\r\n\r\n"]
|
||||
[4.671801, "o", "\u001b[H\u001b[2J\u001b[3Jbash >> "]
|
||||
[4.67392, "o", "ma"]
|
||||
[4.854455, "o", "ke"]
|
||||
[4.944728, "o", " -"]
|
||||
[5.034921, "o", "f "]
|
||||
[5.124982, "o", "em"]
|
||||
[5.215103, "o", "be"]
|
||||
[5.305188, "o", "dd"]
|
||||
[5.395353, "o", "ed"]
|
||||
[5.485457, "o", "/e"]
|
||||
[5.576246, "o", "mb"]
|
||||
[5.75589, "o", "ed"]
|
||||
[5.846014, "o", "de"]
|
||||
[5.93612, "o", "d."]
|
||||
[6.026298, "o", "mk"]
|
||||
[6.11644, "o", " l"]
|
||||
[6.206464, "o", "is"]
|
||||
[6.296631, "o", "t-"]
|
||||
[6.386781, "o", "em"]
|
||||
[6.477052, "o", "be"]
|
||||
[6.657201, "o", "dd"]
|
||||
[6.747412, "o", "ed"]
|
||||
[6.837566, "o", "\r\n"]
|
||||
[7.867599, "o", "files in embedded\r\n['embedded.mk', 'demo.cast', 'record.sh', 'index.md']\r\n"]
|
||||
[9.872436, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[9.872754, "o", "bash >> "]
|
||||
[9.874651, "o", "ma"]
|
||||
[10.055031, "o", "ke"]
|
||||
[10.145171, "o", " -"]
|
||||
[10.235256, "o", "f "]
|
||||
[10.325347, "o", "em"]
|
||||
[10.415525, "o", "be"]
|
||||
[10.505721, "o", "dd"]
|
||||
[10.595814, "o", "ed"]
|
||||
[10.685931, "o", "/e"]
|
||||
[10.776068, "o", "mb"]
|
||||
[10.956362, "o", "ed"]
|
||||
[11.046547, "o", "de"]
|
||||
[11.136692, "o", "d."]
|
||||
[11.226851, "o", "mk"]
|
||||
[11.316894, "o", " e"]
|
||||
[11.406996, "o", "mb"]
|
||||
[11.497205, "o", "ed"]
|
||||
[11.58725, "o", "de"]
|
||||
[11.677471, "o", "d-"]
|
||||
[11.85761, "o", "ba"]
|
||||
[11.947917, "o", "sh"]
|
||||
[12.038071, "o", "\r\n"]
|
||||
[13.045213, "o", "Is the process running bash? We can check with ps\r\n"]
|
||||
[13.051057, "o", "bash\r\n"]
|
||||
[13.051385, "o", "What text to figlet? \r\n"]
|
||||
[14.434504, "o", "t"]
|
||||
[14.503239, "o", "a"]
|
||||
[14.605384, "o", "s"]
|
||||
[14.745978, "o", "k"]
|
||||
[14.946139, "o", "."]
|
||||
[15.080651, "o", "m"]
|
||||
[15.228545, "o", "k"]
|
||||
[15.617669, "o", "\r\n"]
|
||||
[15.618495, "o", " _ _ _ \r\n| |_ __ _ ___| | __ _ __ ___ | | __\r\n| __/ _` / __| |/ / | '_ ` _ \\| |/ /\r\n| || (_| \\__ \\ < _| | | | | | < \r\n \\__\\__,_|___/_|\\_(_)_| |_| |_|_|\\_\\\r\n \r\n"]
|
||||
[15.618636, "o", "the argument below as given in the makefile itself\r\n"]
|
||||
[15.618695, "o", "it's expanded before the script is passed to bash\r\nbash multiline is probably working\r\n"]
|
||||
|
|
|
@ -5,4 +5,5 @@ source "$(dirname "${BASH_SOURCE[0]}")/../functions.sh"
|
|||
cmd 'make -f embedded/embedded.mk help'
|
||||
cmd 'make -f embedded/embedded.mk list-embedded'
|
||||
cmd 'make -f embedded/embedded.mk embedded-bash'
|
||||
sleep 1
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
msg() {
|
||||
printf '%s\n' "$1" | pv -qL 12
|
||||
printf '%s\n' "$1" | pv -qL 20
|
||||
sleep 1
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
# Examples
|
||||
|
||||
|
||||
[`Check`](./check)
|
||||
[Confirm](./check)
|
||||
|
||||
: 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`
|
||||
|
||||
[Recipe Help](./recipe-help)
|
||||
|
||||
: Display the target, docstring and recipe for a given target then exit.
|
||||
|
|
138
docs/examples/recipe-help/demo.cast
Normal file
138
docs/examples/recipe-help/demo.cast
Normal file
|
@ -0,0 +1,138 @@
|
|||
{"version": 2, "width": 60, "height": 20, "timestamp": 1664060106, "env": {"SHELL": "/usr/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[0.007806, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[0.008354, "o", "bash >> "]
|
||||
[0.008532, "o", "ma"]
|
||||
[0.189207, "o", "ke"]
|
||||
[0.279458, "o", " -"]
|
||||
[0.369697, "o", "f "]
|
||||
[0.459892, "o", "re"]
|
||||
[0.550111, "o", "ci"]
|
||||
[0.640099, "o", "pe"]
|
||||
[0.730309, "o", "-h"]
|
||||
[0.820408, "o", "el"]
|
||||
[0.910572, "o", "p/"]
|
||||
[1.090837, "o", "re"]
|
||||
[1.180944, "o", "ci"]
|
||||
[1.271024, "o", "pe"]
|
||||
[1.36131, "o", "-h"]
|
||||
[1.451464, "o", "el"]
|
||||
[1.541712, "o", "p."]
|
||||
[1.631676, "o", "mk"]
|
||||
[1.721815, "o", " h"]
|
||||
[1.812133, "o", "el"]
|
||||
[1.99248, "o", "p\r\n"]
|
||||
[3.025715, "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.032814, "o", "\u001b[H\u001b[2J\u001b[3Jbash >> "]
|
||||
[5.034705, "o", "ma"]
|
||||
[5.215256, "o", "ke"]
|
||||
[5.305482, "o", " -"]
|
||||
[5.395504, "o", "f "]
|
||||
[5.485805, "o", "re"]
|
||||
[5.576036, "o", "ci"]
|
||||
[5.666095, "o", "pe"]
|
||||
[5.756177, "o", "-h"]
|
||||
[5.846563, "o", "el"]
|
||||
[5.93671, "o", "p/"]
|
||||
[6.11689, "o", "re"]
|
||||
[6.206935, "o", "ci"]
|
||||
[6.297128, "o", "pe"]
|
||||
[6.387205, "o", "-h"]
|
||||
[6.477454, "o", "el"]
|
||||
[6.567496, "o", "p."]
|
||||
[6.657713, "o", "mk"]
|
||||
[6.747729, "o", " h"]
|
||||
[6.838006, "o", "el"]
|
||||
[7.018242, "o", "p "]
|
||||
[7.108261, "o", "he"]
|
||||
[7.198405, "o", "lp"]
|
||||
[7.288809, "o", "\r\n"]
|
||||
[8.318829, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
|
||||
[8.325694, "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.329695, "o", "exiting early!\r\nmake[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
|
||||
[10.332715, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[10.333056, "o", "bash >> "]
|
||||
[10.335005, "o", "ma"]
|
||||
[10.515605, "o", "ke"]
|
||||
[10.605896, "o", " -"]
|
||||
[10.696226, "o", "f "]
|
||||
[10.78629, "o", "re"]
|
||||
[10.876669, "o", "ci"]
|
||||
[10.966704, "o", "pe"]
|
||||
[11.056858, "o", "-h"]
|
||||
[11.146831, "o", "el"]
|
||||
[11.236969, "o", "p/"]
|
||||
[11.417281, "o", "re"]
|
||||
[11.507468, "o", "ci"]
|
||||
[11.597442, "o", "pe"]
|
||||
[11.687589, "o", "-h"]
|
||||
[11.777832, "o", "el"]
|
||||
[11.867969, "o", "p."]
|
||||
[11.958105, "o", "mk"]
|
||||
[12.048177, "o", " h"]
|
||||
[12.138291, "o", "el"]
|
||||
[12.318676, "o", "p "]
|
||||
[12.408796, "o", "de"]
|
||||
[12.498823, "o", "ps"]
|
||||
[12.588985, "o", "-o"]
|
||||
[12.679133, "o", "nl"]
|
||||
[12.769237, "o", "y\r\n"]
|
||||
[13.807661, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
|
||||
[13.816448, "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.820255, "o", "exiting early!\r\n"]
|
||||
[13.820461, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
|
||||
[15.823763, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[15.824036, "o", "bash >> "]
|
||||
[15.826016, "o", "ma"]
|
||||
[16.006673, "o", "ke"]
|
||||
[16.09685, "o", " -"]
|
||||
[16.186936, "o", "f "]
|
||||
[16.277228, "o", "re"]
|
||||
[16.367339, "o", "ci"]
|
||||
[16.45744, "o", "pe"]
|
||||
[16.547483, "o", "-h"]
|
||||
[16.637622, "o", "el"]
|
||||
[16.727742, "o", "p/"]
|
||||
[16.907989, "o", "re"]
|
||||
[16.99817, "o", "ci"]
|
||||
[17.088391, "o", "pe"]
|
||||
[17.178352, "o", "-h"]
|
||||
[17.268476, "o", "el"]
|
||||
[17.358766, "o", "p."]
|
||||
[17.448842, "o", "mk"]
|
||||
[17.539039, "o", " h"]
|
||||
[17.629197, "o", "el"]
|
||||
[17.809354, "o", "p "]
|
||||
[17.899578, "o", "fo"]
|
||||
[17.989694, "o", "o\r\n"]
|
||||
[19.020047, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
|
||||
[19.03039, "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.035496, "o", "exiting early!\r\n"]
|
||||
[19.035706, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
|
||||
[21.039168, "o", "\u001b[H\u001b[2J\u001b[3J"]
|
||||
[21.03927, "o", "bash >> "]
|
||||
[21.041378, "o", "ma"]
|
||||
[21.221916, "o", "ke"]
|
||||
[21.31205, "o", " -"]
|
||||
[21.402214, "o", "f "]
|
||||
[21.492482, "o", "re"]
|
||||
[21.582638, "o", "ci"]
|
||||
[21.672609, "o", "pe"]
|
||||
[21.762748, "o", "-h"]
|
||||
[21.853045, "o", "el"]
|
||||
[21.943154, "o", "p/"]
|
||||
[22.123286, "o", "re"]
|
||||
[22.2134, "o", "ci"]
|
||||
[22.303509, "o", "pe"]
|
||||
[22.393685, "o", "-h"]
|
||||
[22.483815, "o", "el"]
|
||||
[22.574005, "o", "p."]
|
||||
[22.664056, "o", "mk"]
|
||||
[22.754229, "o", " h"]
|
||||
[22.844432, "o", "el"]
|
||||
[23.02464, "o", "p "]
|
||||
[23.114692, "o", "ba"]
|
||||
[23.205123, "o", "r\r\n"]
|
||||
[24.260098, "o", "\u001b[1;36mtask.mk recipe help\u001b[0m\r\n\r\n"]
|
||||
[24.267129, "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.271004, "o", "exiting early!\r\n"]
|
||||
[24.271137, "o", "make[1]: *** [/home/daylin/dev/github/mine/task.mk/task.mk:30: help] Error 1\r\n"]
|
12
docs/examples/recipe-help/index.md
Normal file
12
docs/examples/recipe-help/index.md
Normal 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"
|
||||
```
|
||||
|
24
docs/examples/recipe-help/recipe-help.mk
Normal file
24
docs/examples/recipe-help/recipe-help.mk
Normal 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
|
||||
|
11
docs/examples/recipe-help/record.sh
Executable file
11
docs/examples/recipe-help/record.sh
Executable 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
|
|
@ -4,7 +4,14 @@ import sys
|
|||
from pathlib import Path
|
||||
import jinja2
|
||||
|
||||
py_script_names = ["help", "ansi", "info", "print-ansi", "vars", "confirm"]
|
||||
py_script_names = [
|
||||
"help",
|
||||
"info",
|
||||
"print-ansi",
|
||||
"vars",
|
||||
"confirm",
|
||||
"utils",
|
||||
]
|
||||
|
||||
|
||||
def get_jinja_env():
|
||||
|
|
|
@ -4,17 +4,8 @@ ifeq (help,$(firstword $(MAKECMDGOALS)))
|
|||
export HELP_ARGS
|
||||
endif
|
||||
## h, help | show this help
|
||||
ifdef HELP_ARGS
|
||||
help: help-args
|
||||
$(error exiting early)
|
||||
.PHONY: help-args
|
||||
help-args:
|
||||
$(call py,help_py)
|
||||
else
|
||||
.PHONY: help h
|
||||
h help:
|
||||
$(call py,help_py)
|
||||
endif
|
||||
$(call py,help_py) || { echo "exiting early!"; exit 1; }
|
||||
.PHONY: _help
|
||||
_help: export SHOW_HIDDEN=true
|
||||
_help: help
|
||||
|
@ -38,7 +29,8 @@ tconfirm = $(call py,confirm_py,$(1))
|
|||
_update-task.mk:
|
||||
$(call tprint,{a.b_cyan}Updating task.mk{a.end})
|
||||
curl https://raw.githubusercontent.com/daylinmorgan/task.mk/main/task.mk -o .task.mk
|
||||
export MAKEFILE_LIST
|
||||
TASK_MAKEFILE_LIST := $(filter-out $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)),$(MAKEFILE_LIST))
|
||||
export MAKEFILE_LIST MAKE TASK_MAKEFILE_LIST
|
||||
ifndef INHERIT_SHELL
|
||||
SHELL := $(shell which bash)
|
||||
endif
|
||||
|
|
|
@ -4,10 +4,11 @@ ACCENT_STYLE ?= b_yellow
|
|||
PARAMS_STYLE ?= $(ACCENT_STYLE)
|
||||
GOAL_STYLE ?= $(ACCENT_STYLE)
|
||||
MSG_STYLE ?= faint
|
||||
DIVIDER_STYLE ?= default
|
||||
DIVIDER ?= ─
|
||||
DIVIDER_STYLE ?= default
|
||||
HELP_SEP ?= │
|
||||
WRAP ?= 100
|
||||
# python f-string literals
|
||||
EPILOG ?=
|
||||
USAGE ?={ansi.$(HEADER_STYLE)}usage{ansi.end}:\n make <recipe>\n
|
||||
USAGE ?={ansi.header}usage{ansi.end}:\n make <recipe>\n
|
||||
INHERIT_SHELL ?=
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
import sys
|
||||
|
||||
##- '$(ansi_py)' -##
|
||||
##- '$(utils_py)' -##
|
||||
|
||||
|
||||
def confirm():
|
||||
|
|
78
src/help.py
78
src/help.py
|
@ -5,8 +5,16 @@ import argparse
|
|||
from collections import namedtuple
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from textwrap import wrap
|
||||
|
||||
##- '$(utils_py)' -##
|
||||
###-
|
||||
# this is just to trick the LSP during development
|
||||
from utils import ansi, cfg
|
||||
# -###
|
||||
|
||||
##- '$(ansi_py)' -##
|
||||
|
||||
MaxLens = namedtuple("MaxLens", "goal msg")
|
||||
|
||||
|
@ -28,9 +36,13 @@ def parseargs(argstring):
|
|||
return parser.parse_args(argstring.split())
|
||||
|
||||
|
||||
def divider(len):
|
||||
return ansi.style(f" {cfg.div*len}", "div_style")
|
||||
|
||||
|
||||
def gen_makefile():
|
||||
makefile = ""
|
||||
for file in os.getenv("MAKEFILE_LIST").split():
|
||||
for file in os.getenv("MAKEFILE_LIST", "").split():
|
||||
with open(file, "r") as f:
|
||||
makefile += f.read() + "\n\n"
|
||||
return makefile
|
||||
|
@ -64,35 +76,61 @@ def recipe_help_header(goal):
|
|||
item[0].get("msgargs", ""),
|
||||
)
|
||||
else:
|
||||
return f" {ansi.style(goal,'$(GOAL_STYLE)')}:"
|
||||
return f" {ansi.style(goal,'goal')}"
|
||||
|
||||
|
||||
def get_goal_deps(goal="task.mk"):
|
||||
make = os.getenv("MAKE", "make")
|
||||
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 + ":(.*)?")
|
||||
for line in database.splitlines():
|
||||
match = dep_pattern.search(line)
|
||||
if match and match.groups()[0]:
|
||||
return wrap(
|
||||
f"{ansi.style('deps','default')}: {ansi.style(match.groups()[0].strip(),'msg')}",
|
||||
width=cfg.wrap,
|
||||
initial_indent=" ",
|
||||
subsequent_indent=" ",
|
||||
)
|
||||
|
||||
|
||||
def parse_goal(file, goal):
|
||||
goals = goal_pattern.findall(file)
|
||||
matched_goal = [i for i in goals if goal in i.split()]
|
||||
output = []
|
||||
|
||||
if matched_goal:
|
||||
output.append(recipe_help_header(matched_goal[0]))
|
||||
deps = get_goal_deps(matched_goal[0])
|
||||
if deps:
|
||||
output.extend(deps)
|
||||
lines = file.splitlines()
|
||||
loc = [n for n, l in enumerate(lines) if l.startswith(f"{matched_goal[0]}:")][0]
|
||||
recipe = []
|
||||
|
||||
for line in lines[loc + 1 :]:
|
||||
if not line.startswith("\t"):
|
||||
break
|
||||
recipe.append(line)
|
||||
output.append(divider(max((len(l) for l in recipe)) + 5))
|
||||
output.append("\n".join(recipe) + "\n")
|
||||
recipe.append(f" {line.strip()}")
|
||||
output.append(divider(max((len(l.strip()) for l in recipe))))
|
||||
output.append("\n".join(recipe))
|
||||
else:
|
||||
output.append(f"{ansi.b_red}ERROR{ansi.end} Failed to find goal: {goal}")
|
||||
deps = get_goal_deps(goal)
|
||||
if deps:
|
||||
output.append(recipe_help_header(goal))
|
||||
output.extend(deps)
|
||||
|
||||
if not output:
|
||||
output.append(f"{ansi.style('ERROR','b_red')}: Failed to find goal: {goal}")
|
||||
return output
|
||||
|
||||
|
||||
def fmt_goal(goal, msg, max_goal_len, argstr):
|
||||
args = parseargs(argstr)
|
||||
goal_style = args.goal_style.strip() if args.goal_style else "$(GOAL_STYLE)"
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "$(MSG_STYLE)"
|
||||
goal_style = args.goal_style.strip() if args.goal_style else "goal"
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "msg"
|
||||
return (
|
||||
ansi.style(f" {goal:>{max_goal_len}}", goal_style)
|
||||
+ f" $(HELP_SEP) "
|
||||
|
@ -100,27 +138,23 @@ def fmt_goal(goal, msg, max_goal_len, argstr):
|
|||
)
|
||||
|
||||
|
||||
def divider(len):
|
||||
return ansi.style(f" {'$(DIVIDER)'*len}", "$(DIVIDER_STYLE)")
|
||||
|
||||
|
||||
def fmt_rawmsg(msg, argstr, maxlens):
|
||||
args = parseargs(argstr)
|
||||
lines = []
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "$(MSG_STYLE)"
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "msg"
|
||||
if not os.getenv("SHOW_HIDDEN") and args.hidden:
|
||||
return []
|
||||
if msg:
|
||||
if args.align == "sep":
|
||||
lines.append(
|
||||
f"{' '*(maxlens.goal+len('$(HELP_SEP)')+4)}{ansi.style(msg,msg_style)}"
|
||||
f"{' '*(maxlens.goal+len(cfg.sep)+4)}{ansi.style(msg,msg_style)}"
|
||||
)
|
||||
elif args.align == "center":
|
||||
lines.append(f" {ansi.style(msg.center(sum(maxlens)),msg_style)}")
|
||||
else:
|
||||
lines.append(f" {ansi.style(msg,msg_style)}")
|
||||
if args.divider:
|
||||
lines.append(divider(len("$(HELP_SEP)") + sum(maxlens) + 2))
|
||||
lines.append(divider(len(cfg.sep) + sum(maxlens) + 2))
|
||||
if args.whitespace:
|
||||
lines.append("\n")
|
||||
|
||||
|
@ -128,7 +162,7 @@ def fmt_rawmsg(msg, argstr, maxlens):
|
|||
|
||||
|
||||
def print_help():
|
||||
lines = [f"""$(USAGE)"""]
|
||||
lines = [cfg.usage]
|
||||
|
||||
items = list(parse_help(gen_makefile()))
|
||||
maxlens = MaxLens(
|
||||
|
@ -143,25 +177,27 @@ def print_help():
|
|||
)
|
||||
if "rawmsg" in item:
|
||||
lines.extend(fmt_rawmsg(item["rawmsg"], item.get("rawargs", ""), maxlens))
|
||||
lines.append(f"""$(EPILOG)""")
|
||||
lines.append(cfg.epilog)
|
||||
print("\n".join(lines))
|
||||
|
||||
|
||||
def print_arg_help(help_args):
|
||||
print(f"{ansi.style('task.mk recipe help','header')}\n")
|
||||
for arg in help_args.split():
|
||||
print(f"{ansi.style('task.mk recipe help','$(HEADER_STYLE)')}\n")
|
||||
print("\n".join(parse_goal(gen_makefile(), arg)))
|
||||
print()
|
||||
|
||||
|
||||
def main():
|
||||
help_args = os.getenv("HELP_ARGS")
|
||||
if help_args:
|
||||
print_arg_help(help_args)
|
||||
print(a.faint)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print_help()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
#% endblock %#
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#% extends "py-script.mk" %#
|
||||
#% block name %#info#% endblock %#
|
||||
#% block script %#
|
||||
##- '$(ansi_py)' -##
|
||||
##- '$(utils_py)' -##
|
||||
|
||||
print(f"""$(2)""")
|
||||
#% endblock %#
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#% extends "py-script.mk" %#
|
||||
#% block name %#print_ansi#% endblock %#
|
||||
#% block script %#
|
||||
##- '$(ansi_py)' -##
|
||||
##- '$(utils_py)' -##
|
||||
sep = f"$(HELP_SEP)"
|
||||
codes_names = {getattr(ansi, attr): attr for attr in ansi.__dict__}
|
||||
for code in sorted(codes_names.keys(), key=lambda item: (len(item), item)):
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
#% extends "py-script.mk" %#
|
||||
#% block name %#ansi#% endblock %#
|
||||
#% block name %#utils#% endblock %#
|
||||
#% block script %#
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Config:
|
||||
div: str
|
||||
sep: str
|
||||
epilog: str
|
||||
usage: str
|
||||
wrap: int
|
||||
|
||||
|
||||
color2byte = dict(
|
||||
black=0,
|
||||
|
@ -40,6 +51,7 @@ class Ansi:
|
|||
)
|
||||
for name, byte in state2byte.items():
|
||||
self.setcode(name, f"\033[{byte}m")
|
||||
self.add_cfg()
|
||||
|
||||
def setcode(self, name, escape_code):
|
||||
"""create attr for style and escape code"""
|
||||
|
@ -77,6 +89,18 @@ class Ansi:
|
|||
|
||||
return code + end
|
||||
|
||||
def add_cfg(self):
|
||||
cfg_styles = {
|
||||
"header": "$(HEADER_STYLE)",
|
||||
"accent": "$(ACCENT_STYLE)",
|
||||
"params": "$(PARAMS_STYLE)",
|
||||
"goal": "$(GOAL_STYLE)",
|
||||
"msg": "$(MSG_STYLE)",
|
||||
"div_style": "$(DIVIDER_STYLE)",
|
||||
}
|
||||
for name, style in cfg_styles.items():
|
||||
self.setcode(name, getattr(self, style))
|
||||
|
||||
def style(self, text, style):
|
||||
if style not in self.__dict__:
|
||||
print(f"unknown style: {style}")
|
||||
|
@ -86,4 +110,7 @@ class Ansi:
|
|||
|
||||
|
||||
a = ansi = Ansi()
|
||||
|
||||
cfg = Config(
|
||||
"$(DIVIDER)", "$(HELP_SEP)", f"""$(EPILOG)""", f"""$(USAGE)""",int('$(WRAP)'))
|
||||
#% endblock %#
|
|
@ -3,15 +3,15 @@
|
|||
#% block script %#
|
||||
import os
|
||||
|
||||
##- '$(ansi_py)' -##
|
||||
##- '$(utils_py)' -##
|
||||
|
||||
vars = "$2".split()
|
||||
length = max((len(v) for v in vars))
|
||||
|
||||
print(f"{ansi.$(HEADER_STYLE)}vars:{ansi.end}\n")
|
||||
print(f"{ansi.header}vars{ansi.end}:\n")
|
||||
|
||||
for v in vars:
|
||||
print(f" {ansi.b_magenta}{v:<{length}}{ansi.end} = {os.getenv(v)}")
|
||||
print(f" {ansi.params}{v:<{length}}{ansi.end} = {os.getenv(v)}")
|
||||
|
||||
print()
|
||||
#% endblock %#
|
||||
|
|
190
task.mk
190
task.mk
|
@ -1,7 +1,7 @@
|
|||
# }> [github.com/daylinmorgan/task.mk] <{ #
|
||||
# Copyright (c) 2022 Daylin Morgan
|
||||
# MIT License
|
||||
# version: v22.9.19-5-g5f593e3-dev
|
||||
# version: v22.9.19-20-g32110dd
|
||||
#
|
||||
# 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.
|
||||
|
@ -12,12 +12,13 @@ ACCENT_STYLE ?= b_yellow
|
|||
PARAMS_STYLE ?= $(ACCENT_STYLE)
|
||||
GOAL_STYLE ?= $(ACCENT_STYLE)
|
||||
MSG_STYLE ?= faint
|
||||
DIVIDER_STYLE ?= default
|
||||
DIVIDER ?= ─
|
||||
DIVIDER_STYLE ?= default
|
||||
HELP_SEP ?= │
|
||||
WRAP ?= 100
|
||||
# python f-string literals
|
||||
EPILOG ?=
|
||||
USAGE ?={ansi.$(HEADER_STYLE)}usage{ansi.end}:\n make <recipe>\n
|
||||
USAGE ?={ansi.header}usage{ansi.end}:\n make <recipe>\n
|
||||
INHERIT_SHELL ?=
|
||||
# ---- [builtin recipes] ---- #
|
||||
ifeq (help,$(firstword $(MAKECMDGOALS)))
|
||||
|
@ -25,9 +26,8 @@ ifeq (help,$(firstword $(MAKECMDGOALS)))
|
|||
export HELP_ARGS
|
||||
endif
|
||||
## h, help | show this help
|
||||
.PHONY: help h
|
||||
help h:
|
||||
$(call py,help_py)
|
||||
h help:
|
||||
$(call py,help_py) || { echo "exiting early!"; exit 1; }
|
||||
.PHONY: _help
|
||||
_help: export SHOW_HIDDEN=true
|
||||
_help: help
|
||||
|
@ -51,9 +51,10 @@ tconfirm = $(call py,confirm_py,$(1))
|
|||
_update-task.mk:
|
||||
$(call tprint,{a.b_cyan}Updating task.mk{a.end})
|
||||
curl https://raw.githubusercontent.com/daylinmorgan/task.mk/main/task.mk -o .task.mk
|
||||
export MAKEFILE_LIST
|
||||
TASK_MAKEFILE_LIST := $(filter-out $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)),$(MAKEFILE_LIST))
|
||||
export MAKEFILE_LIST MAKE TASK_MAKEFILE_LIST
|
||||
ifndef INHERIT_SHELL
|
||||
SHELL := /bin/bash
|
||||
SHELL := $(shell which bash)
|
||||
endif
|
||||
# ---- [python/bash script runner] ---- #
|
||||
define _newline
|
||||
|
@ -84,8 +85,10 @@ import argparse
|
|||
from collections import namedtuple
|
||||
import os
|
||||
import re
|
||||
$(ansi_py)
|
||||
$(quit_make_py)
|
||||
import subprocess
|
||||
import sys
|
||||
from textwrap import wrap
|
||||
$(utils_py)
|
||||
MaxLens = namedtuple("MaxLens", "goal msg")
|
||||
pattern = re.compile(
|
||||
r"^## (?P<goal>.*?) \| (?P<msg>.*?)(?:\s?\| args: (?P<msgargs>.*?))?$$|^### (?P<rawmsg>.*?)?(?:\s?\| args: (?P<rawargs>.*?))?$$"
|
||||
|
@ -100,9 +103,11 @@ def parseargs(argstring):
|
|||
parser.add_argument("-gs", "--goal-style", type=str)
|
||||
parser.add_argument("--hidden", action="store_true")
|
||||
return parser.parse_args(argstring.split())
|
||||
def divider(len):
|
||||
return ansi.style(f" {cfg.div*len}", "div_style")
|
||||
def gen_makefile():
|
||||
makefile = ""
|
||||
for file in os.getenv("MAKEFILE_LIST").split():
|
||||
for file in os.getenv("MAKEFILE_LIST", "").split():
|
||||
with open(file, "r") as f:
|
||||
makefile += f.read() + "\n\n"
|
||||
return makefile
|
||||
|
@ -132,58 +137,80 @@ def recipe_help_header(goal):
|
|||
item[0].get("msgargs", ""),
|
||||
)
|
||||
else:
|
||||
return f" {ansi.style(goal,'$(GOAL_STYLE)')}:"
|
||||
return f" {ansi.style(goal,'goal')}"
|
||||
def get_goal_deps(goal="task.mk"):
|
||||
make = os.getenv("MAKE", "make")
|
||||
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 + ":(.*)?")
|
||||
for line in database.splitlines():
|
||||
match = dep_pattern.search(line)
|
||||
if match and match.groups()[0]:
|
||||
return wrap(
|
||||
f"{ansi.style('deps','default')}: {ansi.style(match.groups()[0].strip(),'msg')}",
|
||||
width=cfg.wrap,
|
||||
initial_indent=" ",
|
||||
subsequent_indent=" ",
|
||||
)
|
||||
def parse_goal(file, goal):
|
||||
goals = goal_pattern.findall(file)
|
||||
matched_goal = [i for i in goals if goal in i.split()]
|
||||
output = []
|
||||
if matched_goal:
|
||||
output.append(recipe_help_header(matched_goal[0]))
|
||||
deps = get_goal_deps(matched_goal[0])
|
||||
if deps:
|
||||
output.extend(deps)
|
||||
lines = file.splitlines()
|
||||
loc = [n for n, l in enumerate(lines) if l.startswith(f"{matched_goal[0]}:")][0]
|
||||
recipe = []
|
||||
for line in lines[loc + 1 :]:
|
||||
if not line.startswith("\t"):
|
||||
break
|
||||
recipe.append(line)
|
||||
output.append(divider(max((len(l) for l in recipe)) + 5))
|
||||
output.append("\n".join(recipe) + "\n")
|
||||
recipe.append(f" {line.strip()}")
|
||||
output.append(divider(max((len(l.strip()) for l in recipe))))
|
||||
output.append("\n".join(recipe))
|
||||
else:
|
||||
output.append(f"{ansi.b_red}ERROR{ansi.end} Failed to find goal: {goal}")
|
||||
deps = get_goal_deps(goal)
|
||||
if deps:
|
||||
output.append(recipe_help_header(goal))
|
||||
output.extend(deps)
|
||||
if not output:
|
||||
output.append(f"{ansi.style('ERROR','b_red')}: Failed to find goal: {goal}")
|
||||
return output
|
||||
def fmt_goal(goal, msg, max_goal_len, argstr):
|
||||
args = parseargs(argstr)
|
||||
goal_style = args.goal_style.strip() if args.goal_style else "$(GOAL_STYLE)"
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "$(MSG_STYLE)"
|
||||
goal_style = args.goal_style.strip() if args.goal_style else "goal"
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "msg"
|
||||
return (
|
||||
ansi.style(f" {goal:>{max_goal_len}}", goal_style)
|
||||
+ f" $(HELP_SEP) "
|
||||
+ ansi.style(msg, msg_style)
|
||||
)
|
||||
def divider(len):
|
||||
return ansi.style(f" {'$(DIVIDER)'*len}", "$(DIVIDER_STYLE)")
|
||||
def fmt_rawmsg(msg, argstr, maxlens):
|
||||
args = parseargs(argstr)
|
||||
lines = []
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "$(MSG_STYLE)"
|
||||
msg_style = args.msg_style.strip() if args.msg_style else "msg"
|
||||
if not os.getenv("SHOW_HIDDEN") and args.hidden:
|
||||
return []
|
||||
if msg:
|
||||
if args.align == "sep":
|
||||
lines.append(
|
||||
f"{' '*(maxlens.goal+len('$(HELP_SEP)')+4)}{ansi.style(msg,msg_style)}"
|
||||
f"{' '*(maxlens.goal+len(cfg.sep)+4)}{ansi.style(msg,msg_style)}"
|
||||
)
|
||||
elif args.align == "center":
|
||||
lines.append(f" {ansi.style(msg.center(sum(maxlens)),msg_style)}")
|
||||
else:
|
||||
lines.append(f" {ansi.style(msg,msg_style)}")
|
||||
if args.divider:
|
||||
lines.append(divider(len("$(HELP_SEP)") + sum(maxlens) + 2))
|
||||
lines.append(divider(len(cfg.sep) + sum(maxlens) + 2))
|
||||
if args.whitespace:
|
||||
lines.append("\n")
|
||||
return lines
|
||||
def print_help():
|
||||
lines = [f"""$(USAGE)"""]
|
||||
lines = [cfg.usage]
|
||||
items = list(parse_help(gen_makefile()))
|
||||
maxlens = MaxLens(
|
||||
*(max((len(item[x]) for item in items if x in item)) for x in ["goal", "msg"])
|
||||
|
@ -197,25 +224,73 @@ def print_help():
|
|||
)
|
||||
if "rawmsg" in item:
|
||||
lines.extend(fmt_rawmsg(item["rawmsg"], item.get("rawargs", ""), maxlens))
|
||||
lines.append(f"""$(EPILOG)""")
|
||||
lines.append(cfg.epilog)
|
||||
print("\n".join(lines))
|
||||
def print_arg_help(help_args):
|
||||
print(f"{ansi.style('task.mk recipe help','header')}\n")
|
||||
for arg in help_args.split():
|
||||
print(f"{ansi.style('task.mk recipe help','$(HEADER_STYLE)')}\n")
|
||||
print("\n".join(parse_goal(gen_makefile(), arg)))
|
||||
print()
|
||||
def main():
|
||||
help_args = os.getenv("HELP_ARGS")
|
||||
if help_args:
|
||||
quit_make()
|
||||
print_arg_help(help_args)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print_help()
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
endef
|
||||
define ansi_py
|
||||
define info_py
|
||||
$(utils_py)
|
||||
print(f"""$(2)""")
|
||||
endef
|
||||
define print_ansi_py
|
||||
$(utils_py)
|
||||
sep = f"$(HELP_SEP)"
|
||||
codes_names = {getattr(ansi, attr): attr for attr in ansi.__dict__}
|
||||
for code in sorted(codes_names.keys(), key=lambda item: (len(item), item)):
|
||||
print(f"{codes_names[code]:>20} {sep} {code+'*****'+ansi.end} {sep} {repr(code)}")
|
||||
endef
|
||||
define vars_py
|
||||
import os
|
||||
$(utils_py)
|
||||
vars = "$2".split()
|
||||
length = max((len(v) for v in vars))
|
||||
print(f"{ansi.header}vars{ansi.end}:\n")
|
||||
for v in vars:
|
||||
print(f" {ansi.params}{v:<{length}}{ansi.end} = {os.getenv(v)}")
|
||||
print()
|
||||
endef
|
||||
define confirm_py
|
||||
import sys
|
||||
$(utils_py)
|
||||
def confirm():
|
||||
"""
|
||||
Ask user to enter Y or N (case-insensitive).
|
||||
:return: True if the answer is Y.
|
||||
:rtype: bool
|
||||
"""
|
||||
answer = ""
|
||||
while answer not in ["y", "n"]:
|
||||
answer = input(f"""$(2) {a.b_red}[Y/n]{a.end} """).lower()
|
||||
return answer == "y"
|
||||
if confirm():
|
||||
sys.exit()
|
||||
else:
|
||||
sys.exit(1)
|
||||
endef
|
||||
define utils_py
|
||||
import os
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
@dataclass
|
||||
class Config:
|
||||
div: str
|
||||
sep: str
|
||||
epilog: str
|
||||
usage: str
|
||||
wrap: int
|
||||
color2byte = dict(
|
||||
black=0,
|
||||
red=1,
|
||||
|
@ -247,6 +322,7 @@ class Ansi:
|
|||
)
|
||||
for name, byte in state2byte.items():
|
||||
self.setcode(name, f"\033[{byte}m")
|
||||
self.add_cfg()
|
||||
def setcode(self, name, escape_code):
|
||||
"""create attr for style and escape code"""
|
||||
if not sys.stdout.isatty() or os.getenv("NO_COLOR", False):
|
||||
|
@ -277,6 +353,17 @@ class Ansi:
|
|||
print("Expected one or three values for bg as a list")
|
||||
sys.exit(1)
|
||||
return code + end
|
||||
def add_cfg(self):
|
||||
cfg_styles = {
|
||||
"header": "$(HEADER_STYLE)",
|
||||
"accent": "$(ACCENT_STYLE)",
|
||||
"params": "$(PARAMS_STYLE)",
|
||||
"goal": "$(GOAL_STYLE)",
|
||||
"msg": "$(MSG_STYLE)",
|
||||
"div_style": "$(DIVIDER_STYLE)",
|
||||
}
|
||||
for name, style in cfg_styles.items():
|
||||
self.setcode(name, getattr(self, style))
|
||||
def style(self, text, style):
|
||||
if style not in self.__dict__:
|
||||
print(f"unknown style: {style}")
|
||||
|
@ -284,49 +371,6 @@ class Ansi:
|
|||
else:
|
||||
return f"{self.__dict__[style]}{text}{self.__dict__['end']}"
|
||||
a = ansi = Ansi()
|
||||
endef
|
||||
define info_py
|
||||
$(ansi_py)
|
||||
print(f"""$(2)""")
|
||||
endef
|
||||
define print_ansi_py
|
||||
$(ansi_py)
|
||||
sep = f"$(HELP_SEP)"
|
||||
codes_names = {getattr(ansi, attr): attr for attr in ansi.__dict__}
|
||||
for code in sorted(codes_names.keys(), key=lambda item: (len(item), item)):
|
||||
print(f"{codes_names[code]:>20} {sep} {code+'*****'+ansi.end} {sep} {repr(code)}")
|
||||
endef
|
||||
define vars_py
|
||||
import os
|
||||
$(ansi_py)
|
||||
vars = "$2".split()
|
||||
length = max((len(v) for v in vars))
|
||||
print(f"{ansi.$(HEADER_STYLE)}vars:{ansi.end}\n")
|
||||
for v in vars:
|
||||
print(f" {ansi.b_magenta}{v:<{length}}{ansi.end} = {os.getenv(v)}")
|
||||
print()
|
||||
endef
|
||||
define confirm_py
|
||||
import sys
|
||||
$(ansi_py)
|
||||
$(quit_make_py)
|
||||
def confirm():
|
||||
"""
|
||||
Ask user to enter Y or N (case-insensitive).
|
||||
:return: True if the answer is Y.
|
||||
:rtype: bool
|
||||
"""
|
||||
answer = ""
|
||||
while answer not in ["y", "n"]:
|
||||
answer = input(f"""$(2) {a.b_red}[Y/n]{a.end} """).lower()
|
||||
return answer == "y"
|
||||
if confirm():
|
||||
sys.exit()
|
||||
else:
|
||||
quit_make()
|
||||
endef
|
||||
define quit_make_py
|
||||
import os, signal
|
||||
def quit_make():
|
||||
os.kill(os.getppid(), signal.SIGQUIT)
|
||||
cfg = Config(
|
||||
"$(DIVIDER)", "$(HELP_SEP)", f"""$(EPILOG)""", f"""$(USAGE)""",int('$(WRAP)'))
|
||||
endef
|
||||
|
|
Loading…
Reference in a new issue