@@ -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 {
0 commit comments