Проверка шаблона шины для iOS
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

generate 10KB

il y a 11 mois
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. from argparse import ArgumentParser
  5. parser = ArgumentParser(prog='generate v1')
  6. parser.add_argument('module', type=str,
  7. help='the name of the module to generate')
  8. parser.add_argument('-i', '--input', type=str,
  9. help='The path and name of the input file')
  10. parser.add_argument('-o', '--output', type=str,
  11. help='The path of the output files')
  12. args = parser.parse_args()
  13. DIR = os.path.dirname(os.path.realpath(sys.argv[0]))
  14. MODULE = args.module
  15. def isNotKeyword(str):
  16. keywords = [
  17. "core",
  18. "ex",
  19. "recent",
  20. "service",
  21. "set",
  22. "toggle",
  23. "toggleNil",
  24. "vm",
  25. "$vm",
  26. "world",
  27. ]
  28. return str not in keywords
  29. class CoreAction:
  30. def __init__(self, func, sink):
  31. self.func = func
  32. self.sink = sink
  33. def code(self):
  34. return f"""
  35. p.ctrl.m
  36. .compactMap {{ {self.func}($0) }}
  37. .receive(on: DispatchQueue.main)
  38. .sink {{ [weak core = p.core] v in {self.sink} }}
  39. .store(in: &p.core.subscriptions)
  40. """.replace("\n\n", "\n")
  41. class CorePipe:
  42. def __init__(self, name, props):
  43. self.name = name
  44. self.props = props
  45. self.resetMethod()
  46. self.resetDbg()
  47. self.resetSrc()
  48. self.resetExName()
  49. self.resetSteps()
  50. def code(self):
  51. return f"""
  52. p.ctrl.{self.method}(
  53. dbg: "{self.dbg}",
  54. sub: &p.core.subscriptions,
  55. {self.src}.eraseToAnyPublisher(),
  56. {self.steps}
  57. )
  58. """.replace("\n\n", "\n")
  59. def resetDbg(self):
  60. capitals = [l for l in self.name if l.isupper()]
  61. # Нет заглавных.
  62. if len(capitals) == 0:
  63. self.dbg = self.name
  64. return
  65. # Есть заглавные.
  66. firstCap = self.name.find(capitals[0])
  67. self.dbg = self.name[:firstCap] + "".join(capitals)
  68. def resetExName(self):
  69. firstLetter = self.name[0].capitalize()
  70. self.exName = f"""ex{firstLetter}{self.name[1:]}"""
  71. def resetMethod(self):
  72. if "toggle" in self.props:
  73. self.method = "pipe"
  74. else:
  75. self.method = "pipeValue"
  76. def resetSrc(self):
  77. if "core" in self.props:
  78. self.src = "p.core." + self.name
  79. elif "world" in self.props:
  80. self.src = "p.world." + self.name
  81. elif "vm" in self.props:
  82. self.src = "p.core.vm." + self.name
  83. elif "$vm" in self.props:
  84. self.src = "p.core.vm.$" + self.name
  85. else:
  86. # Если это что-то неизвестное заранее, то ищем строку,
  87. # отличную от известных ключевых слов.
  88. self.src = next(filter(isNotKeyword, self.props))
  89. def resetSteps(self):
  90. if "recent" and "ex" in self.props:
  91. self.steps = f"""
  92. {{
  93. $0.{self.name}.value = $1
  94. $0.{self.name}.isRecent = true
  95. }},
  96. {{
  97. $0.{self.name}.isRecent = false
  98. $0.{self.exName} = $1
  99. }}
  100. """
  101. elif "recent" in self.props:
  102. self.steps = f"""
  103. {{
  104. $0.{self.name}.value = $1
  105. $0.{self.name}.isRecent = true
  106. }},
  107. {{ m, _ in m.{self.name}.isRecent = false }}
  108. """
  109. elif "set" in self.props:
  110. self.steps = f"""
  111. {{ $0.{self.name} = $1 }}
  112. """
  113. elif "toggle" in self.props:
  114. self.steps = f"""
  115. {{ $0.{self.name} = true }},
  116. {{ $0.{self.name} = false }}
  117. """
  118. elif "toggleNil" in self.props:
  119. self.steps = f"""
  120. {{ $0.{self.name} = $1 }},
  121. {{ m, _ in m.{self.name} = nil }}
  122. """
  123. class ServiceAction:
  124. def __init__(self, func, sink):
  125. self.func = func
  126. self.sink = sink
  127. def code(self):
  128. return f"""
  129. sp.ctrl.m
  130. .compactMap {{ {self.func}($0) }}
  131. .receive(on: DispatchQueue.main)
  132. .sink {{ v in {self.sink} }}
  133. .store(in: &sp.service.subscriptions)
  134. """.replace("\n\n", "\n")
  135. class ServicePipe:
  136. def __init__(self, name, props):
  137. self.name = name
  138. self.props = props
  139. self.resetMethod()
  140. self.resetDbg()
  141. self.resetSrc()
  142. self.resetExName()
  143. self.resetSteps()
  144. def code(self):
  145. return f"""
  146. sp.ctrl.{self.method}(
  147. dbg: "{self.dbg}",
  148. {self.src}.eraseToAnyPublisher(),
  149. {self.steps}
  150. )
  151. """.replace("\n\n", "\n")
  152. def resetDbg(self):
  153. capitals = [l for l in self.name if l.isupper()]
  154. # Нет заглавных.
  155. if len(capitals) == 0:
  156. self.dbg = self.name
  157. return
  158. # Есть заглавные.
  159. firstCap = self.name.find(capitals[0])
  160. self.dbg = self.name[:firstCap] + "".join(capitals)
  161. def resetExName(self):
  162. firstLetter = self.name[0].capitalize()
  163. self.exName = f"""ex{firstLetter}{self.name[1:]}"""
  164. def resetMethod(self):
  165. if "toggle" in self.props:
  166. self.method = "pipe"
  167. else:
  168. self.method = "pipeValue"
  169. def resetSrc(self):
  170. if "service" in self.props:
  171. self.src = "sp.service." + self.name
  172. elif "world" in self.props:
  173. self.src = "sp.world." + self.name
  174. else:
  175. # Если это и не сервис, и не мир, то
  176. # ищем строку, отличную от известных ключевых слов.
  177. self.src = next(filter(isNotKeyword, self.props))
  178. def resetSteps(self):
  179. if "recent" and "ex" in self.props:
  180. self.steps = f"""
  181. {{
  182. $0.{self.name}.value = $1
  183. $0.{self.name}.isRecent = true
  184. }},
  185. {{
  186. $0.{self.name}.isRecent = false
  187. $0.{self.exName} = $1
  188. }}
  189. """
  190. elif "recent" in self.props:
  191. self.steps = f"""
  192. {{
  193. $0.{self.name}.value = $1
  194. $0.{self.name}.isRecent = true
  195. }},
  196. {{ m, _ in m.{self.name}.isRecent = false }}
  197. """
  198. elif "set" in self.props:
  199. self.steps = f"""
  200. {{ $0.{self.name} = $1 }}
  201. """
  202. elif "toggle" in self.props:
  203. self.steps = f"""
  204. {{ $0.{self.name} = true }},
  205. {{ $0.{self.name} = false }}
  206. """
  207. elif "toggleNil" in self.props:
  208. self.steps = f"""
  209. {{ $0.{self.name} = $1 }},
  210. {{ m, _ in m.{self.name} = nil }}
  211. """
  212. class State:
  213. isCoreAction = False
  214. isCoreController = False
  215. isServiceAction = False
  216. isServiceController = False
  217. def generatePlatform(coreActions, corePipes, serviceActions, servicePipes):
  218. corePlatform = ""
  219. if len(coreActions) > 0 or len(corePipes) > 0:
  220. corePlatform = f"""
  221. static func setupPlatform(_ p: CoreParameters) {{
  222. {coreActions}
  223. {corePipes}
  224. }}
  225. """
  226. return f"""
  227. // ВНИМАНИЕ: Сгенерировано автоматом, не менять руками!
  228. import Foundation
  229. extension {MODULE} {{
  230. enum SectionGenerated {{
  231. {corePlatform}
  232. static func setupPlatform(_ sp: ServiceParameters) {{
  233. {serviceActions}
  234. {servicePipes}
  235. }}
  236. }}
  237. }}
  238. """
  239. def generateCoreAction(ln):
  240. parts = ln.split(": ")
  241. if len(parts) != 2:
  242. return None
  243. func = parts[0].lstrip()
  244. sink = parts[1].rstrip()
  245. action = CoreAction(func, sink)
  246. return action.code()
  247. def generateCorePipe(ln):
  248. parts = ln.split(": [")
  249. if len(parts) != 2:
  250. return None
  251. name = parts[0].lstrip()
  252. props = parts[1][:-1].split(", ")
  253. pipe = CorePipe(name, props)
  254. return pipe.code()
  255. def generateServiceAction(ln):
  256. parts = ln.split(": ")
  257. if len(parts) != 2:
  258. return None
  259. func = parts[0].lstrip()
  260. sink = parts[1].rstrip()
  261. action = ServiceAction(func, sink)
  262. return action.code()
  263. def generateServicePipe(ln):
  264. parts = ln.split(": [")
  265. if len(parts) != 2:
  266. return None
  267. name = parts[0].lstrip()
  268. props = parts[1][:-1].split(", ")
  269. pipe = ServicePipe(name, props)
  270. return pipe.code()
  271. def readFile(fileName):
  272. lines = []
  273. with open(fileName) as file:
  274. for line in file:
  275. lines.append(line.rstrip())
  276. return lines
  277. def resetState(ln):
  278. if ln.startswith("ca:"):
  279. state.isCoreAction = True
  280. state.isCoreController = False
  281. state.isServiceAction = False
  282. state.isServiceController = False
  283. elif ln.startswith("cp:"):
  284. state.isCoreAction = False
  285. state.isCoreController = True
  286. state.isServiceAction = False
  287. state.isServiceController = False
  288. elif ln.startswith("sa:"):
  289. state.isCoreAction = False
  290. state.isCoreController = False
  291. state.isServiceAction = True
  292. state.isServiceController = False
  293. elif ln.startswith("sp:"):
  294. state.isCoreAction = False
  295. state.isCoreController = False
  296. state.isServiceAction = False
  297. state.isServiceController = True
  298. return state
  299. def saveFile(fileName, data):
  300. with open(fileName, "w") as file:
  301. file.write(data)
  302. def validateVersion(ln):
  303. if ln.startswith("version: 1") == False:
  304. print("ERROR: Invalid version")
  305. sys.exit(1)
  306. # Main
  307. state = State()
  308. print(f"Generating platform for module '{MODULE}'...")
  309. fileIn = args.input or f"{DIR}/../../../Modules/{MODULE}/{MODULE}.yml"
  310. fileOut = args.output or f"{DIR}/../../../Modules/{MODULE}/src"
  311. fileOut = os.path.join(fileOut, f'{MODULE}.SectionGenerated.swift')
  312. lines = readFile(fileIn)
  313. validateVersion(lines[0])
  314. coreActions = ""
  315. corePipes = ""
  316. serviceActions = ""
  317. servicePipes = ""
  318. for ln in lines:
  319. st = resetState(ln)
  320. if st.isCoreAction:
  321. action = generateCoreAction(ln)
  322. if action:
  323. coreActions += action
  324. if st.isCoreController:
  325. pipe = generateCorePipe(ln)
  326. if pipe:
  327. corePipes += pipe
  328. if st.isServiceAction:
  329. action = generateServiceAction(ln)
  330. if action:
  331. serviceActions += action
  332. if st.isServiceController:
  333. pipe = generateServicePipe(ln)
  334. if pipe:
  335. servicePipes += pipe
  336. result = generatePlatform(coreActions, corePipes, serviceActions, servicePipes)
  337. saveFile(fileOut, result)