Skip to content

Instantly share code, notes, and snippets.

@bolivarbryan
Created November 15, 2018 19:12
Show Gist options
  • Save bolivarbryan/f924073644aec72cf0670e29d27c7cea to your computer and use it in GitHub Desktop.
Save bolivarbryan/f924073644aec72cf0670e29d27c7cea to your computer and use it in GitHub Desktop.
String parser using XML like formatter
import UIKit
import PlaygroundSupport
class Stack: CustomStringConvertible {
var tag: String
var open: Int
var close: Int
init(tag: String, open: Int, close: Int) {
self.tag = tag
self.open = open
self.close = close
}
var description: String {
return "\((tag, open, close))"
}
}
class StringFormatter {
private var bufferText = ""
private var stack: [Stack] = []
enum Tag: String {
case a = "a"
case b = "b"
case c = "c"
func attKey() -> (NSAttributedStringKey, Any) {
switch self {
case .a:
return (.backgroundColor, UIColor.red)
case .b:
return (.foregroundColor, UIColor.blue)
case .c:
return (.font, UIFont.italicSystemFont(ofSize: 15))
}
}
}
func transformText(initalText: String) -> NSMutableAttributedString {
formatString(text: initalText, idx: 0, bufferText: "", stack: [])
let att = NSMutableAttributedString(string: bufferText)
for s in stack {
if let tag = Tag(rawValue: s.tag) {
let r = NSRange(location: s.open, length: s.close - s.open)
att.addAttribute(tag.attKey().0, value: tag.attKey().1, range: r)
}
}
return att
}
private func formatString(text: String, idx: Int, bufferText: String, stack: [Stack]) {
if text.count == 0 {
self.bufferText = bufferText
self.stack = stack
return
}
let index = text.index(text.startIndex, offsetBy: 2)
let mySubstring = text[..<index]
if "\(mySubstring)" == "</" {
//1.3
var txt = String(text.dropFirst(2))
var tag = ""
while txt.count > 0 {
if txt.first! != ">" {
//1.1.1
tag.append(txt.first!)
} else {
//1.1.2
break
}
txt = String(txt.dropFirst())
}
for t in stack.reversed() {
if t.tag == tag {
t.close = bufferText.count
}
}
formatString(text: String(txt.dropFirst()), idx: idx + 1, bufferText: bufferText, stack: stack)
} else if "\(text.first!)" == "<" {
//1.1
var txt = String(text.dropFirst())
var tag = ""
while txt.count > 0 {
if txt.first! != ">" {
//1.1.1
tag.append(txt.first!)
} else {
//1.1.2
break
}
txt = String(txt.dropFirst())
}
var stk = stack
stk.append(Stack(tag: tag, open: bufferText.count, close: bufferText.count))
formatString(text: String(txt.dropFirst()), idx: idx + 1, bufferText: bufferText, stack: stk)
} else {
//1.2
var txt = bufferText
txt.append(text.first!)
formatString(text: String(text.dropFirst()), idx: idx + 1, bufferText: txt, stack: stack)
}
}
}
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let label = UILabel()
label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
label.textColor = .black
let txt = "<c>hello <a>world</a></c>"
let str = StringFormatter()
print(str.transformText(initalText: txt))
label.attributedText = str.transformText(initalText: txt)
view.addSubview(label)
self.view = view
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment