Skip to content

Commit 02fb3b5

Browse files
ItemBox updates
1 parent 4d24153 commit 02fb3b5

9 files changed

Lines changed: 237 additions & 138 deletions

File tree

CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 14 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CodeEdit/Features/Editor/AutoCompleteCoordinator.swift

Lines changed: 59 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ class AutoCompleteCoordinator: TextViewCoordinator {
1414
private weak var textViewController: TextViewController?
1515
private var localEventMonitor: Any?
1616

17-
private let itemBoxController = ItemBoxWindowController()
17+
private var itemBoxController: ItemBoxWindowController?
1818

1919
func prepareCoordinator(controller: TextViewController) {
20-
itemBoxController.close()
20+
itemBoxController = ItemBoxWindowController()
21+
itemBoxController?.delegate = self
22+
itemBoxController?.close()
2123
self.textViewController = controller
2224

2325
localEventMonitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in
@@ -31,84 +33,79 @@ class AutoCompleteCoordinator: TextViewCoordinator {
3133
}
3234

3335
func showAutocompleteWindow() {
34-
guard let cursorPos = textViewController?.cursorPositions.last,
36+
guard let cursorPos = textViewController?.cursorPositions.first,
3537
let textView = textViewController?.textView,
3638
let window = NSApplication.shared.keyWindow,
39+
let itemBoxController = itemBoxController,
3740
!itemBoxController.isVisible
3841
else {
3942
return
4043
}
4144

45+
@Service var lspService: LSPService
46+
47+
// lspService.
48+
4249
itemBoxController.items = [
43-
CompletionItem(label: "item1", kind: .class),
44-
CompletionItem(label: "item2", kind: .enum),
45-
CompletionItem(label: "item3", kind: .function),
46-
CompletionItem(label: "item4", kind: .color),
47-
CompletionItem(label: "item5", kind: .constant),
48-
CompletionItem(label: "item6", kind: .constructor),
49-
CompletionItem(label: "item7", kind: .enumMember),
50-
CompletionItem(label: "item8", kind: .field),
51-
CompletionItem(label: "item9", kind: .file),
52-
CompletionItem(label: "item10", kind: .folder),
53-
CompletionItem(label: "item11", kind: .snippet),
54-
CompletionItem(label: "item12", kind: .reference),
50+
CompletionItem(label: "CETable", kind: .class),
51+
CompletionItem(label: "CETask", kind: .enum),
52+
CompletionItem(label: "CETarget", kind: .function),
53+
CompletionItem(label: "CEItem", kind: .color),
54+
CompletionItem(label: "tableView", kind: .constant),
55+
CompletionItem(label: "itemBoxController", kind: .constructor),
56+
CompletionItem(label: "showAutocompleteWindow", kind: .enumMember),
57+
CompletionItem(label: "NSApplication", kind: .field),
58+
CompletionItem(label: "CECell", kind: .file),
59+
CompletionItem(label: "Item10", kind: .folder),
60+
CompletionItem(label: "Item11", kind: .snippet),
61+
CompletionItem(label: "Item12", kind: .reference),
5562
]
5663

57-
// Reset the size of the window
58-
let windowSize = ItemBoxWindowController.DEFAULT_SIZE
59-
itemBoxController.window?.setContentSize(windowSize)
60-
6164
let cursorRect = textView.firstRect(forCharacterRange: cursorPos.range, actualRange: nil)
62-
let screenFrame = window.screen!.visibleFrame
63-
let padding: CGFloat = 22
64-
var autocompleteWindowOrigin = NSPoint(
65-
x: cursorRect.origin.x,
66-
y: cursorRect.origin.y
67-
)
68-
69-
// Keep the horizontal position within the screen and some padding
70-
let minX = screenFrame.minX + padding
71-
let maxX = screenFrame.maxX - windowSize.width - padding
72-
73-
if autocompleteWindowOrigin.x < minX {
74-
autocompleteWindowOrigin.x = minX
75-
} else if autocompleteWindowOrigin.x > maxX {
76-
autocompleteWindowOrigin.x = maxX
77-
}
78-
79-
// Check if the window will go below the screen
80-
// We determine whether the window drops down or upwards by choosing which
81-
// corner of the window we will position: `setFrameOrigin` or `setFrameTopLeftPoint`
82-
if autocompleteWindowOrigin.y - windowSize.height < screenFrame.minY {
83-
// If the cursor itself if below the screen, then position the window
84-
// at the bottom of the screen with some padding
85-
if autocompleteWindowOrigin.y < screenFrame.minY {
86-
autocompleteWindowOrigin.y = screenFrame.minY + padding
87-
} else {
88-
// Place above the cursor
89-
autocompleteWindowOrigin.y += cursorRect.height
90-
}
91-
92-
itemBoxController.window?.setFrameOrigin(autocompleteWindowOrigin)
93-
} else {
94-
// If the window goes above the screen, position it below the screen with padding
95-
let maxY = screenFrame.maxY - padding
96-
if autocompleteWindowOrigin.y > maxY {
97-
autocompleteWindowOrigin.y = maxY
98-
}
99-
100-
itemBoxController.window?.setFrameTopLeftPoint(autocompleteWindowOrigin)
101-
}
102-
65+
itemBoxController.constrainWindowToScreenEdges(cursorRect: cursorRect)
10366
itemBoxController.showWindow(attachedTo: window)
10467
}
10568

10669
deinit {
107-
print("Destroyed AutoCompleteCoordinator")
108-
itemBoxController.close()
70+
itemBoxController?.close()
10971
if let localEventMonitor = localEventMonitor {
11072
NSEvent.removeMonitor(localEventMonitor)
11173
self.localEventMonitor = nil
11274
}
11375
}
11476
}
77+
78+
extension MarkupContent {
79+
public init(kind: MarkupKind, value: String) {
80+
do {
81+
let dictionary: [String: Any] = ["kind": kind.rawValue, "value": value]
82+
let data = try JSONSerialization.data(withJSONObject: dictionary)
83+
self = try JSONDecoder().decode(MarkupContent.self, from: data)
84+
} catch {
85+
print("Failed to create MarkupContent: \(error)")
86+
// swiftlint:disable:next force_try
87+
self = try! JSONDecoder().decode(MarkupContent.self, from: """
88+
{"kind": "plaintext", "value": ""}
89+
""".data(using: .utf8)!)
90+
}
91+
}
92+
}
93+
94+
extension AutoCompleteCoordinator: ItemBoxDelegate {
95+
func applyCompletionItem(_ item: CompletionItem) {
96+
guard let cursorPos = textViewController?.cursorPositions.first else {
97+
return
98+
}
99+
100+
do {
101+
let token = try textViewController?.treeSitterClient?.nodesAt(range: cursorPos.range)
102+
guard let token = token?.first else {
103+
return
104+
}
105+
print("Token \(token)")
106+
} catch {
107+
print("\(error)")
108+
return
109+
}
110+
}
111+
}

CodeEdit/Features/Editor/Models/EditorInstance.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class EditorInstance: Hashable {
2727
// Public TextViewCoordinator APIs
2828

2929
var rangeTranslator: RangeTranslator?
30+
var autoCompleteCoordinator: AutoCompleteCoordinator?
3031

3132
// Internal Combine subjects
3233

@@ -38,6 +39,7 @@ class EditorInstance: Hashable {
3839
self.file = file
3940
self.cursorSubject.send(cursorPositions)
4041
self.rangeTranslator = RangeTranslator(cursorSubject: cursorSubject)
42+
self.autoCompleteCoordinator = AutoCompleteCoordinator()
4143
}
4244

4345
func hash(into hasher: inout Hasher) {

CodeEdit/Features/Editor/Views/CodeFileView.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ struct CodeFileView: View {
2121

2222
/// Any coordinators passed to the view.
2323
private var textViewCoordinators: [TextViewCoordinator]
24-
/// The coordinator that manages the autocomplete window (item box)
25-
private let autocompleteCoordinator = AutoCompleteCoordinator()
2624

2725
@AppSettings(\.textEditing.defaultTabWidth)
2826
var defaultTabWidth
@@ -61,7 +59,6 @@ struct CodeFileView: View {
6159
self.textViewCoordinators = textViewCoordinators + [
6260
codeFile.contentCoordinator,
6361
codeFile.languageServerCoordinator,
64-
autocompleteCoordinator,
6562
]
6663
self.isEditable = isEditable
6764

CodeEdit/Features/Editor/Views/EditorAreaView.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import SwiftUI
99
import CodeEditTextView
10+
import CodeEditSourceEditor
1011

1112
struct EditorAreaView: View {
1213
@AppSettings(\.general.showEditorPathBar)
@@ -52,7 +53,10 @@ struct EditorAreaView: View {
5253
if let codeFile = codeFile {
5354
EditorAreaFileView(
5455
codeFile: codeFile,
55-
textViewCoordinators: [selected.rangeTranslator].compactMap({ $0 })
56+
// Linter keeps complaining about types, which is why there are these weird casts
57+
textViewCoordinators: [
58+
selected.rangeTranslator as Any, selected.autoCompleteCoordinator as Any
59+
].compactMap({ $0 as? any TextViewCoordinator })
5660
)
5761
.focusedObject(editor)
5862
.transformEnvironment(\.edgeInsets) { insets in

CodeEdit/Features/LSP/Service/LSPService+Events.swift

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,63 +33,63 @@ extension LSPService {
3333

3434
private func handleEvent(_ event: ServerEvent, for key: ClientKey) {
3535
// TODO: Handle Events
36-
// switch event {
37-
// case let .request(id, request):
38-
// print("Request ID: \(id) for \(key.languageId.rawValue)")
39-
// handleRequest(request)
40-
// case let .notification(notification):
41-
// handleNotification(notification)
42-
// case let .error(error):
43-
// print("Error from EventStream for \(key.languageId.rawValue): \(error)")
44-
// }
36+
switch event {
37+
case let .request(id, request):
38+
print("Request ID: \(id) for \(key.languageId.rawValue)")
39+
handleRequest(request)
40+
case let .notification(notification):
41+
handleNotification(notification)
42+
case let .error(error):
43+
print("Error from EventStream for \(key.languageId.rawValue): \(error)")
44+
}
4545
}
4646

4747
private func handleRequest(_ request: ServerRequest) {
4848
// TODO: Handle Requests
49-
// switch request {
50-
// case let .workspaceConfiguration(params, _):
51-
// print("workspaceConfiguration: \(params)")
52-
// case let .workspaceFolders(handler):
53-
// print("workspaceFolders: \(String(describing: handler))")
54-
// case let .workspaceApplyEdit(params, _):
55-
// print("workspaceApplyEdit: \(params)")
56-
// case let .clientRegisterCapability(params, _):
57-
// print("clientRegisterCapability: \(params)")
58-
// case let .clientUnregisterCapability(params, _):
59-
// print("clientUnregisterCapability: \(params)")
60-
// case let .workspaceCodeLensRefresh(handler):
61-
// print("workspaceCodeLensRefresh: \(String(describing: handler))")
62-
// case let .workspaceSemanticTokenRefresh(handler):
63-
// print("workspaceSemanticTokenRefresh: \(String(describing: handler))")
64-
// case let .windowShowMessageRequest(params, _):
65-
// print("windowShowMessageRequest: \(params)")
66-
// case let .windowShowDocument(params, _):
67-
// print("windowShowDocument: \(params)")
68-
// case let .windowWorkDoneProgressCreate(params, _):
69-
// print("windowWorkDoneProgressCreate: \(params)")
70-
//
71-
// default:
72-
// print()
73-
// }
49+
switch request {
50+
case let .workspaceConfiguration(params, _):
51+
print("workspaceConfiguration: \(params)")
52+
case let .workspaceFolders(handler):
53+
print("workspaceFolders: \(String(describing: handler))")
54+
case let .workspaceApplyEdit(params, _):
55+
print("workspaceApplyEdit: \(params)")
56+
case let .clientRegisterCapability(params, _):
57+
print("clientRegisterCapability: \(params)")
58+
case let .clientUnregisterCapability(params, _):
59+
print("clientUnregisterCapability: \(params)")
60+
case let .workspaceCodeLensRefresh(handler):
61+
print("workspaceCodeLensRefresh: \(String(describing: handler))")
62+
case let .workspaceSemanticTokenRefresh(handler):
63+
print("workspaceSemanticTokenRefresh: \(String(describing: handler))")
64+
case let .windowShowMessageRequest(params, _):
65+
print("windowShowMessageRequest: \(params)")
66+
case let .windowShowDocument(params, _):
67+
print("windowShowDocument: \(params)")
68+
case let .windowWorkDoneProgressCreate(params, _):
69+
print("windowWorkDoneProgressCreate: \(params)")
70+
71+
default:
72+
print()
73+
}
7474
}
7575

7676
private func handleNotification(_ notification: ServerNotification) {
7777
// TODO: Handle Notifications
78-
// switch notification {
79-
// case let .windowLogMessage(params):
80-
// print("windowLogMessage \(params.type)\n```\n\(params.message)\n```\n")
81-
// case let .windowShowMessage(params):
82-
// print("windowShowMessage \(params.type)\n```\n\(params.message)\n```\n")
83-
// case let .textDocumentPublishDiagnostics(params):
84-
// print("textDocumentPublishDiagnostics: \(params)")
85-
// case let .telemetryEvent(params):
86-
// print("telemetryEvent: \(params)")
87-
// case let .protocolCancelRequest(params):
88-
// print("protocolCancelRequest: \(params)")
89-
// case let .protocolProgress(params):
90-
// print("protocolProgress: \(params)")
91-
// case let .protocolLogTrace(params):
92-
// print("protocolLogTrace: \(params)")
93-
// }
78+
switch notification {
79+
case let .windowLogMessage(params):
80+
print("windowLogMessage \(params.type)\n```\n\(params.message)\n```\n")
81+
case let .windowShowMessage(params):
82+
print("windowShowMessage \(params.type)\n```\n\(params.message)\n```\n")
83+
case let .textDocumentPublishDiagnostics(params):
84+
print("textDocumentPublishDiagnostics: \(params)")
85+
case let .telemetryEvent(params):
86+
print("telemetryEvent: \(params)")
87+
case let .protocolCancelRequest(params):
88+
print("protocolCancelRequest: \(params)")
89+
case let .protocolProgress(params):
90+
print("protocolProgress: \(params)")
91+
case let .protocolLogTrace(params):
92+
print("protocolLogTrace: \(params)")
93+
}
9494
}
9595
}

0 commit comments

Comments
 (0)