Skip to content

Instantly share code, notes, and snippets.

@ShadowNinja
Created March 14, 2017 00:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ShadowNinja/440ab80b2f45a3cf8efa4680c4e6e75f to your computer and use it in GitHub Desktop.
Save ShadowNinja/440ab80b2f45a3cf8efa4680c4e6e75f to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import os
class Section:
def __init__(self, name):
self.name = name
self.entries = []
self.sections = []
class Entry:
def __init__(self, name, readable_name, tp, default, comment, args):
self.name = name
self.readable_name = readable_name
self.type = tp
self.default = default or "\"\""
self.comment = comment
self.min = None
self.max = None
self.values = None
if args:
self.set_args(args.split(" "))
def set_args(self, args):
t = self.type
if t == "int" or t == "float":
self.min = args[0]
self.max = args[1]
elif t == "enum" or t == "flags":
self.values = args[0]
def read_section_header(sect_stack, line):
name = line[1:-1]
depth = name.count("*")
if depth:
name = name[depth:]
s = Section(name)
assert(len(sect_stack) > depth)
sect_stack[depth].sections.append(s)
while len(sect_stack) > depth + 1:
sect_stack.pop()
sect_stack.append(s)
def read_entry(sect, line, comment):
#name (Readable name) type default type_args
def read_to(line, cur, end):
l = line[cur:]
end_i = l.find(end)
if end_i == -1:
end_i = len(l)
return l[:end_i], cur + end_i + 1
name, cur = read_to(line, 0, " ")
desc, cur = read_to(line, cur+1, ")")
tp, cur = read_to(line, cur+1, " ")
if tp == "string" or tp == "noise_params":
default = line[cur:]
args = ""
else:
default, cur = read_to(line, cur, " ")
args = line[cur:]
cmt = []
for line in comment.rstrip().split("\n"):
cmt.append(line.strip())
e = Entry(name, desc, tp, default, "\n".join(cmt), args)
sect.entries.append(e)
config = Section("Config")
sect_stack = [config]
with open(os.path.join("builtin", "settingtypes.txt"), "r") as fd:
last_comment = ""
for line in fd:
line = line.strip()
if not line:
continue
if line.startswith("["):
read_section_header(sect_stack, line)
last_comment = ""
elif line.startswith("#"):
last_comment += line[1:] + "\n"
else:
read_entry(sect_stack[-1], line, last_comment)
last_comment = ""
import jinja2
env = jinja2.Environment(
trim_blocks=True,
lstrip_blocks=True,
autoescape=True,
)
@jinja2.evalcontextfilter
def nl2br(ctx, value):
rpl = "<br />\n"
if ctx.autoescape:
value = jinja2.escape(value)
rpl = jinja2.Markup(rpl)
return value.replace("\n", rpl)
env.filters["nl2br"] = nl2br
tpl = env.from_string(
"""<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Minetest configuration file documentation</title>
<style>
div.cfg-section {
margin-left: 0.3rem;
padding-left: 0.1rem;
border-left: 1px dotted black;
}
header.cfg-section {
font-size: 1.5rem;
border-bottom: 1px solid black;
}
.cfg-entry > header {
font-size: 10pt;
}
.cfg-comment {
margin-left: 2rem;
}
code {
background-color: #EEE;
border-radius: 0.2rem;
}
</style>
</head>
<body>
{% macro render_section(section) %}
<div class="cfg-section">
<header class="cfg-section">{{ section.name }}</header>
{% for entry in section.entries %}
<p class="cfg-entry">
<header><b>{{ entry.readable_name }}</b> <code>{{ entry.name }}</code>
(<code>{{ entry.type }}</code> default <code>{{ entry.default }}</code>
{%- if entry.min != None %}, min <code>{{ entry.min }}</code>, max <code>{{ entry.max }}</code>{% endif -%}
{%- if entry.values != None %}, values <code>{{ entry.values }}</code>{% endif -%}
)</header>
<div class="cfg-comment">{{ entry.comment|nl2br }}</div>
</p>
{% endfor %}
{% for subsect in section.sections %}
{{- render_section(subsect) }}
{% endfor %}
</div>
{% endmacro %}
{{ render_section(config) }}
</body>
</html>
""")
print(tpl.render(config=config))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment