Skip to content

Commit 13425fa

Browse files
committed
Adjust real-time suggestions
1 parent 68c1e72 commit 13425fa

3 files changed

Lines changed: 52 additions & 27 deletions

File tree

Core/Sources/CopilotService/CopilotService.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ public class CopilotBaseService {
7272
let localServer = CopilotLocalProcessServer(executionParameters: executionParams)
7373
localServer.logMessages = false
7474
localServer.notificationHandler = { notification, respond in
75-
print(notification)
7675
respond(.timeout)
7776
}
7877
let server = InitializingServer(server: localServer)

Core/Sources/Service/RealtimeSuggestionController.swift

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public actor RealtimeSuggestionController {
1818
])
1919
private var task: Task<Void, Error>?
2020
private var inflightPrefetchTask: Task<Void, Error>?
21+
private var ignoreUntil = Date(timeIntervalSince1970: 0)
2122
let realtimeSuggestionIndicatorController = RealtimeSuggestionIndicatorController()
2223

2324
private init() {
@@ -81,27 +82,13 @@ public actor RealtimeSuggestionController {
8182
}
8283

8384
func handleKeyboardEvent(event: CGEvent) async {
84-
inflightPrefetchTask?.cancel()
85+
await cancelInFlightTasks()
8586

8687
if Task.isCancelled { return }
8788
guard await Environment.isXcodeActive() else { return }
8889

89-
// cancel in-flight tasks
90-
await withTaskGroup(of: Void.self) { group in
91-
for (_, workspace) in await workspaces {
92-
group.addTask {
93-
await workspace.cancelInFlightRealtimeSuggestionRequests()
94-
}
95-
}
96-
group.addTask {
97-
await { @ServiceActor in
98-
inflightRealtimeSuggestionsTasks.forEach { $0.cancel() }
99-
inflightRealtimeSuggestionsTasks.removeAll()
100-
}()
101-
}
102-
}
103-
10490
let escape = 0x35
91+
let arrowKeys = [0x7B, 0x7C, 0x7D, 0x7E]
10592
let isEditing = await Environment.frontmostXcodeWindowIsEditor()
10693

10794
// if Xcode suggestion panel is presenting, and we are not trying to close it
@@ -111,22 +98,29 @@ public actor RealtimeSuggestionController {
11198
}
11299

113100
let shouldTrigger = {
101+
let code = Int(event.getIntegerValueField(.keyboardEventKeycode))
114102
// closing auto-complete panel
115-
if isEditing, event.getIntegerValueField(.keyboardEventKeycode) == escape {
103+
if isEditing, code == escape {
116104
return true
117105
}
106+
107+
// escape and arrows to cancel
118108

119-
// normally typing
120-
if event.type == .keyUp,
121-
event.getIntegerValueField(.keyboardEventKeycode) != escape
122-
{
123-
return true
109+
if code == escape {
110+
return false
124111
}
112+
113+
if arrowKeys.contains(code) {
114+
return false
115+
}
116+
117+
// normally typing
125118

126-
return false
119+
return event.type == .keyUp
127120
}()
128121

129122
guard shouldTrigger else { return }
123+
guard Date().timeIntervalSince(ignoreUntil) > 0 else { return }
130124

131125
inflightPrefetchTask = Task { @ServiceActor in
132126
try? await Task.sleep(nanoseconds: UInt64((
@@ -146,6 +140,31 @@ public actor RealtimeSuggestionController {
146140
}
147141
}
148142
}
143+
144+
func cancelInFlightTasks() async {
145+
inflightPrefetchTask?.cancel()
146+
147+
// cancel in-flight tasks
148+
await withTaskGroup(of: Void.self) { group in
149+
for (_, workspace) in await workspaces {
150+
group.addTask {
151+
await workspace.cancelInFlightRealtimeSuggestionRequests()
152+
}
153+
}
154+
group.addTask {
155+
await { @ServiceActor in
156+
inflightRealtimeSuggestionsTasks.forEach { $0.cancel() }
157+
inflightRealtimeSuggestionsTasks.removeAll()
158+
}()
159+
}
160+
}
161+
}
162+
163+
/// Prevent prefetch to be triggered by commands. Quick and dirty.
164+
func cancelInFlightTasksAndIgnoreTriggerForAWhile() async {
165+
ignoreUntil = Date(timeIntervalSinceNow: 5)
166+
await cancelInFlightTasks()
167+
}
149168
}
150169

151170
/// Present a tiny dot next to mouse cursor if real-time suggestion is enabled.

Core/Sources/Service/XPCService.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ public class XPCService: NSObject, XPCServiceProtocol {
1919
public func getXPCServiceVersion(withReply reply: @escaping (String, String) -> Void) {
2020
reply(
2121
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "N/A",
22-
Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "N/A")
22+
Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "N/A"
23+
)
2324
}
2425

2526
@ServiceActor
@@ -88,6 +89,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
8889
withReply reply: @escaping (Data?, Error?) -> Void
8990
) {
9091
Task { @ServiceActor in
92+
await RealtimeSuggestionController.shared.cancelInFlightTasksAndIgnoreTriggerForAWhile()
9193
do {
9294
let editor = try JSONDecoder().decode(EditorContent.self, from: editorContent)
9395
let fileURL = try await Environment.fetchCurrentFileURL()
@@ -118,6 +120,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
118120
withReply reply: @escaping (Data?, Error?) -> Void
119121
) {
120122
Task { @ServiceActor in
123+
await RealtimeSuggestionController.shared.cancelInFlightTasksAndIgnoreTriggerForAWhile()
121124
do {
122125
let editor = try JSONDecoder().decode(EditorContent.self, from: editorContent)
123126
let fileURL = try await Environment.fetchCurrentFileURL()
@@ -145,6 +148,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
145148
withReply reply: @escaping (Data?, Error?) -> Void
146149
) {
147150
Task { @ServiceActor in
151+
await RealtimeSuggestionController.shared.cancelInFlightTasksAndIgnoreTriggerForAWhile()
148152
do {
149153
let editor = try JSONDecoder().decode(EditorContent.self, from: editorContent)
150154
let fileURL = try await Environment.fetchCurrentFileURL()
@@ -172,6 +176,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
172176
withReply reply: @escaping (Data?, Error?) -> Void
173177
) {
174178
Task { @ServiceActor in
179+
await RealtimeSuggestionController.shared.cancelInFlightTasksAndIgnoreTriggerForAWhile()
175180
do {
176181
let editor = try JSONDecoder().decode(EditorContent.self, from: editorContent)
177182
let fileURL = try await Environment.fetchCurrentFileURL()
@@ -196,6 +201,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
196201
withReply reply: @escaping (Data?, Error?) -> Void
197202
) {
198203
Task { @ServiceActor in
204+
await RealtimeSuggestionController.shared.cancelInFlightTasksAndIgnoreTriggerForAWhile()
199205
do {
200206
let editor = try JSONDecoder().decode(EditorContent.self, from: editorContent)
201207
let fileURL = try await Environment.fetchCurrentFileURL()
@@ -250,7 +256,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
250256
reply(nil, NSError.from(error))
251257
}
252258
}
253-
259+
254260
Task { @ServiceActor in inflightRealtimeSuggestionsTasks.insert(task) }
255261
}
256262

@@ -260,6 +266,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
260266
return
261267
}
262268
Task { @ServiceActor in
269+
await RealtimeSuggestionController.shared.cancelInFlightTasksAndIgnoreTriggerForAWhile()
263270
UserDefaults.shared.set(
264271
!UserDefaults.shared.bool(forKey: SettingsKey.realtimeSuggestionToggle),
265272
forKey: SettingsKey.realtimeSuggestionToggle
@@ -293,7 +300,7 @@ public class XPCService: NSObject, XPCServiceProtocol {
293300
reply()
294301
}
295302
}
296-
303+
297304
Task { @ServiceActor in inflightRealtimeSuggestionsTasks.insert(task) }
298305
}
299306
}

0 commit comments

Comments
 (0)