Skip to content

Commit 26a636c

Browse files
committed
first basic impl of a help system
1 parent 5f7ebcc commit 26a636c

5 files changed

Lines changed: 183 additions & 25 deletions

File tree

Makefile

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# DOMAINS:
55
#: applications.zest-releaser
66
#: core.base
7+
#: core.help
78
#: core.mxenv
89
#: core.mxfiles
910
#: core.packages
@@ -50,7 +51,7 @@ EXTRA_PATH?=
5051
PRIMARY_PYTHON?=python3
5152

5253
# Minimum required Python version.
53-
# Default: 3.7
54+
# Default: 3.9
5455
PYTHON_MIN_VERSION?=3.9
5556

5657
# Install packages using the given package installer method.
@@ -166,6 +167,12 @@ MYPY_SRC?=src
166167
# Default: types-setuptools
167168
MYPY_REQUIREMENTS?=types-setuptools types-docutils types-PyYAML
168169

170+
## core.help
171+
172+
# Request to show all targets, descriptions and arguments for a given domain.
173+
# No default value.
174+
HELP_DOMAIN?=
175+
169176
## applications.zest-releaser
170177

171178
# Options to pass to zest.releaser prerelease command.
@@ -594,6 +601,14 @@ TYPECHECK_TARGETS+=mypy
594601
CLEAN_TARGETS+=mypy-clean
595602
DIRTY_TARGETS+=mypy-dirty
596603

604+
##############################################################################
605+
# help
606+
##############################################################################
607+
608+
.PHONY: help
609+
help: $(MXENV_TARGET)
610+
@mxmake help-generator
611+
597612
##############################################################################
598613
# zest-releaser
599614
##############################################################################
@@ -636,6 +651,10 @@ INSTALL_TARGETS+=$(ZEST_RELEASER_TARGET)
636651
DIRTY_TARGETS+=zest-releaser-dirty
637652
CLEAN_TARGETS+=zest-releaser-clean
638653

654+
##############################################################################
655+
# Custom includes
656+
##############################################################################
657+
639658
-include $(INCLUDE_MAKEFILE)
640659

641660
##############################################################################

src/mxmake/helpgen.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from .parser import MakefileParser
2+
from .topics import get_domain
3+
from .topics import get_topic
4+
from .topics import resolve_domain_dependencies
5+
from .topics import set_domain_runtime_depends
6+
7+
import os
8+
import sys
9+
import textwrap
10+
11+
12+
def print_help(makefile: "pathlib.Path"):
13+
"""Parse the Makefile and print the help."""
14+
15+
parser = MakefileParser(makefile)
16+
17+
sys.stdout.write("\nUsage: make <target> [ARGUMENT1=value1] [ARGUMENT2=value2]\n\n")
18+
help_domain = os.environ.get("HELP_DOMAIN")
19+
if help_domain:
20+
sys.stdout.write(f"Help for domain '{help_domain}'\n\n")
21+
else:
22+
sys.stdout.write("Available targets:\n\n")
23+
24+
domains = [get_domain(fqn) for fqn in parser.fqns]
25+
set_domain_runtime_depends(domains)
26+
idnt = " "
27+
lvl = 1
28+
found = False
29+
for domain in resolve_domain_dependencies(domains):
30+
if help_domain and domain.name != help_domain:
31+
continue
32+
topic = get_topic(domain.topic)
33+
sys.stdout.write(
34+
f"DOMAIN '{domain.name}' (topic {topic.title})\n"
35+
)
36+
sys.stdout.write(
37+
"\n".join(
38+
textwrap.wrap(
39+
domain.description,
40+
width=79,
41+
initial_indent=idnt * lvl,
42+
subsequent_indent=idnt * lvl,
43+
)
44+
)
45+
)
46+
sys.stdout.write("\n\nTARGETS\n\n")
47+
for target in domain.targets:
48+
sys.stdout.write(f"{idnt*lvl}{target.name}\n")
49+
if help_domain:
50+
lvl += 1
51+
found = True
52+
sys.stdout.write(
53+
"\n".join(
54+
textwrap.wrap(
55+
target.description,
56+
width=79,
57+
initial_indent=idnt * (lvl),
58+
subsequent_indent=idnt * (lvl),
59+
)
60+
)
61+
)
62+
sys.stdout.write("\n\n")
63+
lvl -= 1
64+
if help_domain:
65+
sys.stdout.write(f"ARGUMENTS\n\n")
66+
for setting in domain.settings:
67+
fqn_setting = f"{domain.fqn}.{setting.name}"
68+
sys.stdout.write(
69+
f"{idnt*lvl}{setting.name}={parser.settings.get(fqn_setting) or '<not set>'}\n"
70+
)
71+
sys.stdout.write(
72+
"\n".join(
73+
textwrap.wrap(
74+
setting.description,
75+
width=79,
76+
initial_indent=idnt * (lvl + 1),
77+
subsequent_indent=idnt * (lvl + 1),
78+
)
79+
)
80+
)
81+
sys.stdout.write("\n\n")
82+
else:
83+
sys.stdout.write("\n\n")
84+
85+
86+
if not help_domain:
87+
sys.stdout.write("")
88+
sys.stdout.write(
89+
"Need detailed help by domain containing all information?\nRun:\n\n make help HELP_DOMAIN=<domain>\n"
90+
)
91+
elif not found:
92+
sys.stdout.write("No help found for requested domain st\n")
93+
sys.exit(1)

