212 lines
5.6 KiB
Python
212 lines
5.6 KiB
Python
# XF Template Generator
|
|
__author__ = "Louis Heredero"
|
|
__copyright__ = "Copyright 2023, Louis Heredero"
|
|
__license__ = "GPL3.0"
|
|
__version__ = "1.0.0"
|
|
|
|
import json
|
|
import locale
|
|
import os
|
|
import re
|
|
import time
|
|
|
|
def ucfirst(s):
|
|
return s[0].upper() + s[1:]
|
|
|
|
def get_input(title, default=None, non_null=False):
|
|
"""Prompts user for an input
|
|
|
|
Args:
|
|
title (str): Name of value
|
|
default (Any, optional): Default value. Defaults to None.
|
|
non_null (bool, optional): Whether the can be null. Defaults to False.
|
|
|
|
Returns:
|
|
str|None: The value
|
|
"""
|
|
|
|
while True:
|
|
txt = title
|
|
if default is not None:
|
|
txt += f" [{default}]"
|
|
txt += ": "
|
|
value = input(txt).strip()
|
|
if value:
|
|
return value
|
|
|
|
elif default:
|
|
return default
|
|
|
|
elif not non_null:
|
|
return ""
|
|
|
|
def fill_template(dir_, variables, filename):
|
|
"""Replaces values in a template file
|
|
|
|
Args:
|
|
dir_ (str): Path of src directory
|
|
variables (dict): Dictionary of values to replace
|
|
filename (str): Template file name
|
|
|
|
Returns:
|
|
str: Template content with replaced values
|
|
"""
|
|
|
|
with open(os.path.join(dir_, "templates", filename), "r") as f:
|
|
content = f.read()
|
|
|
|
def replace(m):
|
|
indent = m.group(1)
|
|
key = m.group(2)
|
|
txt = variables[key]
|
|
|
|
if indent:
|
|
lines = txt.split("\n")
|
|
lines = [indent+line for line in lines]
|
|
txt = "\n".join(lines)
|
|
|
|
return txt
|
|
|
|
return re.sub("([ \t]*)\$\{(.+?)\}", replace, content)
|
|
|
|
def output_file(dir_, filename, content):
|
|
"""Writes content to a given file. Checks before overwriting
|
|
|
|
Args:
|
|
dir_ (str): Path of src directory
|
|
filename (str): Output file name
|
|
content (str): Content to write
|
|
"""
|
|
|
|
outdir = os.path.join(dir_, "out")
|
|
if not os.path.isdir(outdir):
|
|
os.mkdir(outdir)
|
|
|
|
outpath = os.path.join(outdir, filename)
|
|
if os.path.exists(outpath):
|
|
replace = input(f"The file {filename} already exists. Overwrite it ? y/N: ")
|
|
if replace.lower() != "y":
|
|
return
|
|
|
|
with open(outpath, "w") as f:
|
|
f.write(content)
|
|
|
|
def main():
|
|
locale.setlocale(locale.LC_TIME, "en_GB.utf8")
|
|
dir_ = os.path.dirname(__file__)
|
|
|
|
# Load config if it exists
|
|
conf_path = os.path.join(dir_, "config.json")
|
|
if os.path.exists(conf_path):
|
|
with open(conf_path, "r") as f:
|
|
variables = json.load(f)
|
|
|
|
else:
|
|
variables = {}
|
|
|
|
variables["date"] = time.strftime("%B %Y")
|
|
|
|
variables["author"] = get_input("Author", variables.get("author", ""), True)
|
|
variables["filename"] = get_input("Filename", None, True).upper()
|
|
variables["filename_lc"] = variables["filename"].lower()
|
|
variables["fn"] = get_input("Filename (short)", None, True).upper()
|
|
|
|
##########
|
|
# States #
|
|
##########
|
|
|
|
states = []
|
|
|
|
print("States (leave empty to end):")
|
|
print("> INIT")
|
|
while True:
|
|
state = input("> ").upper()
|
|
if state:
|
|
states.append(state)
|
|
else:
|
|
break
|
|
|
|
states = ["ST"+variables["fn"]+"_"+s for s in states]
|
|
variables["STATES_ENUM"] = ",\n".join(states)
|
|
|
|
states_cases = []
|
|
|
|
for state in states:
|
|
case_ = f"case {state}:\n"
|
|
case_ += " break;"
|
|
states_cases.append(case_)
|
|
|
|
variables["STATES_CASES"] = "\n\n".join(states_cases)
|
|
|
|
##########
|
|
# Events #
|
|
##########
|
|
|
|
events = ["init = 100"]
|
|
|
|
print("Events (leave empty to end):")
|
|
print("> init")
|
|
while True:
|
|
event = input("> ").lower()
|
|
if event:
|
|
events.append(event)
|
|
|
|
else:
|
|
break
|
|
|
|
events_enum = ["ev"+variables["fn"]+e for e in events]
|
|
events_enum = ",\n".join(events_enum).split("\n")
|
|
events_enum[0] += " // TODO change this number (< 256)"
|
|
variables["EVENTS_ENUM"] = "\n".join(events_enum)
|
|
|
|
events_emits_def = []
|
|
|
|
emit_def = ""
|
|
emit_def += "void {filename}_emit{Event}({filename}* me, uint16_t t) {\n"
|
|
emit_def += " POST(me, &{filename}_processEvent, ev{fn}{event}, t, 0);\n"
|
|
emit_def += "}"
|
|
emit_def = emit_def.replace("{filename}", variables["filename"]).replace("{fn}", variables["fn"])
|
|
|
|
for event in events[1:]:
|
|
events_emits_def.append(
|
|
emit_def.replace("{event}", event).replace("{Event}", event.capitalize())
|
|
)
|
|
|
|
variables["EVENTS_EMITS_DEF"] = "\n\n".join(events_emits_def)
|
|
|
|
events_emits_dec = []
|
|
emit_dec = ""
|
|
emit_dec += "/**\n"
|
|
emit_dec += " * Emit the {event} event\n"
|
|
emit_dec += " * @param me the {filename} itself\n"
|
|
emit_dec += " * @param t time to wait in ms before triggering event\n"
|
|
emit_dec += " */"
|
|
emit_dec += "void {filename}_emit{Event}({filename}* me, uint16_t t);"
|
|
emit_dec = emit_dec.replace("{filename}", variables["filename"])
|
|
|
|
for event in events[1:]:
|
|
events_emits_dec.append(
|
|
emit_dec.replace("{event}", event).replace("{Event}", event.capitalize())
|
|
)
|
|
|
|
variables["EVENTS_EMITS_DEC"] = "\n\n".join(events_emits_dec)
|
|
|
|
##################
|
|
# Fill templates #
|
|
##################
|
|
|
|
file_c = fill_template(dir_, variables, "file.c")
|
|
file_h = fill_template(dir_, variables, "file.h")
|
|
|
|
output_file(dir_, variables["filename_lc"]+".c", file_c)
|
|
output_file(dir_, variables["filename_lc"]+".h", file_h)
|
|
|
|
# Save config
|
|
with open(conf_path, "w") as f:
|
|
conf = {
|
|
"author": variables["author"]
|
|
}
|
|
json.dump(conf, f)
|
|
|
|
if __name__ == "__main__":
|
|
main() |