This commit is contained in:
Daylin Morgan 2022-09-05 12:23:17 -05:00
parent f380c10d97
commit 1a894dd5ff
14 changed files with 349 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.task.mk
env/

75
Makefile Normal file
View file

@ -0,0 +1,75 @@
VERSION ?= $(shell git describe --tags --always --dirty | sed s'/dirty/dev/')
TEMPLATES := $(shell find src/ -type f)
.DEFAULT_GOAL := help
header = $(call tprint,{c.b_magenta}==>{c.end} {c.bold}$(1){c.end} {c.b_magenta}<=={c.end})
## bootstrap | generate local conda environment
.PHONY: bootstrap
bootstrap:
$(call header,Bootstrap Environment)
@mamba create -p ./env python jinja2 black
## lint | lint the python
.PHONY: lint
lint:
@black generate.py
@black src/*.py --fast
## release | make new release of project
.PHONY: release
release: version-check
$(call header,Release Project)
@./generate.py $(VERSION) > task.mk
@sed -i 's/task.mk\/.*\/task.mk/task.mk\/v$(VERSION)\/task.mk/g' README.md
@git add task.mk README.md
@git commit -m "release: v$(VERSION)"
## clean | remove the generated files
.PHONY: clean
clean:
@rm -f task.mk .task.mk
.PHONY: version-check
version-check:
@if [[ "${VERSION}" == *'-'* ]]; then\
$(call tprint-sh,{c.red}VERSION INVALID! Uncommited Work{c.end});\
echo ">> version: $(VERSION)"; exit 1;\
elif [[ $(shell echo "${VERSION}" | awk -F. '{ print NF }') -lt 3 ]];then\
$(call tprint-sh,{c.red}VERSION INVALID! Expected CalVer string{c.end});\
echo ">> version: $(VERSION)"; exit 1;\
else \
$(call tprint-sh,{c.green}VERSION LOOKS GOOD!{c.end});\
fi
define msg
{c.b_yellow}
It can even be multiline!{c.end}
and styles can be defined{c.end}
as python {c.bold}f-string{c.end} literals
{c.end}
endef
## info | demonstarte usage of tprint
.PHONY: task
info:
$(call header, Info Message)
$(call tprint,{c.b_magenta}This is task-print output:{c.end})
$(call tprint,$(msg))
define USAGE
{c.$(HEADER_COLOR)}usage:{c.end}
make <recipe>
A usage statement...with {c.b_green}COLOR{c.end}
endef
EPILOG = \nAn epilog...\nfor more help: see github.com/daylinmorgan/task.mk
PRINT_VARS := VERSION
-include .task.mk
.task.mk: $(TEMPLATES) generate.py
./generate.py $(VERSION) > .task.mk

41
generate.py Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env python3
import sys
from pathlib import Path
import jinja2
py_script_names = ["help", "color", "info", "print-colors", "vars"]
def get_jinja_env():
templateLoader = jinja2.FileSystemLoader(searchpath=Path(__file__).parent / "src")
return jinja2.Environment(
loader=templateLoader,
block_start_string="#%",
block_end_string="%#",
variable_start_string="##-",
variable_end_string="-##",
)
def render(env, template, **kwargs):
template = env.get_template(template)
return template.render(**kwargs)
def main():
if len(sys.argv) == 2:
version = sys.argv[1]
else:
version = "dev"
env = get_jinja_env()
py_scripts = [render(env, f"{name}.py") for name in py_script_names]
print(render(env, "task.mk", py_scripts=py_scripts, version=version))
if __name__ == "__main__":
main()

3
setup.cfg Normal file
View file

@ -0,0 +1,3 @@
[flake8]
max_line_length = 88
ignore = E265

36
src/builtins.mk Normal file
View file

@ -0,0 +1,36 @@
# ---- [buitlin recipes] ---- #
## h, help | show this help
.PHONY: help h
help h:
$(call py,help_py)
.PHONY: _help
_help: export SHOW_HIDDEN=true
_help: help
ifdef PRINT_VARS
$(foreach v,$(PRINT_VARS),$(eval export $(v)))
.PHONY: vars v
vars v:
$(call py,vars_py,$(PRINT_VARS))
endif
## _print-colors | show all possible ansi color code combinations
.PHONY:
_print-colors:
$(call py,print_colors_py)
# functions to take f-string literals and pass to python print
tprint = $(call py,info_py,$(1))
tprint-sh = $(call pysh,info_py,$(1))
_update-task.mk:
$(call tprint,Updating task.mk)
curl https://raw.githubusercontent.com/daylinmorgan/task.mk/main/task.mk -o .task.mk
export MAKEFILE_LIST

53
src/color.py Normal file
View file

@ -0,0 +1,53 @@
#% extends "py-script.mk" %#
#% block name %#color#% endblock %#
#% block script %#
import os
import sys
color2byte = dict(
black=0,
red=1,
green=2,
yellow=3,
blue=4,
magenta=5,
cyan=6,
white=7,
)
state2byte = dict(
bold=1, faint=2, italic=3, underline=4, blink=5, fast_blink=6, crossed=9
)
def fg(byte):
return 30 + byte
def bg(byte):
return 40 + byte
class Colors:
"""ANSI color codes"""
def setcolor(self, name, escape_code):
if not sys.stdout.isatty() or os.getenv("NO_COLOR", False):
setattr(self, name, "")
else:
setattr(self, name, escape_code)
def __init__(self):
self.setcolor("end", "\033[0m")
for name, byte in color2byte.items():
self.setcolor(name, f"\033[{fg(byte)}m")
self.setcolor(f"b_{name}", f"\033[1;{fg(byte)}m")
self.setcolor(f"d_{name}", f"\033[2;{fg(byte)}m")
for bgname, bgbyte in color2byte.items():
self.setcolor(f"{name}_on_{bgname}", f"\033[{bg(bgbyte)};{fg(byte)}m")
for name, byte in state2byte.items():
self.setcolor(name, f"\033[{byte}m")
c = colors = Colors()
#% endblock %#

15
src/config.mk Normal file
View file

@ -0,0 +1,15 @@
# ---- CONFIG ---- #
HEADER_COLOR ?= b_cyan
PARAMS_COLOR ?= b_magenta
ACCENT_COLOR ?= b_yellow
GOAL_COLOR ?= $(ACCENT_COLOR)
MSG_COLOR ?= faint
HELP_SEP ?= |
EPILOG ?=
# python f-string literal
define USAGE ?=
{colors.$(HEADER_COLOR)}usage{colors.end}:
make <recipe>
endef

38
src/help.py Normal file
View file

@ -0,0 +1,38 @@
#% extends "py-script.mk" %#
#% block name %#help#% endblock %#
#% block script %#
import os
import re
##- '$(color_py)' -##
pattern = re.compile(r"^## (.*) \| (.*)")
makefile = ""
for file in os.getenv("MAKEFILE_LIST").split():
with open(file, "r") as f:
makefile += f.read() + "\n\n"
def get_help(file):
for line in file.splitlines():
match = pattern.search(line)
if match:
if not os.getenv("SHOW_HIDDEN") and match.groups()[0].startswith("_"):
continue
else:
yield match.groups()
print(f"""$(USAGE)""")
goals = list(get_help(makefile))
goal_len = max(len(goal[0]) for goal in goals)
for goal, msg in goals:
print(
f"{colors.$(GOAL_COLOR)}{goal:>{goal_len}}{colors.end} $(HELP_SEP) {colors.$(MSG_COLOR)}{msg}{colors.end}"
)
print(f"""$(EPILOG)""")
#% endblock %#

7
src/info.py Normal file
View file

@ -0,0 +1,7 @@
#% extends "py-script.mk" %#
#% block name %#info#% endblock %#
#% block script %#
##- '$(color_py)' -##
print(f"""$(2)""")
#% endblock %#

14
src/print-colors.py Normal file
View file

@ -0,0 +1,14 @@
#% extends "py-script.mk" %#
#% block name %#print_colors#% endblock %#
#% block script %#
##- '$(color_py)' -##
codes_names = {
getattr(colors, attr): attr
for attr in dir(colors)
if attr[0:1] != "_" and attr != "end" and attr != "setcolor"
}
for code in sorted(codes_names.keys(), key=lambda item: (len(item), item)):
print("{:>20} {}".format(codes_names[code], code + "******" + colors.end))
#% endblock %#

26
src/py-runner.mk Normal file
View file

@ -0,0 +1,26 @@
# ---- [python script runner] ---- #
# modified from https://unix.stackexchange.com/a/223093
define \n
endef
escape_shellstring = $(subst `,\`,$(subst ",\",$(subst $$,\$$,$(subst \,\\,$1))))
escape_printf = $(subst \,\\,$(subst %,%%,$1))
create_string = $(subst $(\n),\n,$(call escape_shellstring,$(call escape_printf,$1)))
ifdef DEBUG
define py
@printf "Python Script:"
@printf "$(call create_string,$($(1)))"
@printf "$(call create_string,$($(1)))" | python3
endef
else
py = @printf "$(call create_string,$($(1)))" | python3
endif
pysh = printf "$(call create_string,$($(1)))" | python3

5
src/py-script.mk Normal file
View file

@ -0,0 +1,5 @@
define #% block name %##% endblock %#_py
#% block script %##% endblock %#
endef

16
src/task.mk Normal file
View file

@ -0,0 +1,16 @@
# --------------------- [github.com/daylinmorgan/task.mk] -------------------- #
# Copyright (c) 2022 Daylin Morgan
# MIT License
# ##- version -##
#% include 'config.mk' %#
#% include 'builtins.mk' %#
#% include 'py-runner.mk' %#
# ---- [python scripts] ---- #
#% for script in py_scripts %#
##- script -##
#% endfor %#

18
src/vars.py Normal file
View file

@ -0,0 +1,18 @@
#% extends "py-script.mk" %#
#% block name %#vars#% endblock %#
#% block script %#
import os
##- '$(color_py)' -##
vars = "$2".split()
length = max((len(v) for v in vars))
print(f"{colors.$(HEADER_COLOR)}vars:{colors.end}\n")
for v in vars:
print(f" {colors.b_magenta}{v:<{length}}{colors.end} = {os.getenv(v)}")
print()
#% endblock %#