Skip to content

Commit 8c53b93

Browse files
committed
Add command Prompt to Code
1 parent 11a4762 commit 8c53b93

File tree

9 files changed

+100
-0
lines changed

9 files changed

+100
-0
lines changed

Copilot for Xcode.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
C841BB242994CAD400B0B336 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C841BB232994CAD400B0B336 /* SettingsView.swift */; };
3333
C8520301293C4D9000460097 /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8520300293C4D9000460097 /* Helpers.swift */; };
3434
C85AF32D29CF0C170031E18B /* DebugView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C85AF32C29CF0C170031E18B /* DebugView.swift */; };
35+
C861A6A329E5503F005C41A3 /* PromptToCodeCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */; };
3536
C861E6112994F6070056CB02 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C861E6102994F6070056CB02 /* AppDelegate.swift */; };
3637
C861E6152994F6080056CB02 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C861E6142994F6080056CB02 /* Assets.xcassets */; };
3738
C861E61E2994F6150056CB02 /* Service in Frameworks */ = {isa = PBXBuildFile; productRef = C861E61D2994F6150056CB02 /* Service */; };
@@ -180,6 +181,7 @@
180181
C8520300293C4D9000460097 /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = "<group>"; };
181182
C8520308293D805800460097 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
182183
C85AF32C29CF0C170031E18B /* DebugView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugView.swift; sourceTree = "<group>"; };
184+
C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptToCodeCommand.swift; sourceTree = "<group>"; };
183185
C861E60E2994F6070056CB02 /* CopilotForXcodeExtensionService.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CopilotForXcodeExtensionService.app; sourceTree = BUILT_PRODUCTS_DIR; };
184186
C861E6102994F6070056CB02 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
185187
C861E6142994F6080056CB02 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -262,6 +264,7 @@
262264
C800DBB0294C624D00B04CAC /* PrefetchSuggestionsCommand.swift */,
263265
C8EE07A029CC9ED30043B6D9 /* ExplainSelectionCommand.swift */,
264266
C8DCEFFF29CE11D500FDDDD7 /* ChatWithSelection.swift */,
267+
C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */,
265268
C81458972939EFDC00135263 /* Info.plist */,
266269
C81458982939EFDC00135263 /* EditorExtension.entitlements */,
267270
);
@@ -527,6 +530,7 @@
527530
files = (
528531
C8DCF00029CE11D500FDDDD7 /* ChatWithSelection.swift in Sources */,
529532
C81458942939EFDC00135263 /* SourceEditorExtension.swift in Sources */,
533+
C861A6A329E5503F005C41A3 /* PromptToCodeCommand.swift in Sources */,
530534
C8520301293C4D9000460097 /* Helpers.swift in Sources */,
531535
C8009BFF2941C551007AA7E8 /* ToggleRealtimeSuggestionsCommand.swift in Sources */,
532536
C87B03A5293B261200C77EAE /* AcceptSuggestionCommand.swift in Sources */,

Core/Sources/Client/AsyncXPCService.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ public struct AsyncXPCService {
186186
{ $0.chatWithSelection }
187187
)
188188
}
189+
190+
public func promptToCode(editorContent: EditorContent) async throws -> UpdatedContent? {
191+
try await suggestionRequest(
192+
connection,
193+
editorContent,
194+
{ $0.promptToCode }
195+
)
196+
}
189197
}
190198

