-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
ragemp.py
101 lines (69 loc) · 3.01 KB
/
ragemp.py
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
"""
C# File merger for RageMP.
Copyright (c) 2020-2022 Hannele Ruiz
Under the MIT License
"""
import logging
import re
import sys
from datetime import datetime
from pathlib import Path
HEADER = "// LemonUI for RageMP\n// Generated on {date}{comment}\n\n#define RAGEMP\n\n{statements}{code}\n"
LOGGER = logging.getLogger("merger")
RE_SPECIFIC_USINGS = re.compile("#e?l?if RAGEMP\n([a-zA-Z0-9; . =\n]*)\n(?:#elif|#endif)")
RE_GENERAL_USINGS = re.compile("(?:^|#endif\n)([a-zA-Z0-9; .\n=]*);")
RE_USING = re.compile("using ([A-Za-z0-9.= ]+);?", re.MULTILINE)
RE_NAMESPACE = re.compile("(namespace LemonUI[.A-Za-z /]*\n{[\\s\\S]*})")
RE_SKIP = re.compile("// NO MERGE")
def process_usings(match: re.Match):
if match is None:
return
for main_group in match.groups():
for statement_group in RE_USING.finditer(main_group):
if statement_group is None:
continue
for statement in statement_group.groups():
yield statement
def main():
logging.basicConfig(level=logging.INFO)
arguments = sys.argv
LOGGER.info("Launch Arguments: " + " ".join(f"\"{x}\"" for x in arguments))
if len(arguments) > 4 or len(arguments) < 3:
LOGGER.critical("Expected 2 or 3 arguments: [code source] [code output] {comment}")
sys.exit(1)
code_path = Path(arguments[1])
code_output = Path(arguments[2])
comment = f"\n// {arguments[3]}" if len(arguments) > 3 else ""
strings = ""
namespaces = []
LOGGER.info("Starting the processing of the files")
for path in code_path.rglob("*.cs"):
with path.open(encoding="utf-8") as file:
content = file.read()
relative_path = path.relative_to(code_path)
if RE_SKIP.match(content):
LOGGER.info(f"Ignoring {relative_path}: File marked as to be skipped")
continue
LOGGER.info(f"Processing {relative_path}")
namespaces_found = RE_NAMESPACE.search(content).groups()
if namespaces_found is None:
LOGGER.warning("File does not contains usable code")
continue
specific = list(process_usings(RE_SPECIFIC_USINGS.search(content)))
general = list(process_usings(RE_GENERAL_USINGS.search(content)))
LOGGER.info(f"Found {len(specific)} + {len(general)} using statements")
namespaces.extend(specific)
namespaces.extend(general)
namespace = namespaces_found[0]
strings = f"{strings}\n\n// {relative_path}\n{namespace}"
namespaces = list(set(namespaces))
namespaces.sort()
LOGGER.info(f"Adding {len(namespaces)} unique using statements: " + ", ".join(namespaces))
statements = "\n".join(f"using {x};" for x in namespaces)
code_output.parent.mkdir(exist_ok=True)
with open(code_output, mode="w", encoding="utf-8") as file:
text = HEADER.format(date=datetime.now(), statements=statements, code=strings, comment=comment)
file.write(text)
LOGGER.info(f"File exported as {code_output}")
if __name__ == "__main__":
main()