Compare commits
No commits in common. "5b9f59ec098fe31ed4fcd511067ae5c8610164d4" and "6e4cbfdb6ddbdc7770a1fe25f13f227b6e8118bf" have entirely different histories.
5b9f59ec09
...
6e4cbfdb6d
|
@ -77,25 +77,8 @@ class JavaScriptHighlighter {
|
|||
|
||||
return attributed
|
||||
}
|
||||
|
||||
private func emit(token: TokenType, range: NSRange) {
|
||||
let color: NSColor
|
||||
switch token {
|
||||
case .string:
|
||||
color = .systemRed
|
||||
case .number:
|
||||
color = .systemBlue
|
||||
case .punctuation:
|
||||
color = .systemTeal
|
||||
case .identifier:
|
||||
return
|
||||
}
|
||||
attributed.addAttribute(.foregroundColor, value: color, range: range)
|
||||
}
|
||||
|
||||
private func consumeExpression() {
|
||||
consumeWhitespace()
|
||||
|
||||
guard let char = peek() else { return }
|
||||
|
||||
if identifierStarts.contains(char) {
|
||||
|
@ -119,15 +102,6 @@ class JavaScriptHighlighter {
|
|||
} else {
|
||||
consume()
|
||||
}
|
||||
|
||||
consumeWhitespace()
|
||||
}
|
||||
|
||||
private func consumeWhitespace(newlines: Bool = true) {
|
||||
let charSet = newlines ? CharacterSet.whitespacesAndNewlines : .whitespaces
|
||||
while let char = peek(), charSet.contains(char) {
|
||||
consume()
|
||||
}
|
||||
}
|
||||
|
||||
private func consumeIdentifier() {
|
||||
|
@ -150,7 +124,7 @@ class JavaScriptHighlighter {
|
|||
}
|
||||
}
|
||||
print("Number: \(text[numberStart..<currentIndex])")
|
||||
emit(token: .number, range: range(from: numberStart, to: currentIndex))
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemBlue, range: range(from: numberStart, to: currentIndex))
|
||||
}
|
||||
|
||||
private func consumeString() {
|
||||
|
@ -163,7 +137,7 @@ class JavaScriptHighlighter {
|
|||
consume() // string closing quote
|
||||
}
|
||||
print("String: \(text[stringStart..<currentIndex])")
|
||||
emit(token: .string, range: range(from: stringStart, to: currentIndex))
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemRed, range: range(from: stringStart, to: currentIndex))
|
||||
}
|
||||
|
||||
private func consumeTemplateString() {
|
||||
|
@ -174,7 +148,7 @@ class JavaScriptHighlighter {
|
|||
consume() // $
|
||||
consume() // {
|
||||
print("Template string fragment: '\(text[stringFragmentStart!..<currentIndex])'")
|
||||
emit(token: .string, range: range(from: stringFragmentStart!, to: currentIndex))
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemRed, range: range(from: stringFragmentStart!, to: currentIndex))
|
||||
consumeTemplateStringExpression()
|
||||
stringFragmentStart = currentIndex
|
||||
if currentIndex < text.endIndex && peek() == "}" {
|
||||
|
@ -184,7 +158,7 @@ class JavaScriptHighlighter {
|
|||
stringFragmentStart = stringFragmentStart ?? currentIndex
|
||||
consume() // `
|
||||
print("Template string fragment: '\(text[stringFragmentStart!..<currentIndex])'")
|
||||
emit(token: .string, range: range(from: stringFragmentStart!, to: currentIndex))
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemRed, range: range(from: stringFragmentStart!, to: currentIndex))
|
||||
stringFragmentStart = nil
|
||||
break
|
||||
} else {
|
||||
|
@ -193,7 +167,7 @@ class JavaScriptHighlighter {
|
|||
}
|
||||
if let start = stringFragmentStart {
|
||||
print("Template string fragment: '\(text[start..<currentIndex])'")
|
||||
emit(token: .string, range: range(from: start, to: currentIndex))
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemRed, range: range(from: start, to: currentIndex))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,7 +187,7 @@ class JavaScriptHighlighter {
|
|||
private func consumeFunctionCallOrGrouping() {
|
||||
consume() // (
|
||||
print("Opening (")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
indent += " "
|
||||
while currentIndex < text.endIndex && peek() != ")" {
|
||||
consumeExpression()
|
||||
|
@ -222,31 +196,27 @@ class JavaScriptHighlighter {
|
|||
if currentIndex < text.endIndex {
|
||||
consume() // )
|
||||
print("Closing )")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
}
|
||||
}
|
||||
|
||||
private func consumeObject() {
|
||||
consume() // {
|
||||
print("Opening {")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
indent += " "
|
||||
object:
|
||||
while currentIndex < text.endIndex && peek() != "}" {
|
||||
consumeObjectKey()
|
||||
if peek() == ":" {
|
||||
consume() // :
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
consumeWhitespace()
|
||||
while currentIndex < text.endIndex && peek() != "," && peek() != "}" {
|
||||
consumeExpression()
|
||||
}
|
||||
}
|
||||
consumeWhitespace()
|
||||
|
||||
if peek() == "," {
|
||||
consume() // ,
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
if currentIndex < text.endIndex {
|
||||
break object
|
||||
}
|
||||
} else if peek() == "," {
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
|
@ -256,12 +226,11 @@ class JavaScriptHighlighter {
|
|||
if currentIndex < text.endIndex {
|
||||
consume() // }
|
||||
print("Closing }")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
}
|
||||
}
|
||||
|
||||
private func consumeObjectKey() {
|
||||
consumeWhitespace()
|
||||
guard let char = peek() else { return }
|
||||
let keyStart = currentIndex!
|
||||
if identifierStarts.contains(char) {
|
||||
|
@ -270,19 +239,18 @@ class JavaScriptHighlighter {
|
|||
consumeString()
|
||||
}
|
||||
print("Object key: '\(text[keyStart..<currentIndex])'")
|
||||
consumeWhitespace()
|
||||
}
|
||||
|
||||
private func consumeDotLookup() {
|
||||
consume() // .
|
||||
print("Dot lookup")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
}
|
||||
|
||||
private func consumeArray() {
|
||||
consume() // [
|
||||
print("Opening [")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
indent += " "
|
||||
array:
|
||||
while currentIndex < text.endIndex && peek() != "]" {
|
||||
|
@ -290,8 +258,6 @@ class JavaScriptHighlighter {
|
|||
while currentIndex < text.endIndex {
|
||||
if peek() == "," {
|
||||
consume() // ,
|
||||
print("Array separator")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
break
|
||||
} else if peek() == "]" {
|
||||
break array
|
||||
|
@ -306,17 +272,8 @@ class JavaScriptHighlighter {
|
|||
if currentIndex < text.endIndex {
|
||||
consume() // ]
|
||||
print("Closing ]")
|
||||
emit(token: .punctuation, range: prevCharRange())
|
||||
attributed.addAttribute(.foregroundColor, value: NSColor.systemTeal, range: prevCharRange())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension JavaScriptHighlighter {
|
||||
enum TokenType {
|
||||
case identifier
|
||||
case punctuation
|
||||
case number
|
||||
case string
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
let source = "{a: 1234 , 'b': 'blah', foo}"
|
||||
let source = "`+`${{a:3}}`"
|
||||
_ = JavaScriptHighlighter(text: source).highlight()
|
||||
|
||||
|
|
Loading…
Reference in New Issue