191199
struct AutoFinishContinuation<T> {

Core/Sources/Service/SuggestionCommandHandler/CommentBaseCommandHandler.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ struct CommentBaseCommandHandler: SuggestionCommandHandler {
179179
func chatWithSelection(editor: EditorContent) async throws -> UpdatedContent? {
180180
throw NotSupportedInCommentMode()
181181
}
182+
183+
func promptToCode(editor: XPCShared.EditorContent) async throws -> XPCShared.UpdatedContent? {
184+
throw NotSupportedInCommentMode()
185+
}
182186
}
183187

184188
// MARK: - Unsupported

Core/Sources/Service/SuggestionCommandHandler/SuggestionCommandHandler.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ protocol SuggestionCommandHandler {
2020
func explainSelection(editor: EditorContent) async throws -> UpdatedContent?
2121
@ServiceActor
2222
func chatWithSelection(editor: EditorContent) async throws -> UpdatedContent?
23+
@ServiceActor
24+
func promptToCode(editor: EditorContent) async throws -> UpdatedContent?
2325
}

Core/Sources/Service/SuggestionCommandHandler/WindowBaseCommandHandler.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,4 +275,43 @@ struct WindowBaseCommandHandler: SuggestionCommandHandler {
275275

276276
presenter.presentChatRoom(fileURL: fileURL)
277277
}
278+
279+
func promptToCode(editor: EditorContent) async throws -> UpdatedContent? {
280+
Task {
281+
do {
282+
try await _promptToCode(editor: editor)
283+
} catch {
284+
presenter.presentError(error)
285+
}
286+
}
287+
return nil
288+
}
289+
290+
func _promptToCode(editor: EditorContent) async throws {
291+
presenter.markAsProcessing(true)
292+
defer { presenter.markAsProcessing(false) }
293+
let fileURL = try await Environment.fetchCurrentFileURL()
294+
let language = UserDefaults.shared.value(for: \.chatGPTLanguage)
295+
let codeLanguage = languageIdentifierFromFileURL(fileURL)
296+
let code = {
297+
guard let selection = editor.selections.last,
298+
selection.start != selection.end else { return "" }
299+
return editor.selectedCode(in: selection)
300+
}()
301+
302+
_ = await WidgetDataSource.shared.createPromptToCode(
303+
for: fileURL,
304+
code: code,
305+
selectionRange: editor.selections.last.map { .init(
306+
start: $0.start,
307+
end: $0.end
308+
) } ?? .init(
309+
start: editor.cursorPosition,
310+
end: editor.cursorPosition
311+
),
312+
language: codeLanguage
313+
)
314+
315+
presenter.presentPromptToCode(fileURL: fileURL)
316+
}
278317
}

Core/Sources/Service/XPCService.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,15 @@ public class XPCService: NSObject, XPCServiceProtocol {
232232
try await handler.chatWithSelection(editor: editor)
233233
}
234234
}
235+
236+
public func promptToCode(
237+
editorContent: Data,
238+
withReply reply: @escaping (Data?, Error?) -> Void
239+
) {
240+
replyWithUpdatedContent(editorContent: editorContent, withReply: reply) { handler, editor in
241+
try await handler.promptToCode(editor: editor)
242+
}
243+
}
235244

236245
// MARK: - Settings
237246

Core/Sources/XPCShared/XPCServiceProtocol.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ public protocol XPCServiceProtocol {
4444
editorContent: Data,
4545
withReply reply: @escaping (Data?, Error?) -> Void
4646
)
47+
func promptToCode(
48+
editorContent: Data,
49+
withReply reply: @escaping (Data?, Error?) -> Void
50+
)
4751

4852
func toggleRealtimeSuggestion(withReply reply: @escaping (Error?) -> Void)
4953

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Client
2+
import CopilotModel
3+
import Foundation
4+
import XcodeKit
5+
6+
class PromptToCodeCommand: NSObject, XCSourceEditorCommand, CommandType {
7+
var name: String { "Prompt to Code" }
8+
9+
func perform(
10+
with invocation: XCSourceEditorCommandInvocation,
11+
completionHandler: @escaping (Error?) -> Void
12+
) {
13+
Task {
14+
do {
15+
let service = try getService()
16+
if let content = try await service.promptToCode(
17+
editorContent: .init(invocation)
18+
) {
19+
invocation.accept(content)
20+
}
21+
completionHandler(nil)
22+
} catch is CancellationError {
23+
completionHandler(nil)
24+
} catch {
25+
completionHandler(error)
26+
}
27+
}
28+
}
29+
}

EditorExtension/SourceEditorExtension.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class SourceEditorExtension: NSObject, XCSourceEditorExtension {
1515
PrefetchSuggestionsCommand(),
1616
ChatWithSelectionCommand(),
1717
ExplainSelectionCommand(),
18+
PromptToCodeCommand(),
1819
].map(makeCommandDefinition)
1920
}
2021

0 commit comments

Comments
 (0)