Last active
September 12, 2024 04:50
-
-
Save JadenGeller/e4b337991e028ba97b68e837fb201102 to your computer and use it in GitHub Desktop.
parsing custom attributed text format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct AttributedStringBuilder { | |
@Stack var attributes: RichTextAttributes = .init() | |
var string: AttributedString = "" | |
mutating func text(_ span: String) { | |
string += AttributedString(span, attributes: .init(attributes)) | |
} | |
mutating func attribute(_ span: String) { | |
attributes.parse(span.trimmingCharacters(in: .whitespaces)) // todo: only do at end prob? | |
} | |
mutating func push() { | |
$attributes.push() | |
} | |
mutating func pop() { | |
try? $attributes.pop() // todo: error handling | |
} | |
} | |
struct DirectiveProcessor { | |
var upstream: AttributedStringBuilder | |
var span = "" | |
var isDirective = false | |
mutating func delimit() { | |
if isDirective { | |
upstream.attribute(span) | |
} else if !span.isEmpty { | |
upstream.text(span) | |
} | |
span = "" | |
} | |
mutating func directive() { | |
delimit() | |
if !isDirective { | |
upstream.push() | |
isDirective = true | |
} | |
} | |
mutating func open() { | |
delimit() | |
isDirective = false | |
} | |
mutating func close() { | |
delimit() | |
if isDirective { | |
// oops! a dangling directive. we pushed but was never opened! | |
upstream.pop() | |
} | |
upstream.pop() | |
} | |
mutating func char(_ character: Character) { | |
span.append(character) | |
} | |
} | |
struct EscapingTokenizer { | |
var upstream: DirectiveProcessor | |
var isEscaped = false | |
mutating func token(_ character: Character) { | |
switch (isEscaped, character) { | |
case (true, #"\"#): | |
isEscaped = false | |
upstream.char(character) | |
case (true, "{"): | |
isEscaped = false | |
upstream.char(character) | |
case (true, "}"): | |
isEscaped = false | |
upstream.char(character) | |
case (true, "n"): // fixme: allow other escapes? | |
isEscaped = false | |
upstream.char("\n") | |
case (true, _): | |
isEscaped = false | |
upstream.directive() | |
upstream.char(character) | |
case (false, #"\"#): | |
isEscaped = true | |
case (false, "{"): | |
upstream.open() | |
case (false, "}"): | |
upstream.close() | |
case (false, _): | |
upstream.char(character) | |
} | |
} | |
mutating func terminate() { | |
upstream.delimit() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
\textStyle body {The \color blue {sky appears blue} due to a phenomenon called \italic \color indigo {Rayleigh scattering}. This occurs when \weight bold {sunlight} passes through the Earth's atmosphere and \highlight yellow {interacts with molecules and small particles}.} | |
\textStyle body {Sunlight is made up of different colors, each with its own wavelength. \highlight cyan \italic {Blue light} has a shorter wavelength and is scattered in all directions by the gases and particles in the atmosphere. This scattered blue light is what we see when we look up at the sky.} | |
\textStyle body {In contrast, \color red {red light} has a longer wavelength and is scattered less, which is why the sky can appear \highlight orange {reddish during sunrise and sunset} when the light path through the atmosphere is longer.} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment