|
|
@@ -0,0 +1,373 @@ |
|
|
|
#!/usr/bin/env python3 |
|
|
|
import os |
|
|
|
import sys |
|
|
|
from argparse import ArgumentParser |
|
|
|
|
|
|
|
parser = ArgumentParser(prog='generate v1') |
|
|
|
parser.add_argument('module', type=str, |
|
|
|
help='the name of the module to generate') |
|
|
|
parser.add_argument('-i', '--input', type=str, |
|
|
|
help='The path and name of the input file') |
|
|
|
parser.add_argument('-o', '--output', type=str, |
|
|
|
help='The path of the output files') |
|
|
|
|
|
|
|
args = parser.parse_args() |
|
|
|
DIR = os.path.dirname(os.path.realpath(sys.argv[0])) |
|
|
|
MODULE = args.module |
|
|
|
|
|
|
|
def isNotKeyword(str): |
|
|
|
keywords = [ |
|
|
|
"core", |
|
|
|
"ex", |
|
|
|
"recent", |
|
|
|
"service", |
|
|
|
"set", |
|
|
|
"toggle", |
|
|
|
"toggleNil", |
|
|
|
"vm", |
|
|
|
"$vm", |
|
|
|
"world", |
|
|
|
] |
|
|
|
return str not in keywords |
|
|
|
|
|
|
|
class CoreAction: |
|
|
|
def __init__(self, func, sink): |
|
|
|
self.func = func |
|
|
|
self.sink = sink |
|
|
|
|
|
|
|
def code(self): |
|
|
|
return f""" |
|
|
|
p.ctrl.m |
|
|
|
.compactMap {{ {self.func}($0) }} |
|
|
|
.receive(on: DispatchQueue.main) |
|
|
|
.sink {{ [weak core = p.core] v in {self.sink} }} |
|
|
|
.store(in: &p.core.subscriptions) |
|
|
|
""".replace("\n\n", "\n") |
|
|
|
|
|
|
|
class CorePipe: |
|
|
|
def __init__(self, name, props): |
|
|
|
self.name = name |
|
|
|
self.props = props |
|
|
|
self.resetMethod() |
|
|
|
self.resetDbg() |
|
|
|
self.resetSrc() |
|
|
|
self.resetExName() |
|
|
|
self.resetSteps() |
|
|
|
|
|
|
|
def code(self): |
|
|
|
return f""" |
|
|
|
p.ctrl.{self.method}( |
|
|
|
dbg: "{self.dbg}", |
|
|
|
sub: &p.core.subscriptions, |
|
|
|
{self.src}.eraseToAnyPublisher(), |
|
|
|
{self.steps} |
|
|
|
) |
|
|
|
""".replace("\n\n", "\n") |
|
|
|
|
|
|
|
def resetDbg(self): |
|
|
|
capitals = [l for l in self.name if l.isupper()] |
|
|
|
# Нет заглавных. |
|
|
|
if len(capitals) == 0: |
|
|
|
self.dbg = self.name |
|
|
|
return |
|
|
|
# Есть заглавные. |
|
|
|
firstCap = self.name.find(capitals[0]) |
|
|
|
self.dbg = self.name[:firstCap] + "".join(capitals) |
|
|
|
|
|
|
|
def resetExName(self): |
|
|
|
firstLetter = self.name[0].capitalize() |
|
|
|
self.exName = f"""ex{firstLetter}{self.name[1:]}""" |
|
|
|
|
|
|
|
def resetMethod(self): |
|
|
|
if "toggle" in self.props: |
|
|
|
self.method = "pipe" |
|
|
|
else: |
|
|
|
self.method = "pipeValue" |
|
|
|
|
|
|
|
def resetSrc(self): |
|
|
|
if "core" in self.props: |
|
|
|
self.src = "p.core." + self.name |
|
|
|
elif "world" in self.props: |
|
|
|
self.src = "p.world." + self.name |
|
|
|
elif "vm" in self.props: |
|
|
|
self.src = "p.core.vm." + self.name |
|
|
|
elif "$vm" in self.props: |
|
|
|
self.src = "p.core.vm.$" + self.name |
|
|
|
else: |
|
|
|
# Если это что-то неизвестное заранее, то ищем строку, |
|
|
|
# отличную от известных ключевых слов. |
|
|
|
self.src = next(filter(isNotKeyword, self.props)) |
|
|
|
|
|
|
|
def resetSteps(self): |
|
|
|
if "recent" and "ex" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ |
|
|
|
$0.{self.name}.value = $1 |
|
|
|
$0.{self.name}.isRecent = true |
|
|
|
}}, |
|
|
|
{{ |
|
|
|
$0.{self.name}.isRecent = false |
|
|
|
$0.{self.exName} = $1 |
|
|
|
}} |
|
|
|
""" |
|
|
|
elif "recent" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ |
|
|
|
$0.{self.name}.value = $1 |
|
|
|
$0.{self.name}.isRecent = true |
|
|
|
}}, |
|
|
|
{{ m, _ in m.{self.name}.isRecent = false }} |
|
|
|
""" |
|
|
|
elif "set" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ $0.{self.name} = $1 }} |
|
|
|
""" |
|
|
|
elif "toggle" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ $0.{self.name} = true }}, |
|
|
|
{{ $0.{self.name} = false }} |
|
|
|
""" |
|
|
|
elif "toggleNil" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ $0.{self.name} = $1 }}, |
|
|
|
{{ m, _ in m.{self.name} = nil }} |
|
|
|
""" |
|
|
|
|
|
|
|
class ServiceAction: |
|
|
|
def __init__(self, func, sink): |
|
|
|
self.func = func |
|
|
|
self.sink = sink |
|
|
|
|
|
|
|
def code(self): |
|
|
|
return f""" |
|
|
|
sp.ctrl.m |
|
|
|
.compactMap {{ {self.func}($0) }} |
|
|
|
.receive(on: DispatchQueue.main) |
|
|
|
.sink {{ v in {self.sink} }} |
|
|
|
.store(in: &sp.service.subscriptions) |
|
|
|
""".replace("\n\n", "\n") |
|
|
|
|
|
|
|
class ServicePipe: |
|
|
|
def __init__(self, name, props): |
|
|
|
self.name = name |
|
|
|
self.props = props |
|
|
|
self.resetMethod() |
|
|
|
self.resetDbg() |
|
|
|
self.resetSrc() |
|
|
|
self.resetExName() |
|
|
|
self.resetSteps() |
|
|
|
|
|
|
|
def code(self): |
|
|
|
return f""" |
|
|
|
sp.ctrl.{self.method}( |
|
|
|
dbg: "{self.dbg}", |
|
|
|
{self.src}.eraseToAnyPublisher(), |
|
|
|
{self.steps} |
|
|
|
) |
|
|
|
""".replace("\n\n", "\n") |
|
|
|
|
|
|
|
def resetDbg(self): |
|
|
|
capitals = [l for l in self.name if l.isupper()] |
|
|
|
# Нет заглавных. |
|
|
|
if len(capitals) == 0: |
|
|
|
self.dbg = self.name |
|
|
|
return |
|
|
|
# Есть заглавные. |
|
|
|
firstCap = self.name.find(capitals[0]) |
|
|
|
self.dbg = self.name[:firstCap] + "".join(capitals) |
|
|
|
|
|
|
|
def resetExName(self): |
|
|
|
firstLetter = self.name[0].capitalize() |
|
|
|
self.exName = f"""ex{firstLetter}{self.name[1:]}""" |
|
|
|
|
|
|
|
def resetMethod(self): |
|
|
|
if "toggle" in self.props: |
|
|
|
self.method = "pipe" |
|
|
|
else: |
|
|
|
self.method = "pipeValue" |
|
|
|
|
|
|
|
def resetSrc(self): |
|
|
|
if "service" in self.props: |
|
|
|
self.src = "sp.service." + self.name |
|
|
|
elif "world" in self.props: |
|
|
|
self.src = "sp.world." + self.name |
|
|
|
else: |
|
|
|
# Если это и не сервис, и не мир, то |
|
|
|
# ищем строку, отличную от известных ключевых слов. |
|
|
|
self.src = next(filter(isNotKeyword, self.props)) |
|
|
|
|
|
|
|
def resetSteps(self): |
|
|
|
if "recent" and "ex" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ |
|
|
|
$0.{self.name}.value = $1 |
|
|
|
$0.{self.name}.isRecent = true |
|
|
|
}}, |
|
|
|
{{ |
|
|
|
$0.{self.name}.isRecent = false |
|
|
|
$0.{self.exName} = $1 |
|
|
|
}} |
|
|
|
""" |
|
|
|
elif "recent" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ |
|
|
|
$0.{self.name}.value = $1 |
|
|
|
$0.{self.name}.isRecent = true |
|
|
|
}}, |
|
|
|
{{ m, _ in m.{self.name}.isRecent = false }} |
|
|
|
""" |
|
|
|
elif "set" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ $0.{self.name} = $1 }} |
|
|
|
""" |
|
|
|
elif "toggle" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ $0.{self.name} = true }}, |
|
|
|
{{ $0.{self.name} = false }} |
|
|
|
""" |
|
|
|
elif "toggleNil" in self.props: |
|
|
|
self.steps = f""" |
|
|
|
{{ $0.{self.name} = $1 }}, |
|
|
|
{{ m, _ in m.{self.name} = nil }} |
|
|
|
""" |
|
|
|
|
|
|
|
class State: |
|
|
|
isCoreAction = False |
|
|
|
isCoreController = False |
|
|
|
isServiceAction = False |
|
|
|
isServiceController = False |
|
|
|
|
|
|
|
def generatePlatform(coreActions, corePipes, serviceActions, servicePipes): |
|
|
|
corePlatform = "" |
|
|
|
if len(coreActions) > 0 or len(corePipes) > 0: |
|
|
|
corePlatform = f""" |
|
|
|
static func setupPlatform(_ p: CoreParameters) {{ |
|
|
|
{coreActions} |
|
|
|
{corePipes} |
|
|
|
}} |
|
|
|
""" |
|
|
|
|
|
|
|
return f""" |
|
|
|
// ВНИМАНИЕ: Сгенерировано автоматом, не менять руками! |
|
|
|
|
|
|
|
import Foundation |
|
|
|
|
|
|
|
extension {MODULE} {{ |
|
|
|
enum SectionGenerated {{ |
|
|
|
{corePlatform} |
|
|
|
static func setupPlatform(_ sp: ServiceParameters) {{ |
|
|
|
{serviceActions} |
|
|
|
{servicePipes} |
|
|
|
}} |
|
|
|
}} |
|
|
|
}} |
|
|
|
""" |
|
|
|
|
|
|
|
def generateCoreAction(ln): |
|
|
|
parts = ln.split(": ") |
|
|
|
if len(parts) != 2: |
|
|
|
return None |
|
|
|
func = parts[0].lstrip() |
|
|
|
sink = parts[1].rstrip() |
|
|
|
action = CoreAction(func, sink) |
|
|
|
return action.code() |
|
|
|
|
|
|
|
def generateCorePipe(ln): |
|
|
|
parts = ln.split(": [") |
|
|
|
if len(parts) != 2: |
|
|
|
return None |
|
|
|
name = parts[0].lstrip() |
|
|
|
props = parts[1][:-1].split(", ") |
|
|
|
pipe = CorePipe(name, props) |
|
|
|
return pipe.code() |
|
|
|
|
|
|
|
def generateServiceAction(ln): |
|
|
|
parts = ln.split(": ") |
|
|
|
if len(parts) != 2: |
|
|
|
return None |
|
|
|
func = parts[0].lstrip() |
|
|
|
sink = parts[1].rstrip() |
|
|
|
action = ServiceAction(func, sink) |
|
|
|
return action.code() |
|
|
|
|
|
|
|
def generateServicePipe(ln): |
|
|
|
parts = ln.split(": [") |
|
|
|
if len(parts) != 2: |
|
|
|
return None |
|
|
|
name = parts[0].lstrip() |
|
|
|
props = parts[1][:-1].split(", ") |
|
|
|
pipe = ServicePipe(name, props) |
|
|
|
return pipe.code() |
|
|
|
|
|
|
|
def readFile(fileName): |
|
|
|
lines = [] |
|
|
|
with open(fileName) as file: |
|
|
|
for line in file: |
|
|
|
lines.append(line.rstrip()) |
|
|
|
return lines |
|
|
|
|
|
|
|
def resetState(ln): |
|
|
|
if ln.startswith("ca:"): |
|
|
|
state.isCoreAction = True |
|
|
|
state.isCoreController = False |
|
|
|
state.isServiceAction = False |
|
|
|
state.isServiceController = False |
|
|
|
elif ln.startswith("cp:"): |
|
|
|
state.isCoreAction = False |
|
|
|
state.isCoreController = True |
|
|
|
state.isServiceAction = False |
|
|
|
state.isServiceController = False |
|
|
|
elif ln.startswith("sa:"): |
|
|
|
state.isCoreAction = False |
|
|
|
state.isCoreController = False |
|
|
|
state.isServiceAction = True |
|
|
|
state.isServiceController = False |
|
|
|
elif ln.startswith("sp:"): |
|
|
|
state.isCoreAction = False |
|
|
|
state.isCoreController = False |
|
|
|
state.isServiceAction = False |
|
|
|
state.isServiceController = True |
|
|
|
return state |
|
|
|
|
|
|
|
def saveFile(fileName, data): |
|
|
|
with open(fileName, "w") as file: |
|
|
|
file.write(data) |
|
|
|
|
|
|
|
def validateVersion(ln): |
|
|
|
if ln.startswith("version: 1") == False: |
|
|
|
print("ERROR: Invalid version") |
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
|
|
|
# Main |
|
|
|
state = State() |
|
|
|
print(f"Generating platform for module '{MODULE}'...") |
|
|
|
fileIn = args.input or f"{DIR}/../../../Modules/{MODULE}/{MODULE}.yml" |
|
|
|
fileOut = args.output or f"{DIR}/../../../Modules/{MODULE}/src" |
|
|
|
fileOut = os.path.join(fileOut, f'{MODULE}.SectionGenerated.swift') |
|
|
|
lines = readFile(fileIn) |
|
|
|
validateVersion(lines[0]) |
|
|
|
coreActions = "" |
|
|
|
corePipes = "" |
|
|
|
serviceActions = "" |
|
|
|
servicePipes = "" |
|
|
|
for ln in lines: |
|
|
|
st = resetState(ln) |
|
|
|
if st.isCoreAction: |
|
|
|
action = generateCoreAction(ln) |
|
|
|
if action: |
|
|
|
coreActions += action |
|
|
|
if st.isCoreController: |
|
|
|
pipe = generateCorePipe(ln) |
|
|
|
if pipe: |
|
|
|
corePipes += pipe |
|
|
|
if st.isServiceAction: |
|
|
|
action = generateServiceAction(ln) |
|
|
|
if action: |
|
|
|
serviceActions += action |
|
|
|
if st.isServiceController: |
|
|
|
pipe = generateServicePipe(ln) |
|
|
|
if pipe: |
|
|
|
servicePipes += pipe |
|
|
|
result = generatePlatform(coreActions, corePipes, serviceActions, servicePipes) |
|
|
|
saveFile(fileOut, result) |