Skip to content

Commit 75d7c7f

Browse files
committed
Add multiple step revert in prompt to code
1 parent 4543d5e commit 75d7c7f

File tree

3 files changed

+45
-28
lines changed

3 files changed

+45
-28
lines changed

Core/Sources/PromptToCodeService/PromptToCodeService.swift

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,32 @@ public final class PromptToCodeService: ObservableObject {
1111

1212
var runningAPI: PromptToCodeAPI?
1313

14-
@Published public var oldCode: String?
14+
public indirect enum HistoryNode: Equatable {
15+
case empty
16+
case node(code: String, description: String, previous: HistoryNode)
17+
18+
mutating func enqueue(code: String, description: String) {
19+
let current = self
20+
self = .node(code: code, description: description, previous: current)
21+
}
22+
23+
mutating func pop() -> (code: String, description: String)? {
24+
switch self {
25+
case .empty:
26+
return nil
27+
case let .node(code, description, previous):
28+
self = previous
29+
return (code, description)
30+
}
31+
}
32+
}
33+
34+
@Published public var history: HistoryNode
1535
@Published public var code: String
1636
@Published public var isResponding: Bool = false
1737
@Published public var description: String = ""
1838
@Published public var isContinuous = false
19-
public var oldDescription: String?
20-
public var canRevert: Bool { oldCode != nil }
39+
public var canRevert: Bool { history != .empty }
2140
public var selectionRange: CursorRange
2241
public var language: CopilotLanguage
2342
public var indentSize: Int
@@ -31,7 +50,6 @@ public final class PromptToCodeService: ObservableObject {
3150
selectionRange: CursorRange,
3251
language: CopilotLanguage,
3352
identSize: Int,
34-
usesTabsForIndentation: Bool
3553
usesTabsForIndentation: Bool,
3654
projectRootURL: URL,
3755
fileURL: URL,
@@ -45,15 +63,15 @@ public final class PromptToCodeService: ObservableObject {
4563
self.projectRootURL = projectRootURL
4664
self.fileURL = fileURL
4765
self.allCode = allCode
66+
self.history = .empty
4867
}
4968

5069
public func modifyCode(prompt: String) async throws {
5170
let api = promptToCodeAPI
5271
runningAPI = api
5372
isResponding = true
5473
let toBeModified = code
55-
oldDescription = description
56-
oldCode = code
74+
history.enqueue(code: code, description: description)
5775
code = ""
5876
description = ""
5977
defer { isResponding = false }
@@ -63,13 +81,17 @@ public final class PromptToCodeService: ObservableObject {
6381
language: language,
6482
indentSize: indentSize,
6583
usesTabsForIndentation: usesTabsForIndentation,
66-
requirement: prompt
84+
requirement: prompt,
85+
projectRootURL: projectRootURL,
86+
fileURL: fileURL,
87+
allCode: allCode
6788
)
6889
for try await fragment in stream {
69-
Task { @MainActor in
70-
code = fragment.code
71-
description = fragment.description
72-
}
90+
code = fragment.code
91+
description = fragment.description
92+
}
93+
if code.isEmpty, description.isEmpty {
94+
revert()
7395
}
7496
} catch is CancellationError {
7597
return
@@ -78,26 +100,15 @@ public final class PromptToCodeService: ObservableObject {
78100
return
79101
}
80102

81-
if let oldCode {
82-
code = oldCode
83-
}
84-
if let oldDescription {
85-
description = oldDescription
86-
}
87-
oldCode = nil
88-
oldDescription = nil
103+
revert()
89104
throw error
90105
}
91106
}
92107

93108
public func revert() {
94-
guard let oldCode = oldCode else { return }
95-
code = oldCode
96-
if let oldDescription {
97-
description = oldDescription
98-
}
99-
self.oldCode = nil
100-
oldDescription = nil
109+
guard let (code, description) = history.pop() else { return }
110+
self.code = code
111+
self.description = description
101112
}
102113

103114
public func generateCompletion() -> CopilotCompletion {

Core/Sources/Service/GUI/PromptToCodeProvider+Service.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ extension PromptToCodeProvider {
1818
service.$isResponding.sink(receiveValue: set(\.isResponding)).store(in: &cancellables)
1919
service.$description.sink(receiveValue: set(\.description)).store(in: &cancellables)
2020
service.$isContinuous.sink(receiveValue: set(\.isContinuous)).store(in: &cancellables)
21-
service.$oldCode.map { $0 != nil }
21+
service.$history.map { $0 != .empty }
2222
.sink(receiveValue: set(\.canRevert)).store(in: &cancellables)
2323

2424
onCancelTapped = { [cancellables] in

Core/Sources/Service/SuggestionCommandHandler/WindowBaseCommandHandler.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ struct WindowBaseCommandHandler: SuggestionCommandHandler {
128128
presenter.markAsProcessing(true)
129129
defer { presenter.markAsProcessing(false) }
130130
let fileURL = try await Environment.fetchCurrentFileURL()
131+
132+
if let service = WidgetDataSource.shared.promptToCodes[fileURL]?.promptToCodeService {
133+
WidgetDataSource.shared.removePromptToCode(for: fileURL)
134+
presenter.closePromptToCode(fileURL: fileURL)
135+
return
136+
}
137+
131138
let (workspace, _) = try await Workspace.fetchOrCreateWorkspaceIfNeeded(fileURL: fileURL)
132139
workspace.rejectSuggestion(forFileAt: fileURL, editor: editor)
133140
presenter.discardSuggestion(fileURL: fileURL)
@@ -364,7 +371,6 @@ struct WindowBaseCommandHandler: SuggestionCommandHandler {
364371

365372
_ = await WidgetDataSource.shared.createPromptToCode(
366373
for: fileURL,
367-
code: code,
368374
projectURL: projectURL ?? fileURL,
369375
selectedCode: code,
370376
allCode: editor.content,

0 commit comments

Comments
 (0)