@@ -8,12 +8,6 @@
9import Foundation
9import Foundation
11−typealias Lines = [String]
12−typealias Element = [String]
13−let commentChars = CharacterSet.init(charactersIn: "#/")
14−let styleCharecters = CharacterSet.init(charactersIn: "_*")
17enum BracketStyle {
11enum BracketStyle {
18 case square
12 case square
19 case round
13 case round
@@ -67,11 +61,11 @@ default:
67 if let surl = args.popFirst() {
61 if let surl = args.popFirst() {
68 outputUrl = URL(fileURLWithPath: surl)
62 outputUrl = URL(fileURLWithPath: surl)
70− case "-b:s":
64+ case "-s":
71 style = .square
65 style = .square
72− case "-b:r":
66+ case "-r":
73 style = .round
67 style = .round
74− case "-b:l":
68+ case "-l":
75 style = .line
69 style = .line
@@ -87,6 +81,7 @@ enum ElementStyle: String {
87 case italic = "italic"
81 case italic = "italic"
88 case boldItalic = "bold-italic"
82 case boldItalic = "bold-italic"
84+let styleCharecters = CharacterSet.init(charactersIn: "_*")
90extension String.SubSequence {
85extension String.SubSequence {
91 var style: ElementStyle {
86 var style: ElementStyle {
92 let num = self.prefix(while: {styleCharecters.contains($0.unicodeScalars.first!)}).count
87 let num = self.prefix(while: {styleCharecters.contains($0.unicodeScalars.first!)}).count
@@ -105,209 +100,79 @@ extension String.SubSequence {
105 return self.trimmingCharacters(in: styleCharecters)
100 return self.trimmingCharacters(in: styleCharecters)
109−func process(element: Element) -> String {
103+func process(mth: String) -> String {
110− var out = ""
104+ let whitespace = CharacterSet.whitespaces
112− var inMatrix = false
114 var seperated = false
106 var seperated = false
115− var afterSeparator: [Substring] = []
107+ var afterSeparator: [String.SubSequence] = []
117− var small = false
109+ var out = "<math>"
118−
110+ let lines = mth.split(separator: "\n", omittingEmptySubsequences: false)
119− let arrows = CharacterSet.init(charactersIn: "⟺⟷⟼⟻⟶⟹⟵⟸")
111+ .map {$0.trimmingCharacters(in: .whitespaces)}
120−
112+ var insideMatrix = false
121− let nEl = element.map { (el) -> String in
123− case let l where l.last == ">" && l.first == "<" && l.dropLast().dropFirst().filter({$0 == "="}).count > 0:
126− case let l where l.last == ">" && l.first == "<" && l.dropLast().dropFirst().filter({$0 == "-"}).count > 0:
129− case let l where l.last == ">" && l.first == "|" && l.dropLast().dropFirst().filter({$0 == "-"}).count > 0:
132− case let l where l.last == "|" && l.first == "<" && l.dropLast().dropFirst().filter({$0 == "-"}).count > 0:
135− case let l where l.last == ">" && l.dropLast().filter({$0 == "-"}).count > 0:
138− case let l where l.last == ">" && l.dropLast().filter({$0 == "="}).count > 0:
141− case let l where l.first == "<" && l.dropFirst().filter({$0 == "-"}).count > 0:
144− case let l where l.first == "<" && l.dropFirst().filter({$0 == "="}).count > 0:
152− func process(lineElement: Substring, withAttributes attributes: String = "", style: ElementStyle = .none) -> Substring {
153− func extractNextElement(from line: Substring) -> (element: Substring, left: Substring) {
154− if line.first != "(" {
155− var i = line.startIndex
156− var el: Substring = ""
157− while i < line.endIndex && CharacterSet.alphanumerics.contains(line[i].unicodeScalars.first!) {
159− i = line.index(after: i)
161− return (el, line[i...])
164− var i = line.startIndex
165− var el: Substring = ""
166− while i < line.endIndex {
175− i = line.index(after: i)
182− print("Mismatched brackets")
185− return (el.dropFirst(), line[i...])
188− var i = lineElement.startIndex
189− while i < lineElement.endIndex {
190− switch lineElement[i] {
192− let parts = extractNextElement(from: lineElement[lineElement.index(after: i)...])
193− return "<mo mathvariant=\"\(style.rawValue)\" \(attributes)>\(lineElement[..<i].filter({$0 != "\\"}))</mo>" + "<msup><mo></mo><mn>\(parts.element)</mn></msup>" + process(lineElement: parts.left, withAttributes: attributes, style: style)
195− let parts = extractNextElement(from: lineElement[lineElement.index(after: i)...])
196− return "<mo mathvariant=\"\(style.rawValue)\" \(attributes)>\(lineElement[..<i].filter({$0 != "\\"}))</mo>" + "<mover accent=\"true\"><mrow><mo>\(parts.element)</mo></mrow><mo>_</mo></mover>" + process(lineElement: parts.left, withAttributes: attributes, style: style)
198− i = lineElement.index(after: i)
200− let parts = extractNextElement(from: lineElement[lineElement.index(after: i)...])
201− return "<mo mathvariant=\"\(style.rawValue)\" \(attributes)>\(lineElement[..<i].filter({$0 != "\\"}))</mo>" + "<msub><mo></mo><mn>\(parts.element)</mn></msub>" + process(lineElement: parts.left, withAttributes: attributes, style: style)
205− i = lineElement.index(after: i)
207− return Substring("<mo mathvariant=\"\(style.rawValue)\" \(attributes)>\(lineElement.filter({$0 != "\\"}))</mo>")
209− func process(line: Substring) {
113+ func pureProcess(line: Substring) {
210 out.append("<mtr>")
114 out.append("<mtr>")
211 for element in line.split(
115 for element in line.split(
212− whereSeparator: {c in CharacterSet.whitespaces.contains(c.unicodeScalars.first!)}) {
116+ whereSeparator: {c in whitespace.contains(c.unicodeScalars.first!)}) {
213 switch element {
117 switch element {
214 case "_":
118 case "_":
215 out.append("<mtd><mspace height=\"0.8em\"/></mtd>")
119 out.append("<mtd><mspace height=\"0.8em\"/></mtd>")
217 let eStyle = element.style
121 let eStyle = element.style
218− out.append("<mtd>\(process(lineElement: Substring(element.trimmingStyleCharecters()), withAttributes: "height=\"0.8em\"", style: eStyle))</mtd>")
122+ out.append("<mtd><mn mathvariant=\"\(eStyle.rawValue)\" height=\"0.8em\">\(element.trimmingStyleCharecters())</mn></mtd>")
221 out.append("</mtr>")
125 out.append("</mtr>")
223− func process(comment: String) {
127+ func checkInsideMatrix() {
224− if comment.hasPrefix("#") {
128+ if insideMatrix {
225− out.append("<!-- \(comment.trimmingCharacters(in: commentChars).trimmingCharacters(in: .whitespaces)) -->")
129+ if seperated {
130+ out.append("</mtable><mo>|</mo><mtable>")
131+ for line in afterSeparator {
132+ pureProcess(line: line)
135+ out.append("</mtable><mo>\(style.closing)</mo></mrow>")
136+ insideMatrix = false
228−
141+ func process(line: String.SubSequence) {
147+ out.append("<mrow><mo>\(style.opening)</mo><mtable>")
150+ pureProcess(line: line)
229− for line in nEl {
154+ for line in lines {
230− if inMatrix {
155+ if !insideMatrix {
231− if first && line.contains("|") {
156+ if lines.first?.contains("|") == true {
232 seperated = true
157 seperated = true
235− case "]":
160+ if line == "" {
237− out.append("</mtable><mo stretchy=\"true\">|</mo><mtable>")
238− for line in afterSeparator {
239− process(line: line)
161+ process(line: Substring(line))
242− out.append("</mtable><mo stretchy=\"true\">\(style.closing)</mo></mrow></mtd></mtr>")
247− if seperated {
162+ } else if seperated {
248− let split = line.split(separator: "|", maxSplits: 1, omittingEmptySubsequences: false)
163+ let split = line.split(separator: "|", maxSplits: 1, omittingEmptySubsequences: false)
249− if split.count != 2 {
164+ if split.count != 2 {
250− print("Inconsistent syntax. The `|` seperator isn't consistent within a matrix.")
165+ print("Inconsistent syntax")
253− process(line: split[0])
254− afterSeparator.append(split[1])
256− process(line: Substring(line))
168+ process(line: split[0])
169+ afterSeparator.append(split[1])
260− switch line {
171+ process(line: Substring(line))
261− case let l where l.hasPrefix("//"):
263− case let l where l.hasPrefix("#"):
264− out.append("</mtable></math>\n\n")
266− out.append("\n\n<math><mtable>")
267− break // TODO: Figure out what to do
269− out.append("<mtr><mtd><mrow><mo stretchy=\"true\">\(style.opening)</mo><mtable>")
275− out.append("</mtable><mtable>")
279− case let l where arrows.contains(l.first!.unicodeScalars.first!):
280− out.append("<mtr><mtd><mo>\(line)</mo></mtd></mtr>")
282− out.append("<mtr><mtd>\(small ? "<mstyle scriptlevel=\"1\">" : "")\(process(lineElement: Substring(line)))\(small ? "</mstyle>" : "")</mtd></mtr>")
290−func process(mth: String) -> String {
292− .split(separator: "\n", omittingEmptySubsequences: false)
293− .map({$0.trimmingCharacters(in: .whitespaces)})
295− var i = l.startIndex
296− for u in 0..<max(0, l.count - 1) {
297− if l[i] == "/" && l[l.index(after: i)] == "/" {
298− return String(l.dropLast(l.count - u))
300− i = l.index(after: i)
304− .split(separator: "")
305− var out = "<math><mtable>"
306− for el in elements {
307− out.append(process(element: Array(el)))
308− out.append("</mtable><mtable>")
310− out.append("</mtable></math>")
175+ out.append("</math>")
311 return out
176 return out