src/mxmake/main.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
from mxmake.parser import MakefileParser
2-
from mxmake.templates import ci_template
3-
from mxmake.templates import get_template_environment
4-
from mxmake.templates import template
5-
from mxmake.topics import collect_missing_dependencies
6-
from mxmake.topics import Domain
7-
from mxmake.topics import get_domain
8-
from mxmake.topics import get_topic
9-
from mxmake.topics import load_topics
10-
from mxmake.topics import resolve_domain_dependencies
11-
from mxmake.topics import set_domain_runtime_depends
1+
from .helpgen import print_help
2+
from .parser import MakefileParser
3+
from .templates import ci_template
4+
from .templates import get_template_environment
5+
from .templates import template
6+
from .topics import collect_missing_dependencies
7+
from .topics import Domain
8+
from .topics import get_domain
9+
from .topics import get_topic
10+
from .topics import load_topics
11+
from .topics import resolve_domain_dependencies
12+
from .topics import set_domain_runtime_depends
1213
from operator import attrgetter
1314
from pathlib import Path
1415
from textwrap import indent
@@ -301,16 +302,31 @@ def update_command(args: argparse.Namespace):
301302
sys.stdout.write("###############\n\n")
302303

303304
if not Path("Makefile").exists():
304-
sys.stdout.write("Makefile not exists, abort\n")
305+
sys.stdout.write("Makefile does not exist, abort\n")
305306
sys.exit(1)
306307

307308
create_config(prompt=False, preseeds=None)
308309

309310

310-
update_parser = command_parsers.add_parser("update", help="Update makefile")
311+
update_parser = command_parsers.add_parser("update", help="Update Makefile")
311312
update_parser.set_defaults(func=update_command)
312313

313314

315+
def help_generator_command(args: argparse.Namespace):
316+
sys.stdout.write("Help for Makefile\n")
317+
makefile = Path("Makefile")
318+
if not makefile.exists():
319+
sys.stdout.write("Makefile does not exist, abort\n")
320+
sys.exit(1)
321+
322+
print_help(makefile)
323+
324+
325+
help_generator_parser = command_parsers.add_parser(
326+
"help-generator", help="Help for Makefile"
327+
)
328+
help_generator_parser.set_defaults(func=help_generator_command)
329+
314330
##############################################################################
315331
# main
316332
##############################################################################

src/mxmake/topics/core/base.mk

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@
1010
#:description = Deploy project. Supposed to setup a production version of
1111
#: the project.
1212
#:
13+
#:[setting.DEPLOY_TARGETS]
14+
#:description = `deploy` target dependencies.
15+
#:default =
16+
#:
1317
#:[target.run]
1418
#:description = Run project. Depending on target defined in `RUN_TARGET`
1519
#:
20+
#:[setting.RUN_TARGET]
21+
#:description = target to be executed when calling `make run`
22+
#:default =
23+
#:
1624
#:[target.dirty]
1725
#:description = Force make to rebuild targets on next make run.
1826
#:
@@ -27,21 +35,21 @@
2735
#:[target.runtime-clean]
2836
#:description = Remove runtime artifacts, like byte-code and caches.
2937
#:
38+
#:[setting.CLEAN_FS]
39+
#:description = Additional files and folders to remove when running clean target
40+
#:default =
41+
#:
3042
#:[target.check]
31-
#:description = Run all QA related targets, e.g. code style or type checks.
43+
#:description = Run all QA checkers related targets, e.g. code style
3244
#: Only gets included if any qa topic related domain is used.
3345
#:
34-
#:[setting.DEPLOY_TARGETS]
35-
#:description = `deploy` target dependencies.
36-
#:default =
37-
#:
38-
#:[setting.RUN_TARGET]
39-
#:description = target to be executed when calling `make run`
40-
#:default =
46+
#:[target.type-check]
47+
#:description = Run all QA type-checkers related targets, e.g. type checks.
48+
#: Only gets included if any qa topic related domain is used.
4149
#:
42-
#:[setting.CLEAN_FS]
43-
#:description = Additional files and folders to remove when running clean target
44-
#:default =
50+
#:[target.format]
51+
#:description = Run all QA code formatters related targets, e.g. code style
52+
#: Only gets included if any qa topic related domain is used.
4553
#:
4654
#:[setting.INCLUDE_MAKEFILE]
4755
#:description = Optional makefile to include before default targets. This can

src/mxmake/topics/core/help.mk

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#:[help]
2+
#:title = Help System
3+
#:description = A system to provide the user of the Makefile an overview of the targets
4+
#: and all environment variable based arguments.
5+
#:
6+
#:depends = core.mxenv
7+
#:
8+
#:[target.help]
9+
#:description = Print help for the Makefile.
10+
#:
11+
#:[setting.HELP_DOMAIN]
12+
#:description = Request to show all targets, descriptions and arguments for a given domain.
13+
#:default =
14+
#:
15+
16+
##############################################################################
17+
# help
18+
##############################################################################
19+
20+
.PHONY: help
21+
help: $(MXENV_TARGET)
22+
@mxmake help-generator

0 commit comments

Comments
 (0)