@@ -42,6 +42,7 @@ extension NSAttributedString.Key {
4242 // MARK: Public Properties
4343
4444 private( set) var syntax : Syntax
45+ private( set) var syntaxName : String
4546
4647 var theme : Theme ?
4748
@@ -57,6 +58,7 @@ extension NSAttributedString.Key {
5758 private var highlightParseTask : Task < Void , any Error > ?
5859 private var outlineParseTask : Task < Void , any Error > ?
5960 private var invalidRanges : EditedRangeSet
61+ private var isReady = false
6062
6163
6264 // MARK: Lifecycle
@@ -70,11 +72,10 @@ extension NSAttributedString.Key {
7072 init ( textStorage: NSTextStorage , syntax: Syntax , name: String ) {
7173
7274 self . textStorage = textStorage
73- self . invalidRanges = EditedRangeSet ( range: textStorage. range)
74-
7575 self . syntax = syntax
76- self . highlightParser = try ? LanguageRegistry . shared. highlightParser ( name: name) ?? syntax. highlightParser
77- self . outlineParser = syntax. outlineParser
76+ self . syntaxName = name
77+
78+ self . invalidRanges = EditedRangeSet ( range: textStorage. range)
7879 }
7980
8081
@@ -85,6 +86,19 @@ extension NSAttributedString.Key {
8586
8687 // MARK: Public Methods
8788
89+ /// Sets up parsers and starts the initial parse.
90+ func setupParser( ) {
91+
92+ self . cancel ( )
93+
94+ self . highlightParser = try ? LanguageRegistry . shared. highlightParser ( name: self . syntaxName) ?? self . syntax. highlightParser
95+ self . outlineParser = self . syntax. outlineParser
96+ self . isReady = true
97+
98+ self . parseAll ( )
99+ }
100+
101+
88102 /// Cancels all remaining parsing tasks.
89103 func cancel( ) {
90104
@@ -104,16 +118,17 @@ extension NSAttributedString.Key {
104118
105119 self . cancel ( )
106120
121+ self . syntax = syntax
122+ self . syntaxName = name
123+
124+ guard self . isReady else { return }
125+
107126 // clear current highlight
108127 if self . highlightParser != nil {
109128 self . textStorage. apply ( highlights: [ ] , theme: nil , in: self . textStorage. range)
110129 }
111130
112- self . syntax = syntax
113- self . highlightParser = try ? LanguageRegistry . shared. highlightParser ( name: name) ?? syntax. highlightParser
114- self . outlineParser = syntax. outlineParser
115-
116- self . parseAll ( )
131+ self . setupParser ( )
117132 }
118133
119134
@@ -124,6 +139,8 @@ extension NSAttributedString.Key {
124139 /// - delta: The change in length.
125140 func invalidate( in editedRange: NSRange , changeInLength delta: Int ) {
126141
142+ assert ( self . isReady)
143+
127144 self . highlightParseTask? . cancel ( )
128145 self . highlightParseTask = nil
129146
@@ -136,6 +153,8 @@ extension NSAttributedString.Key {
136153 /// Applies a short debounce before parsing to allow the text system to settle.
137154 func parseIfNeeded( ) {
138155
156+ assert ( self . isReady)
157+
139158 self . updateOutline ( withDelay: true )
140159 self . highlightIfNeeded ( withDelay: true )
141160 }
@@ -144,6 +163,8 @@ extension NSAttributedString.Key {
144163 /// Re-parses the entire document immediately.
145164 func parseAll( ) {
146165
166+ assert ( self . isReady)
167+
147168 self . invalidRanges. update ( editedRange: self . textStorage. range)
148169
149170 self . updateOutline ( withDelay: false )
0 commit comments