summaryrefslogtreecommitdiffhomepage
path: root/cheatsheet/tool/generate_cheatsheet_code.py
diff options
context:
space:
mode:
Diffstat (limited to 'cheatsheet/tool/generate_cheatsheet_code.py')
-rw-r--r--cheatsheet/tool/generate_cheatsheet_code.py169
1 files changed, 169 insertions, 0 deletions
diff --git a/cheatsheet/tool/generate_cheatsheet_code.py b/cheatsheet/tool/generate_cheatsheet_code.py
new file mode 100644
index 0000000..afb502c
--- /dev/null
+++ b/cheatsheet/tool/generate_cheatsheet_code.py
@@ -0,0 +1,169 @@
+import os
+import sys
+import argparse
+from contextlib import contextmanager
+
+def parseColors(inp, outp, modules):
+ previous_line = ""
+ data = []
+ indicator = "CLITERAL(Color)"
+ for line in inp.readlines():
+ if indicator in line or indicator in previous_line:
+ data.append(previous_line.strip())
+ previous_line = line
+
+ for d in data:
+ print(f" {d.replace('CLITERAL', '').replace('NOTE: ', '')}".rstrip(), file=outp)
+
+
+def parseStructs(inp, outp, modules):
+ struct_section_starters = ["Image", "Camera", "Wave", "VrDeviceInfo", "FilePathList"]
+ start_section = "// Structures Definition\n"
+ end_section = "// Enumerators Definition\n"
+ data = []
+ comment = []
+ for line in inp.readlines():
+ if line == start_section:
+ data = []
+ comment = []
+ elif line == end_section:
+ break
+ elif line.startswith("//--"):
+ pass
+ elif line.startswith("//"):
+ comment.append(line.strip())
+ elif line.strip().startswith("typedef struct"):
+ if line[len("typedef struct") + 1].isupper():
+ data.append((line.strip(" {\n"), comment))
+ comment = []
+ elif line.strip().startswith("typedef"):
+ comment = [] # ignore non structs, just like the current cheatsheet
+
+ for d in data:
+ struct = d[0].replace("CLITERAL", "").replace("typedef ", "") + ";"
+ for s in struct_section_starters:
+ if s in struct:
+ print(file=outp)
+ comments = ("\n" + (35 * " ")).join(d[1])
+ print(f" {struct:30} {comments}", file=outp)
+
+
+def parseMathFile(inp, outp, modules):
+ tag = "RMAPI"
+ data = []
+ comments = []
+ for line in inp.readlines():
+ if line.startswith("// Module Functions Definition"):
+ data.append((line[len("// Module Functions Definition - "):-1],))
+ elif line.startswith("//------"):
+ pass
+ elif line.startswith("//"):
+ comments.append(line.strip("\n /"))
+ elif line.startswith(tag):
+ data.append((line[len(tag)+1:].strip(), comments))
+ comments = []
+
+ for d in data:
+ if len(d) == 2:
+ print(f" {d[0]:75} {'//' if len(d[1]) > 0 else ''} {' '.join(d[1])}", file=outp)
+ elif len(d) == 1:
+ print(f"\n // {d[0]}", file=outp)
+
+
+def parseFile(inp, outp, modules):
+ tag = "RLAPI"
+ data = []
+ current_module = ""
+ moduleHeader = "(Module: "
+ for line in inp.readlines():
+ if moduleHeader in line:
+ idx = line.index(moduleHeader) + len(moduleHeader)
+ idx_end = line.index(")", idx)
+ wasnt_in = False
+ if not (current_module in modules):
+ data = []
+ wasnt_in = True
+ current_module = line[idx:idx_end]
+ if not wasnt_in and not current_module in modules:
+ break
+ if current_module in modules:
+ if line.startswith("//"):
+ data.append(line.strip())
+ elif line.startswith("\n"):
+ data.append(line.strip())
+ elif line.startswith(tag):
+ data.append(line[len(tag):].strip())
+
+ # 3 and onwards to skip first module declaration
+ for d in data[3:-1]:
+ print(f" {d}".rstrip(), file=outp)
+
+
+@contextmanager
+def fileorstd(filepath, data=''):
+ if isinstance(filepath, str):
+ fil = open(filepath, data)
+ try:
+ yield fil
+ finally:
+ fil.close()
+ else: # is stdin or stdout
+ yield filepath
+
+
+def performModule(module, mathin, libin, outp):
+ with fileorstd(mathin if module == ["math"] else libin, "r") as sin, \
+ fileorstd(outp, "w+") as sout:
+ fn = parseFile
+ if module == ["math"]:
+ fn = parseMathFile
+ if module == ["structs"]:
+ fn = parseStructs
+ if module == ["colors"]:
+ fn = parseColors
+ fn(sin, sout, module)
+
+
+def main():
+ all_modules = ["core", "rgestures", "rcamera", "shapes", "textures", "text", "models", "audio", "math"]
+ modules = {
+ "core": ["core", "rgestures", "rcamera"],
+ "shapes": ["shapes"],
+ "textures": ["textures"],
+ "text": ["text"],
+ "models": ["models"],
+ "audio": ["audio"],
+ "math": ["math"],
+ "structs": ["structs"],
+ "colors": ["colors"],
+ }
+ parser = argparse.ArgumentParser(description="Generator for cheatsheet c files for raylib.com",
+ epilog="Example: python generate_cheatsheet_code.py -r raylib/src/raylib.h -m raylib/src/raymath.h -o raylib.com/cheatsheet/ # this generates all files")
+ parser.add_argument("module", nargs="?", type=str, help="the name of the module to generate. If not specified, generates all. Must be one of " + ", ".join(modules.keys()))
+ parser.add_argument("-r", "--raylib", dest="inlib", default=sys.stdin, type=str, help="path to the raylib.h header file. If not specified uses stdin")
+ parser.add_argument("-m", "--raymath", dest="inmath", default=sys.stdin, type=str, help="path to the raymath.h header file. If not specified uses stdin")
+ parser.add_argument("-o", "--output", dest="out", default=sys.stdout, type=str, help="the file to generate, or folder if generating all modules")
+ args = parser.parse_args()
+
+ if args.module is not None:
+ module = []
+ try:
+ module = modules[args.module]
+ except KeyError:
+ parser.print_help()
+ print(f"Error: {args.module} is not a valid module")
+ performModule(module, args.inmath, args.inlib, args.out)
+ else:
+ is_stdout = args.out is sys.stdout
+ if not is_stdout and not os.path.exists(args.out):
+ os.mkdir(args.out)
+
+ for mod, modules in modules.items():
+ outp = args.out
+ if not is_stdout:
+ outp += f"/raylib_{mod}.c"
+ performModule(modules, args.inmath, args.inlib, outp)
+
+
+if __name__ == "__main__":
+ main()