|
| 1 | +import CodeEditSourceEditor |
| 2 | + |
| 3 | +/// Keeps the text view's contents in step with the document it is showing. |
| 4 | +/// |
| 5 | +/// `SourceEditor` pushes text into its text view exactly once, in |
| 6 | +/// `makeNSViewController`. `updateNSViewController` diffs language, configuration and |
| 7 | +/// highlight providers — **it never diffs the text behind the `Binding<String>`**. Switching |
| 8 | +/// tabs therefore leaves the previously opened document on screen, and every tab shows the |
| 9 | +/// same file. |
| 10 | +/// |
| 11 | +/// `prepareCoordinator` is the one hook that hands out the live controller, and it runs once |
| 12 | +/// per controller, so this holds it weakly and `CodeEditorView` calls `reload(text:)` when |
| 13 | +/// the document changes. |
| 14 | +/// |
| 15 | +/// This is a workaround for upstream, not a design preference. If a future version diffs the |
| 16 | +/// text on update, this type should go away — see [MEMORY.md](../../../docs/MEMORY.md). |
| 17 | +@MainActor |
| 18 | +final class DocumentTextCoordinator: TextViewCoordinator { |
| 19 | + private weak var controller: TextViewController? |
| 20 | + |
| 21 | + func prepareCoordinator(controller: TextViewController) { |
| 22 | + self.controller = controller |
| 23 | + } |
| 24 | + |
| 25 | + /// Replace the editor's contents, unless it is already showing them. |
| 26 | + /// |
| 27 | + /// Safe either way: the change flows back through the binding, and `Document.setContent` |
| 28 | + /// guards on equality, so reloading the same text records no edit and no undo entry. |
| 29 | + func reload(text: String) { |
| 30 | + guard let controller, controller.textView.string != text else { return } |
| 31 | + controller.setText(text) |
| 32 | + } |
| 33 | +} |
0 commit comments