Skip to content

Commit 4a3cb13

Browse files
Documentation, Improve Public AppKit API (#353)
- Improves appkit integration documentation with an example. - Adds a new, public, `jumpToDefinitionDelegate` variable on the `TextViewController` for managing that API. - Documents `jumpToDefinitionDelegate` and `completionDelegate`, noting the fact that they are weak references and must have an outside, strong, reference to function properly.
1 parent 5b10252 commit 4a3cb13

File tree

5 files changed

+61
-25
lines changed

5 files changed

+61
-25
lines changed

Sources/CodeEditSourceEditor/Controller/TextViewController+Lifecycle.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -218,23 +218,23 @@ extension TextViewController {
218218
case .flagsChanged:
219219
if modifierFlags.contains(.command),
220220
let coords = view.window?.convertPoint(fromScreen: NSEvent.mouseLocation) {
221-
self.jumpToDefinitionModel?.mouseHovered(windowCoordinates: coords)
221+
self.jumpToDefinitionModel.mouseHovered(windowCoordinates: coords)
222222
}
223223

224224
if !modifierFlags.contains(.command) {
225-
self.jumpToDefinitionModel?.cancelHover()
225+
self.jumpToDefinitionModel.cancelHover()
226226
}
227227
return event
228228
case .mouseMoved:
229229
guard modifierFlags.contains(.command) else {
230-
self.jumpToDefinitionModel?.cancelHover()
230+
self.jumpToDefinitionModel.cancelHover()
231231
return event
232232
}
233-
self.jumpToDefinitionModel?.mouseHovered(windowCoordinates: event.locationInWindow)
233+
self.jumpToDefinitionModel.mouseHovered(windowCoordinates: event.locationInWindow)
234234
return event
235235
case .leftMouseUp:
236-
if let range = jumpToDefinitionModel?.hoveredRange {
237-
self.jumpToDefinitionModel?.performJump(at: range)
236+
if let range = jumpToDefinitionModel.hoveredRange {
237+
self.jumpToDefinitionModel.performJump(at: range)
238238
return nil
239239
}
240240
return event
@@ -274,7 +274,7 @@ extension TextViewController {
274274
guard let cursor = cursorPositions.first else {
275275
return event
276276
}
277-
jumpToDefinitionModel?.performJump(at: cursor.range)
277+
jumpToDefinitionModel.performJump(at: cursor.range)
278278
return nil
279279
case (_, _):
280280
return event

Sources/CodeEditSourceEditor/Controller/TextViewController.swift

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ public class TextViewController: NSViewController {
2424

2525
// MARK: - Views and Child VCs
2626

27-
// MARK: - Views and Child VCs
28-
2927
weak var findViewController: FindViewController?
3028

3129
internal(set) public var scrollView: NSScrollView!
@@ -87,8 +85,24 @@ public class TextViewController: NSViewController {
8785
/// The provided highlight provider.
8886
public var highlightProviders: [HighlightProviding]
8987

88+
/// A delegate object that can respond to requests for completion items, filtering completion items, and triggering
89+
/// the suggestion window. See ``CodeSuggestionDelegate``.
90+
/// - Note: The ``TextViewController`` keeps only a `weak` reference to this object. To function properly, ensure a
91+
/// strong reference to the delegate is kept *outside* of this variable.
9092
public weak var completionDelegate: CodeSuggestionDelegate?
9193

94+
/// A delegate object that responds to requests for jump to definition actions. see ``JumpToDefinitionDelegate``.
95+
/// - Note: The ``TextViewController`` keeps only a `weak` reference to this object. To function properly, ensure a
96+
/// strong reference to the delegate is kept *outside* of this variable.
97+
public var jumpToDefinitionDelegate: JumpToDefinitionDelegate? {
98+
get {
99+
jumpToDefinitionModel.delegate
100+
}
101+
set {
102+
jumpToDefinitionModel.delegate = newValue
103+
}
104+
}
105+
92106
// MARK: - Config Helpers
93107

94108
/// The font to use in the `textView`
@@ -177,7 +191,7 @@ public class TextViewController: NSViewController {
177191
/// This will be `nil` if another highlighter provider is passed to the source editor.
178192
internal(set) public var treeSitterClient: TreeSitterClient? {
179193
didSet {
180-
jumpToDefinitionModel?.treeSitterClient = treeSitterClient
194+
jumpToDefinitionModel.treeSitterClient = treeSitterClient
181195
}
182196
}
183197

@@ -186,7 +200,7 @@ public class TextViewController: NSViewController {
186200
/// Filters used when applying edits..
187201
var textFilters: [TextFormation.Filter] = []
188202

189-
var jumpToDefinitionModel: JumpToDefinitionModel?
203+
var jumpToDefinitionModel: JumpToDefinitionModel
190204

191205
var cancellables = Set<AnyCancellable>()
192206

@@ -214,7 +228,9 @@ public class TextViewController: NSViewController {
214228
highlightProviders: [HighlightProviding] = [TreeSitterClient()],
215229
foldProvider: LineFoldProvider? = nil,
216230
undoManager: CEUndoManager? = nil,
217-
coordinators: [TextViewCoordinator] = []
231+
coordinators: [TextViewCoordinator] = [],
232+
completionDelegate: CodeSuggestionDelegate? = nil,
233+
jumpToDefinitionDelegate: JumpToDefinitionDelegate? = nil
218234
) {
219235
self.language = language
220236
self.configuration = configuration
@@ -223,9 +239,16 @@ public class TextViewController: NSViewController {
223239
self.foldProvider = foldProvider ?? LineIndentationFoldProvider()
224240
self._undoManager = undoManager
225241
self.invisibleCharactersCoordinator = InvisibleCharactersCoordinator(configuration: configuration)
242+
self.completionDelegate = completionDelegate
243+
self.jumpToDefinitionModel = JumpToDefinitionModel(
244+
controller: nil,
245+
treeSitterClient: treeSitterClient,
246+
delegate: jumpToDefinitionDelegate
247+
)
226248

227249
super.init(nibName: nil, bundle: nil)
228250

251+
jumpToDefinitionModel.controller = self
229252
suggestionTriggerModel.controller = self
230253

231254
if let idx = highlightProviders.firstIndex(where: { $0 is TreeSitterClient }),
@@ -253,11 +276,6 @@ public class TextViewController: NSViewController {
253276
}
254277
self.textCoordinators = coordinators.map { WeakCoordinator($0) }
255278

256-
jumpToDefinitionModel = JumpToDefinitionModel(
257-
controller: self,
258-
treeSitterClient: treeSitterClient,
259-
delegate: nil
260-
)
261279
}
262280

263281
required init?(coder: NSCoder) {

Sources/CodeEditSourceEditor/Documentation.docc/SourceEditorView.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,29 @@ let editorController = TextViewController(
8686
cursorPositions: [CursorPosition(line: 0, column: 0)],
8787
highlightProviders: [], // Use the tree-sitter syntax highlighting provider by default
8888
undoManager: nil,
89-
coordinators: [] // Optionally inject editing behavior or other plugins.
89+
coordinators: [], // Optionally inject editing behavior or other plugins.
90+
completionDelegate: nil, // Provide code suggestions while typing via a delegate object.
91+
jumpToDefinitionDelegate // Allow users to perform the 'jump to definition' using a delegate object.
9092
)
9193
```
9294

95+
To add the controller to your view, add it as a child view controller and add the editor's view to your view hierarchy.
96+
97+
```swift
98+
final class MyController: NSViewController {
99+
override func loadView() {
100+
super.loadView()
101+
let editorController: TextViewController = /**/
102+
103+
addChild(editorController)
104+
view.addSubview(editorController.view)
105+
editorController.view.viewDidMoveToSuperview()
106+
}
107+
}
108+
```
109+
110+
For more AppKit API options, see the documentation on ``TextViewController``.
111+
93112
## Topics
94113

95114
- ``SourceEditor``

Sources/CodeEditSourceEditor/JumpToDefinition/JumpToDefinitionModel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ final class JumpToDefinitionModel {
2020
weak var delegate: JumpToDefinitionDelegate?
2121
weak var treeSitterClient: TreeSitterClient?
2222

23-
private weak var controller: TextViewController?
23+
weak var controller: TextViewController?
2424

2525
private(set) public var hoveredRange: NSRange?
2626

@@ -33,7 +33,7 @@ final class JumpToDefinitionModel {
3333
controller?.textView
3434
}
3535

36-
init(controller: TextViewController, treeSitterClient: TreeSitterClient?, delegate: JumpToDefinitionDelegate?) {
36+
init(controller: TextViewController?, treeSitterClient: TreeSitterClient?, delegate: JumpToDefinitionDelegate?) {
3737
self.controller = controller
3838
self.treeSitterClient = treeSitterClient
3939
self.delegate = delegate

Sources/CodeEditSourceEditor/SourceEditor/SourceEditor.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ public struct SourceEditor: NSViewControllerRepresentable {
103103
cursorPositions: state.cursorPositions ?? [],
104104
highlightProviders: context.coordinator.highlightProviders,
105105
undoManager: undoManager,
106-
coordinators: coordinators
106+
coordinators: coordinators,
107+
completionDelegate: completionDelegate,
108+
jumpToDefinitionDelegate: jumpToDefinitionDelegate
107109
)
108110
switch text {
109111
case .binding(let binding):
@@ -118,9 +120,6 @@ public struct SourceEditor: NSViewControllerRepresentable {
118120
controller.setCursorPositions(state.cursorPositions ?? [])
119121
}
120122

121-
controller.completionDelegate = completionDelegate
122-
controller.jumpToDefinitionModel?.delegate = jumpToDefinitionDelegate
123-
124123
context.coordinator.setController(controller)
125124
return controller
126125
}
@@ -131,7 +130,7 @@ public struct SourceEditor: NSViewControllerRepresentable {
131130

132131
public func updateNSViewController(_ controller: TextViewController, context: Context) {
133132
controller.completionDelegate = completionDelegate
134-
controller.jumpToDefinitionModel?.delegate = jumpToDefinitionDelegate
133+
controller.jumpToDefinitionDelegate = jumpToDefinitionDelegate
135134

136135
context.coordinator.updateHighlightProviders(highlightProviders)
137136

0 commit comments

Comments
 (0)