diff --git a/.task.cfg.mk b/.task.cfg.mk index aa0fe0d..bee51bf 100644 --- a/.task.cfg.mk +++ b/.task.cfg.mk @@ -7,4 +7,5 @@ endef EPILOG = \nfor more info: gh.dayl.in/task.mk PRINT_VARS := VERSION SHELL +PHONIFY = 1 diff --git a/Makefile b/Makefile index 5ea7899..4c2f259 100644 --- a/Makefile +++ b/Makefile @@ -4,25 +4,21 @@ TEMPLATES := $(shell find src/ -type f) msg = $(if $(tprint),$(call tprint,{a.bold}==> {a.magenta}$(1){a.end}),@echo '==> $(1)') ### task.mk development |> -d -ms b_green --align center -.PHONY: bootstrap env hooks bootstrap: env hooks ## generate local dev environment |> -ms b_magenta -gs b_cyan -env: +env: ## $(call msg,Bootstrapping Environment) @mamba create -p ./env python jinja2 black -y @mamba run -p ./env pip install yartsu -hooks: +hooks: ## @git config core.hooksPath .githooks -docs-env: +docs-env: ## @mamba run -p ./env pip install mkdocs-material mkdocs-git-revision-date-localized-plugin -.PHONY: l lint l lint: ## lint the python $(call msg,Linting) @black generate.py @black src/*.py --fast - -.PHONY: assets assets: ## generate assets @yartsu -o assets/help.svg -t "make help" -- make --no-print-directory help @@ -35,14 +31,12 @@ git commit -m "release: $(VERSION)" --no-verify git tag $(VERSION) endef -.PHONY: release release: version-check ## release new version of task.mk $(call msg,Release Project) $(call tbash,release_sh) -.PHONY: clean c clean: ## remove the generated files - @rm -f task.mk .task.mk + @rm -f .task.mk define version_check_sh if git rev-parse -q --verify "refs/tags/${VERSION}" >/dev/null; then @@ -56,13 +50,11 @@ elif [[ $(shell echo "${VERSION}" | awk -F. '{ print NF }') -lt 3 ]];then\ fi endef -.PHONY: version-check -version-check: +version-check: ## @$(call tprint,>> version: {a.green}$(VERSION){a.end}) @$(call tbash,version_check_sh) @$(call tprint,>> {a.green}VERSION LOOKS GOOD!{a.end}) -.PHONY: task info: ## demonstrate usage of tprint $(call msg,Info Message) $(call tprint,{a.black_on_cyan}This is task-print output:{a.end}) @@ -74,5 +66,5 @@ task.mk: $(TEMPLATES) generate.py -include .task.cfg.mk .task.mk .task.mk: $(TEMPLATES) generate.py - $(call msg,re-jinjaing the local .task.mk) + $(call msg,re-jinjaing the local {a.b_cyan}.task.mk{a.end}) @./generate.py $(VERSION) > .task.mk || (echo "generator failed!!" && rm .task.mk) diff --git a/generate.py b/generate.py index 89b9c56..70ccf59 100755 --- a/generate.py +++ b/generate.py @@ -11,6 +11,8 @@ py_script_names = [ "vars", "confirm", "utils", + "phonify", + "parsers", ] diff --git a/mkdocs.yml b/mkdocs.yml index 4870cb3..54f01d4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -26,5 +26,3 @@ markdown_extensions: - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences - - diff --git a/src/builtins.mk b/src/builtins.mk index d61b792..b9307fb 100644 --- a/src/builtins.mk +++ b/src/builtins.mk @@ -17,16 +17,19 @@ endif ### task.mk builtins: |> -d --hidden _print-ansi: ## show all possible ansi color code combinations $(call py,print_ansi_py) +_update-task.mk: ## downloads version of task.mk (TASKMK_VERSION=) + $(call tprint,{a.b_cyan}Updating task.mk{a.end}) + curl https://raw.githubusercontent.com/daylinmorgan/task.mk/$(TASKMK_VERSION)/task.mk -o .task.mk # functions to take f-string literals and pass to python print tprint = $(call py,print_py,$(1)) tprint-verbose= $(call py-verbose,print_py,$(1)) tconfirm = $(call py,confirm_py,$(1)) -_update-task.mk: ## downloads version of task.mk (TASKMK_VERSION=) - $(call tprint,{a.b_cyan}Updating task.mk{a.end}) - curl https://raw.githubusercontent.com/daylinmorgan/task.mk/$(TASKMK_VERSION)/task.mk -o .task.mk .PHONY: h help _help _print-ansi _update-task.mk 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 +ifdef PHONIFY +$(shell $(call py-verbose,phonify_py)) +endif diff --git a/src/header.mk b/src/header.mk index cbd20dd..a4ddb40 100644 --- a/src/header.mk +++ b/src/header.mk @@ -5,3 +5,4 @@ TASKMK_VERSION ?= ##- version -## # 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. # You can update your .task.mk with `make _update-task.mk` +# and initialize a repo with `bash <(curl -fsSL gh.dayl.in/task.mk/init)`. diff --git a/src/help.py b/src/help.py index 4b67f39..0a8baae 100644 --- a/src/help.py +++ b/src/help.py @@ -3,43 +3,22 @@ #% block script %# import argparse from collections import namedtuple -import os -import re import subprocess -import sys from textwrap import wrap -###- -from utils import Ansi, cfg # this is just to trick the LSP during development +###- LSP TRICK ONLY +import sys, os +from utils import Ansi, cfg +from parsers import pattern, goal_pattern, gen_makefile, parse_help # -### + ##- '$(utils_py)' -## +##- '$(parsers_py)' -## a = ansi = Ansi(target="stdout") MaxLens = namedtuple("MaxLens", "goal msg") -###- double dollar signs to prevent make escaping them -### -###- bets on how long until I break this regex? -### -pattern = re.compile( - r""" -(?: - ^\#\#\#\s+ # <- raw message - | - ^(?: - (?:\#\#\s+)? - (?P.*?)(?:\s+\|>|:.*?\#\#)\s+ - ) # <- a custom goal or actual recipe -) -(?P.*?)?\s? # <- help text (optional) -(?:\|>\s+ - (?P.*?) -)? # <- style args (optional) -$$ -""", - re.X, -) -goal_pattern = re.compile(r"""^(?!#|\t)(.*):.*\n\t""", re.MULTILINE) - def parseargs(argstring): parser = argparse.ArgumentParser() @@ -56,28 +35,6 @@ def divider(len): return ansi.style(f" {cfg.div*len}", "div_style") -def gen_makefile(): - makefile = "" - for file in os.getenv("MAKEFILE_LIST", "").split(): - with open(file, "r") as f: - makefile += f.read() + "\n\n" - return makefile - - -def parse_help(file, hidden=False): - for line in file.splitlines(): - match = pattern.search(line) - if match: - if ( - not hidden - and not os.getenv("SHOW_HIDDEN") - and str(match.groupdict().get("goal")).startswith("_") - ): - pass - else: - yield {k: v for k, v in match.groupdict().items() if v is not None} - - def recipe_help_header(goal): item = [ i @@ -147,6 +104,10 @@ def fmt_goal(goal, msg, max_goal_len, argstr): args = parseargs(argstr) goal_style = args.goal_style.strip() if args.goal_style else "goal" msg_style = args.msg_style.strip() if args.msg_style else "msg" + # TODO: refactor this to be closer to parse_goal? + if not msg or (not os.getenv("SHOW_HIDDEN") and args.hidden): + return + return ( ansi.style(f" {goal:>{max_goal_len}}", goal_style) + f" $(HELP_SEP) " @@ -189,11 +150,11 @@ def print_help(): ) for item in items: if "goal" in item: - lines.append( - fmt_goal( - item["goal"], item["msg"], maxlens.goal, item.get("msgargs", "") - ) + newgoal = fmt_goal( + item["goal"], item["msg"], maxlens.goal, item.get("msgargs", "") ) + if newgoal: + lines.append(newgoal) else: lines.extend(fmt_rawmsg(item["msg"], item.get("msgargs", ""), maxlens)) lines.append(cfg.epilog) diff --git a/src/parsers.py b/src/parsers.py new file mode 100644 index 0000000..026115b --- /dev/null +++ b/src/parsers.py @@ -0,0 +1,59 @@ +#% extends "py-script.mk" %# +#% block name %#parsers#% endblock %# +#% block script %# +import re + +###- LSP TRICK ONLY +import os, sys + +# -### + +##- '$(utils_py)' -## + +###- double dollar signs to prevent make escaping them -### +###- bets on how long until I break this regex? -### +pattern = re.compile( + r""" +(?: + ^\#\#\#\s+ # <- raw message + | + ^(?: + (?:\#\#\s+)? + (?P.*?)(?:\s+\|>|:.*?\#\#)\s? + ) # <- a custom goal or actual recipe +) +(?P.*?)?\s? # <- help text (optional) +(?:\|>\s+ + (?P.*?) +)? # <- style args (optional) +$$ +""", + re.X, +) + +goal_pattern = re.compile(r"""^(?!#|\t)(.*):.*\n\t""", re.MULTILINE) + + +def gen_makefile(): + makefile = "" + for file in os.getenv("MAKEFILE_LIST", "").split(): + with open(file, "r") as f: + makefile += f.read() + "\n\n" + return makefile + + +def parse_help(file, hidden=False): + for line in file.splitlines(): + match = pattern.search(line) + if match: + if ( + not hidden + and not os.getenv("SHOW_HIDDEN") + and str(match.groupdict().get("goal")).startswith("_") + ): + pass + else: + yield {k: v for k, v in match.groupdict().items() if v is not None} + + +#% endblock %# diff --git a/src/phonify.py b/src/phonify.py new file mode 100644 index 0000000..cc4fcef --- /dev/null +++ b/src/phonify.py @@ -0,0 +1,17 @@ +#% extends "py-script.mk" %# +#% block name %#phonify#% endblock %# +#% block script %# + +##- '$(utils_py)' -## +##- '$(parsers_py)' -## + + +def main(): + items = " ".join((i["goal"] for i in parse_help(gen_makefile()) if "goal" in i)) + sys.stdout.write(".PHONY: " + items) + + +if __name__ == "__main__": + main() + +#% endblock %# diff --git a/src/print-ansi.py b/src/print-ansi.py index c99e316..e21be87 100644 --- a/src/print-ansi.py +++ b/src/print-ansi.py @@ -2,8 +2,11 @@ #% block name %#print_ansi#% endblock %# #% block script %# ##- '$(utils_py)' -## +###- LSP TRICK ONLY import sys +# -### + codes_names = { getattr(ansi, attr): attr for attr in ansi.__dict__ diff --git a/src/task.mk b/src/task.mk index 663ee51..7abc9e4 100644 --- a/src/task.mk +++ b/src/task.mk @@ -1,8 +1,8 @@ #% include 'header.mk' %# #% include 'config.mk' %# -#% include 'builtins.mk' %# -#% include 'runners.mk' %# # ---- [python scripts] ---- # #%- for script in py_scripts %# ##- script -## #%- endfor %# +#% include 'runners.mk' %# +#% include 'builtins.mk' %# diff --git a/src/utils.py b/src/utils.py index 0924352..1c18af5 100644 --- a/src/utils.py +++ b/src/utils.py @@ -96,6 +96,7 @@ class Ansi: sys.exit(1) return code + end + ###- the below $() variables are injected by make -### def add_cfg(self): cfg_styles = { diff --git a/src/vars.py b/src/vars.py index 14e8034..6792b67 100644 --- a/src/vars.py +++ b/src/vars.py @@ -12,8 +12,8 @@ from utils import Ansi ansi = Ansi(target="stdout") ###- $2 is a list of variables set by task.mk delimited with '<|>' -### -task_vars = tuple(v.split('=') for v in "$2".split('<|>')) +task_vars = tuple(v.split("=") for v in "$2".split("<|>")) length = max((len(v[0]) for v in task_vars)) rows = (f" {ansi.params}{v[0]:<{length}}{ansi.end} = {v[1]}" for v in task_vars) -print('\n'.join((f"{ansi.header}vars{ansi.end}:\n", *rows,''))) +print("\n".join((f"{ansi.header}vars{ansi.end}:\n", *rows, ""))) #% endblock %#