minetest-flow-cd2025/generate_docs.py
2023-07-14 08:22:50 +12:00

134 lines
4.1 KiB
Python

from ruamel.yaml import YAML
import collections, re, requests
yaml = YAML(typ='safe')
hide_elements = {
'background', 'background9', 'scroll_container', 'scrollbar', 'tabheader'
}
special_case_names = {'tablecolumns': 'TableColumns',
'tableoptions': 'TableOptions'}
def fetch_elements():
res = requests.get('https://github.com/luk3yx/minetest-formspec_ast/raw/'
'master/elements.yaml')
return yaml.load(res.text)
Field = collections.namedtuple('Field', 'name type is_list', defaults=(False,))
def search_for_fields(obj, *, is_list=False):
assert isinstance(obj, (list, tuple))
if len(obj) == 2:
if obj[1] == '...':
yield from search_for_fields(obj[0], is_list=True)
return
if isinstance(obj[0], str) and isinstance(obj[1], str):
yield Field(obj[0], obj[1], is_list)
return
for e in obj:
yield from search_for_fields(e)
def optional(element_name, field_name):
if field_name in ('w', 'h'):
return (element_name not in ('list', 'hypertext', 'model') and
'image' not in element_name)
return field_name == 'name'
def element_to_docs(element_name, variants):
if element_name in special_case_names:
flow_name = special_case_names[element_name]
else:
flow_name = re.sub(r'_(.)', lambda m: m.group(1).upper(),
element_name.capitalize())
fields = collections.Counter(search_for_fields(variants))
if ((element_name in hide_elements or Field('x', 'number') not in fields or
all(field.name in ('x', 'y') for field in fields)) and
element_name not in special_case_names):
return ''
lines = [
f'### `gui.{flow_name}`\n',
f"Equivalent to Minetest's `{element_name}[]` element.\n",
'**Example**',
'```lua',
f'gui.{flow_name} {{'
]
num = 1
indent = ' ' * 4
if element_name == 'tablecolumns':
lines.append(f'{indent}tablecolumns = {{')
lines.append(f'{indent}{indent}{{')
indent += ' ' * 8
for field, count in fields.items():
if (field.name in ('x', 'y') or (element_name == 'tooltip' and
field.name in ('w', 'h'))):
continue
if field.type == 'number':
value = num
num += 1
elif field.type == 'string':
if field.name == 'name':
value = f'"my_{element_name}"'
elif field.name == 'orientation':
value = '"vertical"'
elif 'color' in field.name:
value = '"#FF0000"'
elif field.name == 'type':
value = '"text"'
elif field.name == 'gui_element_name':
value = '"my_button"'
elif 'texture' in field.name:
value = '"texture.png"'
else:
value = '"Hello world!"'
elif field.type in ('boolean', 'fullscreen'):
value = 'false'
elif field.type == 'table':
value = '{field = "value"}'
else:
value = '<?>'
if field.is_list and field.type != 'table':
value = f'{{{value}, ...}}'
line = f'{indent}{field.name} = {value},'
if ((count < len(variants) or optional(element_name, field.name)) and
field.name != 'gui_element_name'):
line = line + ' -- Optional'
lines.append(line)
if element_name == 'tablecolumns':
lines.append(' ' * 8 + '},')
lines.append(' ' * 8 + '...')
lines.append(' ' * 4 + '}')
lines.append('}')
lines.append('```')
return '\n'.join(lines)
if __name__ == '__main__':
print('Fetching data...')
elements = fetch_elements()
print('Done.')
with open('elements.md', 'w') as f:
f.write('# Auto-generated elements list\n\n')
f.write('This is probably broken.')
for element_name, variants in elements.items():
docs = element_to_docs(element_name, variants)
if docs:
f.write('\n\n')
f.write(docs)