git.iko.soy/SourceDocsSwift
on 17dbfa5 help sign in
README.md−36
since splitsnapshots
unifiedsplit
@@ -1,39 +1,3 @@
1# SourceDocsSwift
1# SourceDocsSwift
2
2
3Генернирует LaTeX-таблицы всех классов, структур и их полей и методов из проекта Xcode для вставки в техническую документацию.
3Генернирует LaTeX-таблицы всех классов, структур и их полей и методов из проекта Xcode для вставки в техническую документацию.
4−
5−## Установка
6−
7−```bash
8−brew install ilyakooo0/tap/sourceDocsSwift
9−```
10−
11−## Использование
12−
13−```bash
14−sourceDocsSwift -i path/to/XcodePrjectDirectory/ -o path/to/output/doc.tex -s latex -l 1
15−```
16−
17−```bash
18−sourceDocsSwift -s tech -l 2
19−```
20−
21−По умолчанию ищет проект в текущей папке и пишет результат в эту же папку в файл `doc.tex`.
22−
23−В LaTeX документ можно вставить просто положив рядом с щсновным `.tex` документом и вставив в нужное место:
24−
25−```LaTeX
26−\include{doc}
27−```
28−
29−Так же требуется пакет `longtable`. Если в вашем шаблоне этого еще нигде нет, то где-нибудь в преамбуле надо вставить:
30−
31−```LaTeX
32−\usepackage{longtable}
33−```
34−### Параметры
35−
36−- `[-s | --style] [latex | tech]` -- стиль команды самого внешнего уровня
37−- `[-l | --level] [1 | 2 | 3]` -- отступ в уровнях
38−- `[-i | --input] path/to/projectDirectory` -- путь к папке с проектом
39−- `[-o | --output] path/to/output.tex` -- путь к фалу, в который писать результат
SourceDocsSwift/TeXer.swift+13−50
@@ -7,26 +7,26 @@
7//
7//
8
8
9struct TeXer {
9struct TeXer {
10− static func convert(objects: [Object], with style: TexType = .laTeX(2)) -> String {
10+ static func convert(objects: [Object]) -> String {
11 return """
11 return """
12− \\\(style.section(for: 1)){Описание классов и структур}
12+ \\subsection{Описание классов и структур}
13
13
14− \\begin{longtable}{| >{\\raggedright\\arraybackslash}p{0.55\\textwidth} | p{0.4\\textwidth}|}
14+ \\begin{longtable}{|p{0.55\\textwidth} | p{0.4\\textwidth}|}
15 \\hline
15 \\hline
16 \\textbf{Класс или стркура} & \\textbf{Описание} \\\\ \\hline
16 \\textbf{Класс или стркура} & \\textbf{Описание} \\\\ \\hline
17− \( objects.map {"\\texttt{\($0.declaration)} & {\\color{red} TODO} \\\\ \\hline"} .joined(separator: "\n") )
17+ \( objects.map {"\\texttt{\($0.declaration)} & \($0.documentation ?? "{\\color{red} TODO}") \\\\ \\hline"} .joined(separator: "\n") )
18 \\end{longtable}
18 \\end{longtable}
19+
19
20
20−
21− \\\(style.section(for: 1)){Описание полей классов и структур}
21+ \\subsection{Описание полей классов и структур}
22
22
23 \(
23 \(
24 objects.compactMap {
24 objects.compactMap {
25 if $0.fields.count > 0 {
25 if $0.fields.count > 0 {
26 return """
26 return """
27− \\\(style.section(for: 2))*{\\texttt{\($0.declaration)}}
27+ \\subsubsection{\\texttt{\($0.declaration)}}
28
28
29− \\begin{longtable}{| >{\\raggedright\\arraybackslash}p{0.55\\textwidth} | p{0.4\\textwidth}|}
29+ \\begin{longtable}{|p{0.55\\textwidth} | p{0.4\\textwidth}|}
30 \\hline
30 \\hline
31 \\textbf{Поле} & \\textbf{Описание} \\\\ \\hline
31 \\textbf{Поле} & \\textbf{Описание} \\\\ \\hline
32 \( $0.fields.map {"\\texttt{\($0.declaration.prefix {$0 != "="})} & {\\color{red} TODO} \\\\ \\hline"} .joined(separator: "\n") )
32 \( $0.fields.map {"\\texttt{\($0.declaration.prefix {$0 != "="})} & {\\color{red} TODO} \\\\ \\hline"} .joined(separator: "\n") )
@@ -38,19 +38,19 @@ struct TeXer {
38 }
38 }
39 } .joined(separator: "\n")
39 } .joined(separator: "\n")
40 )
40 )
41−
41+
42− \\\(style.section(for: 1)){Описание методов классов и структур}
42+ \\subsection{Описание методов классов и структур}
43
43
44 \(
44 \(
45 objects.compactMap {
45 objects.compactMap {
46 if $0.methods.count > 0 {
46 if $0.methods.count > 0 {
47 return """
47 return """
48− \\\(style.section(for: 2))*{\\texttt{\($0.declaration)}}
48+ \\subsubsection{\\texttt{\($0.declaration)}}
49
49
50− \\begin{longtable}{| >{\\raggedright\\arraybackslash}p{0.55\\textwidth} | p{0.4\\textwidth}|}
50+ \\begin{longtable}{|p{0.55\\textwidth} | p{0.4\\textwidth}|}
51 \\hline
51 \\hline
52 \\textbf{Метод} & \\textbf{Описание} \\\\ \\hline
52 \\textbf{Метод} & \\textbf{Описание} \\\\ \\hline
53− \( $0.methods.map {"\\texttt{\($0.declaration)} & {\\color{red} TODO} \\\\ \\hline"} .joined(separator: "\n") )
53+ \( $0.methods.map {"\\texttt{\($0.declaration)} & \($0.documentation ?? "{\\color{red} TODO}") \\\\ \\hline"} .joined(separator: "\n") )
54 \\end{longtable}
54 \\end{longtable}
55
55
56 """
56 """
@@ -61,41 +61,4 @@ struct TeXer {
61 )
61 )
62 """
62 """
63 }
63 }
64−
65− enum TexType {
66− case techDoc(Int)
67− case laTeX(Int)
68−
69− func section(`for` level: Int) -> String {
70− switch self {
71− case .laTeX(let i):
72− return String(repeating: "sub", count: i+level-2).appending("section")
73− case .techDoc(let i):
74− switch i+level-2 {
75− case 0:
76− return "addition"
77− default:
78− return TexType.laTeX(i).section(for: level)
79− }
80− }
81− }
82− var levelOffset: Int {
83− get {
84− switch self {
85− case .laTeX(let i):
86− return i
87− case .techDoc(let i):
88− return i
89− }
90− }
91− set {
92− switch self {
93− case .laTeX(_):
94− self = .laTeX(newValue)
95− case .techDoc(_):
96− self = .techDoc(newValue)
97− }
98− }
99− }
100− }
101}
64}
SourceDocsSwift/main.swift+13−59
@@ -8,76 +8,36 @@
8
8
9import Foundation
9import Foundation
10
10
11+//let directory = "/Users/ilya/Developer/Dotrix/Dotrix/"
12+//let output = "/Users/ilya/Desktop/foo.tex"
13+
11let args = Array(CommandLine.arguments.dropFirst())
14let args = Array(CommandLine.arguments.dropFirst())
12−//let temp = FileManager.default.temporaryDirectory.appendingPathComponent("SourceDocsSwift/build\(Date().timeIntervalSince1970)", isDirectory: true)
15+let temp = FileManager.default.temporaryDirectory.appendingPathComponent("SourceDocsSwift/build\(Date().timeIntervalSince1970)")
16+
17+print(temp)
13
18
14var output = "docs.tex"
19var output = "docs.tex"
15var directory: String?
20var directory: String?
16−var style: TeXer.TexType = .laTeX(2)
17
21
18var i = 0
22var i = 0
19while i < args.count {
23while i < args.count {
20 switch args[i] {
24 switch args[i] {
21− case "-o", "--output":
25+ case "-o":
22 if i + 1 < args.count {
26 if i + 1 < args.count {
23 i += 1
27 i += 1
24 output = args[i]
28 output = args[i]
25 }
29 }
26− case "-i", "--input":
30+ case "-i":
27 if i + 1 < args.count {
31 if i + 1 < args.count {
28 i += 1
32 i += 1
29 directory = args[i]
33 directory = args[i]
30 }
34 }
31− case "-s", "--style":
32− if i + 1 < args.count {
33− i += 1
34− switch args[i].lowercased() {
35− case "latex", "xetex", "tex":
36− style = .laTeX(style.levelOffset)
37− case "tech", "techdoc", "techdocs":
38− style = .techDoc(style.levelOffset)
39− default:
40− print("""
41− That is not a valid style.
42−
43− Valid styles are:
44− latex
45− techdoc
46− """)
47− exit(1)
48− }
49− }
50− case "-l", "--level":
51− if i + 1 < args.count {
52− i += 1
53− guard let l = Int(args[i]) else {
54− print("""
55− That is not a valid int.
56− """)
57− exit(1)
58− }
59− if l < 1 {
60− print("""
61− Level must be greater or equal to 1.
62− """)
63− exit(1)
64− }
65− style.levelOffset = l
66− }
67 default:
35 default:
68 break
36 break
69 }
37 }
70 i += 1
38 i += 1
71}
39}
72
40
73−var outputIsDirectory: ObjCBool = false
74−
75−FileManager.default.fileExists(atPath: output, isDirectory: &outputIsDirectory)
76−
77−if outputIsDirectory.boolValue {
78− output.append("/docs.tex")
79−}
80−
81let decoder = JSONDecoder()
41let decoder = JSONDecoder()
82
42
83guard let xcbTagetData = Shell.launch(executable: "/usr/bin/xcodebuild", arguments: ["-list", "-json"], launchDirectory: directory) else {
43guard let xcbTagetData = Shell.launch(executable: "/usr/bin/xcodebuild", arguments: ["-list", "-json"], launchDirectory: directory) else {
@@ -99,8 +59,8 @@ let targets = xcbResponse.targets
99var files: [String: [Object]] = [:]
59var files: [String: [Object]] = [:]
100
60
101for target in targets {
61for target in targets {
102−// try? FileManager.default.removeItem(at: temp)
62+ try? FileManager.default.removeItem(at: temp)
103− guard let skResponseData = Shell.launch(executable: "/usr/local/bin/sourcekitten", arguments: ["doc", "--", "-target", target], launchDirectory: directory) else {
63+ guard let skResponseData = Shell.launch(executable: "/usr/local/bin/sourcekitten", arguments: ["doc", "--", "-target", target, "CONFIGURATION_BUILD_DIR=\(temp)"], launchDirectory: directory) else {
104 print("""
64 print("""
105 Make sure sourcekitten is installed
65 Make sure sourcekitten is installed
106
66
@@ -120,15 +80,9 @@ for target in targets {
120
80
121
81
122
82
123−let tex = TeXer.convert(objects: files.flatMap {$0.value}, with: style)
83+let tex = TeXer.convert(objects: files.flatMap {$0.value})
124−do {
84+
125− try tex.write(toFile: output, atomically: true, encoding: .utf8)
85+try? tex.write(toFile: output, atomically: true, encoding: .utf8)
126−} catch {
127− print("""
128− There was an error writing the outuput file.
129− """)
130− exit(1)
131−}
132
86
133print("""
87print("""
134+-------+
88+-------+