-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgen.py
More file actions
172 lines (137 loc) · 5.87 KB
/
Copy pathgen.py
File metadata and controls
172 lines (137 loc) · 5.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import os
import sys
import subprocess
import re
# I wrote this script almost entirely using copilot bc i dont know python
# so it might be a mess or doing bad things but it works
# git clone the repository at https://github.com/KristalTeam/Kristal.git using the subprocess module, or update it if it already exists
subprocess.call(['git', 'submodule', 'update', '--init', '--remote', "Kristal"])
SRC_PATH = os.path.join("Kristal", "src")
ignore = [
os.path.join("engine", "loadthread.lua"),
os.path.join("engine", "loadstate.lua"),
os.path.join("utils", "graphics.lua"),
os.path.join("teststate.lua"),
# TODO: Should be accessible, but as variables of Kristal
os.path.join("engine", "menu", "menu.lua"),
os.path.join("engine", "shaders.lua"),
os.path.join("engine", "overlay.lua"),
]
copy = [
os.path.join("engine", "vars.lua"),
os.path.join("engine", "statevars.lua"),
os.path.join("engine", "vendcust.lua"),
]
scripts = []
copy_scripts = []
# Loop through the files recursively inside the "Kristal/src" directory, excluding the "lib" directory
for root, dirs, files in os.walk(SRC_PATH, topdown=False):
for name in files:
# Get the path of the file relative to the "Kristal/src" directory
path = os.path.join(root, name)[len(SRC_PATH) + 1:]
# If the file is a .lua file, and it's not in the "lib" directory, add it to the scripts list
if path.endswith(".lua") and not path.startswith("lib"+os.path.sep):
if path in copy:
copy_scripts.append(path)
elif not path in ignore:
scripts.append(path)
# If we have a "library" folder, delete it and all of its contents
if os.path.exists("library"):
for root, dirs, files in os.walk("library", topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir("library")
# Create a new "library" folder
os.mkdir("library")
event_calls = []
# Now we read each script file and process it
for script in scripts:
functions = []
classes = []
aliases = []
# Read the script file
with open(os.path.join(SRC_PATH, script)) as f:
data = f.read()
print(f"Processing {script}...")
# Find all functions in the script file, and add them to the functions list
for match in re.finditer(r"((?:^---.*$\n)+)?^function (\S+\(.*\))", data, flags=re.M):
functions.append((match.group(1), match.group(2)))
# Find the first class definition in the script file, and add it to the classes list
for match in re.finditer(r"((?:^---.*$\n)+)?^local ([^\s,]+)(?:, super)? = (?:(?:Class)|(?:{}))", data, flags=re.M):
classes.append((match.group(1), match.group(2)))
break
# Find all events being called
for match in re.finditer(r"Kristal\.(?:(?:callEvent)|(?:modCall))\(\"(\S+)\"", data):
if not match.group(1) in event_calls:
event_calls.append(match.group(1))
# Find standalone documentation comments (usually aliases)
for match in re.finditer(r"((?:^---.*$[\r\n]*)+)$(?!\n\S)", data, flags=re.M):
aliases.append(match.group(1))
# Create a new file in the "library" folder matching the script file name, creating the directory if it doesn't exist
os.makedirs(os.path.join("library", os.path.dirname(script)), exist_ok=True)
with open(os.path.join("library", script), "w") as f:
# Write the script file name as a comment
normal_path = script.replace("\\", "/")
f.write(
f"""--[[
Generated from {os.path.join(SRC_PATH, script)}
Source: https://github.com/KristalTeam/Kristal/blob/main/src/{normal_path}
]]""")
f.write("\n\n---@meta\n\n")
# Write the classes
for class_ in classes:
if class_[0] != None:
# Write the documentation comments, if any exist
f.write(class_[0])
# Write the class definition
f.write(f"{class_[1]} = {{}}\n\n")
# Write the aliases
for alias in aliases:
if alias.startswith("---@diagnostic"):
continue
f.write(alias)
f.write("\n\n")
# Write the functions
for function in functions:
# Ignore love callbacks
if "love." in function[1]:
continue
if function[0] != None:
# Write the documentation comments, if any exist
f.write(function[0])
# Write the function definition
f.write(f"function {function[1]} end\n\n")
# Also process each file that should be directly copied
for script in copy_scripts:
print(f"Copying {script}...")
# Read the contents of the script
f = open(os.path.join(SRC_PATH, script), "r")
script_text = f.read()
f.close()
# Create a new file in the "library" folder matching the script file name, creating the directory if it doesn't exist
os.makedirs(os.path.join("library", os.path.dirname(script)), exist_ok=True)
with open(os.path.join("library", script), "w") as f:
# Write the script file name as a comment
normal_path = script.replace("\\", "/")
f.write(
f"""--[[
Generated from {os.path.join(SRC_PATH, script)}
Source: https://github.com/KristalTeam/Kristal/blob/main/src/{normal_path}
]]""")
# Append the meta annotation to the file
f.write("\n\n---@meta\n\n")
# Copy the script to the output file
f.write(script_text)
# Temp solution to Mod global
# TODO: Document these manually?
with open(os.path.join("library", "mod.lua"), "w") as f:
f.write(
"""--[[
Generated from Kristal mod event calls
]]""")
f.write("\n\n---@meta\n\n")
f.write("Mod = {}\n\n")
for event in event_calls:
f.write(f"function Mod:{event}(...) end\n\n")