Skip to content

Commit 0559fc4

Browse files
committed
perf(editor): idle the hidden fold ribbon and use NSString equality in binding sync
1 parent 347cfa2 commit 0559fc4

3 files changed

Lines changed: 14 additions & 1 deletion

File tree

LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/Gutter/GutterView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ public class GutterView: NSView {
7878
public var showFoldingRibbon: Bool = true {
7979
didSet {
8080
foldingRibbon.isHidden = !showFoldingRibbon
81+
if showFoldingRibbon {
82+
foldingRibbon.model?.refresh()
83+
}
8184
}
8285
}
8386

LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/LineFolding/Model/LineFoldModel.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ class LineFoldModel: NSObject, NSTextStorageDelegate, ObservableObject {
5757
foldCache.folds(in: range)
5858
}
5959

60+
/// Recomputes folds for the whole document. Used to catch up after the ribbon has been hidden and is shown again.
61+
func refresh() {
62+
textChangedStreamContinuation.yield()
63+
}
64+
6065
func textStorage(
6166
_ textStorage: NSTextStorage,
6267
didProcessEditing editedMask: NSTextStorageEditActions,
@@ -67,6 +72,9 @@ class LineFoldModel: NSObject, NSTextStorageDelegate, ObservableObject {
6772
return
6873
}
6974
foldCache.storageUpdated(editedRange: editedRange, changeInLength: delta)
75+
// Recalculating folds walks the whole document. Skip it while the ribbon is hidden; `refresh()` rebuilds when
76+
// it is shown again.
77+
guard foldView?.isHidden != true else { return }
7078
textChangedStreamContinuation.yield()
7179
}
7280

LocalPackages/CodeEditSourceEditor/Sources/CodeEditSourceEditor/SourceEditor/TextBindingSync.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ final class TextBindingSync {
7777
/// tree-sitter state for the old document and highlighting never recovers.
7878
func applyRepresentableText(_ newValue: String, controller: TextViewController) {
7979
guard !phase.isEditorChangePending else { return }
80-
guard newValue != lastSyncedText else { return }
80+
// Compare with NSString literal equality. The text can be multiple megabytes and bridged from NSTextStorage,
81+
// so Swift's canonical `!=` walks the whole string through Unicode normalization on every representable update.
82+
if let lastSyncedText, (newValue as NSString).isEqual(to: lastSyncedText) { return }
8183

8284
writebackTask?.cancel()
8385
phase.applyRepresentableValue {

0 commit comments

Comments
 (0)