Skip to content

Commit a5581a2

Browse files
Invalidate Visible Range, Responsive Language Update (#238)
### Description - Updates the visible set of indices when text storage happens, fixing the linked issue. - When setting a new language on the highlighter, adds a small "reset" that clears all current highlights. This makes the language update feel snappier, as the user receives immediate feedback. Before the ts parser could take a few seconds to begin highlighting, so there would be a delay making it seem like the language update was not happening. - Adds a missing `throw` to the tree-sitter client that made edits always run synchronously (didn't feel big enough for a whole PR, found while debugging). - Only updates the font if the font is new, making text layouts occur much less frequently (also doesn't feel big enough for a separate PR) ### Related Issues * #235 ### Checklist - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots https://github.com/CodeEditApp/CodeEditSourceEditor/assets/35942988/e719178e-bc9a-4830-9ca5-8d113dcb9d8b
1 parent 63dcea1 commit a5581a2

File tree

3 files changed

+21
-8
lines changed

3 files changed

+21
-8
lines changed

Sources/CodeEditSourceEditor/CodeEditSourceEditor.swift

+9-1
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,16 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
156156
return
157157
}
158158

159-
controller.font = font
159+
if controller.font != font {
160+
controller.font = font
161+
}
162+
160163
controller.wrapLines = wrapLines
161164
controller.useThemeBackground = useThemeBackground
162165
controller.lineHeightMultiple = lineHeight
163166
controller.editorOverscroll = editorOverscroll
164167
controller.contentInsets = contentInsets
168+
165169
if controller.isEditable != isEditable {
166170
controller.isEditable = isEditable
167171
}
@@ -173,15 +177,19 @@ public struct CodeEditSourceEditor: NSViewControllerRepresentable {
173177
if controller.language.id != language.id {
174178
controller.language = language
175179
}
180+
176181
if controller.theme != theme {
177182
controller.theme = theme
178183
}
184+
179185
if controller.indentOption != indentOption {
180186
controller.indentOption = indentOption
181187
}
188+
182189
if controller.tabWidth != tabWidth {
183190
controller.tabWidth = tabWidth
184191
}
192+
185193
if controller.letterSpacing != letterSpacing {
186194
controller.letterSpacing = letterSpacing
187195
}

Sources/CodeEditSourceEditor/Highlighting/Highlighter.swift

+11-6
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ class Highlighter: NSObject {
3636
return IndexSet(integersIn: textView?.visibleTextRange ?? NSRange())
3737
}()
3838

39-
// MARK: - Tasks
40-
41-
private var runningTasks: [UUID: Task<Void, Never>] = [:]
42-
4339
// MARK: - UI
4440

4541
/// The text view to highlight
@@ -114,6 +110,15 @@ class Highlighter: NSObject {
114110
/// - Parameter language: The language to update to.
115111
public func setLanguage(language: CodeLanguage) {
116112
guard let textView = self.textView else { return }
113+
// Remove all current highlights. Makes the language setting feel snappier and tells the user we're doing
114+
// something immediately.
115+
textView.textStorage.setAttributes(
116+
attributeProvider.attributesFor(nil),
117+
range: NSRange(location: 0, length: textView.textStorage.length)
118+
)
119+
textView.layoutManager.invalidateLayoutForRect(textView.visibleRect)
120+
validSet.removeAll()
121+
pendingSet.removeAll()
117122
highlightProvider?.setUp(textView: textView, codeLanguage: language)
118123
invalidate()
119124
}
@@ -304,11 +309,11 @@ extension Highlighter {
304309
visibleSet.insert(range: editedRange)
305310
}
306311

312+
updateVisibleSet(textView: textView)
313+
307314
highlightProvider?.applyEdit(textView: textView, range: range, delta: delta) { [weak self] invalidIndexSet in
308315
let indexSet = invalidIndexSet
309316
.union(IndexSet(integersIn: editedRange))
310-
// Only invalidate indices that are visible.
311-
.intersection(self?.visibleSet ?? IndexSet())
312317

313318
for range in indexSet.rangeView {
314319
self?.invalidate(range: NSRange(range))

Sources/CodeEditSourceEditor/TreeSitter/TreeSitterClient.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public final class TreeSitterClient: HighlightProviding {
218218
let longDocument = textView.documentRange.length > Constants.maxSyncContentLength
219219

220220
if longEdit || longDocument {
221-
221+
throw Error.syncUnavailable
222222
}
223223
try performSync(operation)
224224
} catch {

0 commit comments

Comments
 (0)