Skip to content

Commit 2f6b4e2

Browse files
committed
Merge branch 'release/0.12.0'
2 parents 241ae5a + 01fc537 commit 2f6b4e2

File tree

65 files changed

+2417
-1056
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2417
-1056
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 */,

Copilot for Xcode/App.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import Client
12
import SwiftUI
2-
import XPCShared
33
import UpdateChecker
4+
import XPCShared
45

56
@main
67
struct CopilotForXcodeApp: App {
@@ -11,6 +12,10 @@ struct CopilotForXcodeApp: App {
1112
.preferredColorScheme(.dark)
1213
.onAppear {
1314
UserDefaults.setupDefaultSettings()
15+
Task {
16+
let service = try getService()
17+
await service.boostQoS()
18+
}
1419
}
1520
.environment(\.updateChecker, UpdateChecker(hostBundle: Bundle.main))
1621
}
@@ -21,7 +26,7 @@ struct CopilotForXcodeApp: App {
2126
var isPreview: Bool { ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" }
2227

2328
struct UpdateCheckerKey: EnvironmentKey {
24-
static var defaultValue: UpdateChecker = UpdateChecker(hostBundle: nil)
29+
static var defaultValue: UpdateChecker = .init(hostBundle: nil)
2530
}
2631

2732
extension EnvironmentValues {
@@ -30,5 +35,3 @@ extension EnvironmentValues {
3035
set { self[UpdateCheckerKey.self] = newValue }
3136
}
3237
}
33-
34-

Copilot for Xcode/DebugView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ final class DebugSettings: ObservableObject {
77
var disableLazyVStack: Bool
88
@AppStorage(\.preCacheOnFileOpen)
99
var preCacheOnFileOpen: Bool
10+
@AppStorage(\.runNodeWithInteractiveLoggedInShell)
11+
var runNodeWithInteractiveLoggedInShell: Bool
1012
init() {}
1113
}
1214

@@ -24,6 +26,10 @@ struct DebugSettingsView: View {
2426
Text("Cache editor information on file open")
2527
}
2628
.toggleStyle(.switch)
29+
Toggle(isOn: $settings.runNodeWithInteractiveLoggedInShell) {
30+
Text("Run node with interactive logged-in bash")
31+
}
32+
.toggleStyle(.switch)
2733
}
2834
}.buttonStyle(.copilot)
2935
}

Copilot for Xcode/SettingsView.swift

Lines changed: 231 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,40 @@ import LaunchAgentManager
22
import Preferences
33
import SwiftUI
44

5-
final class Settings: ObservableObject {
6-
@AppStorage(\.quitXPCServiceOnXcodeAndAppQuit)
7-
var quitXPCServiceOnXcodeAndAppQuit: Bool
8-
@AppStorage(\.realtimeSuggestionToggle)
9-
var realtimeSuggestionToggle: Bool
10-
@AppStorage(\.realtimeSuggestionDebounce)
11-
var realtimeSuggestionDebounce: Double
12-
@AppStorage(\.suggestionPresentationMode)
13-
var suggestionPresentationMode: Preferences.PresentationMode
14-
@AppStorage(\.suggestionWidgetPositionMode)
15-
var suggestionWidgetPositionMode: SuggestionWidgetPositionMode
16-
@AppStorage(\.widgetColorScheme)
17-
var widgetColorScheme: WidgetColorScheme
18-
@AppStorage(\.acceptSuggestionWithAccessibilityAPI)
19-
var acceptSuggestionWithAccessibilityAPI: Bool
20-
init() {}
21-
}
22-
235
struct SettingsView: View {
6+
final class Settings: ObservableObject {
7+
@AppStorage(\.quitXPCServiceOnXcodeAndAppQuit)
8+
var quitXPCServiceOnXcodeAndAppQuit: Bool
9+
@AppStorage(\.realtimeSuggestionToggle)
10+
var realtimeSuggestionToggle: Bool
11+
@AppStorage(\.realtimeSuggestionDebounce)
12+
var realtimeSuggestionDebounce: Double
13+
@AppStorage(\.suggestionPresentationMode)
14+
var suggestionPresentationMode: Preferences.PresentationMode
15+
@AppStorage(\.suggestionWidgetPositionMode)
16+
var suggestionWidgetPositionMode: SuggestionWidgetPositionMode
17+
@AppStorage(\.widgetColorScheme)
18+
var widgetColorScheme: WidgetColorScheme
19+
@AppStorage(\.acceptSuggestionWithAccessibilityAPI)
20+
var acceptSuggestionWithAccessibilityAPI: Bool
21+
@AppStorage(\.disableSuggestionFeatureGlobally)
22+
var disableSuggestionFeatureGlobally: Bool
23+
@AppStorage(\.suggestionFeatureEnabledProjectList)
24+
var suggestionFeatureEnabledProjectList: [String]
25+
@AppStorage(\.promptToCodeFeatureProvider)
26+
var promptToCodeFeatureProvider: PromptToCodeFeatureProvider
27+
@AppStorage(\.preferWidgetToStayInsideEditorWhenWidthGreaterThan)
28+
var preferWidgetToStayInsideEditorWhenWidthGreaterThan: Double
29+
@AppStorage(\.hideCommonPrecedingSpacesInSuggestion)
30+
var hideCommonPrecedingSpacesInSuggestion: Bool
31+
init() {}
32+
}
33+
2434
@StateObject var settings = Settings()
2535
@State var editingRealtimeSuggestionDebounce: Double = UserDefaults.shared
2636
.value(for: \.realtimeSuggestionDebounce)
2737
@Environment(\.updateChecker) var updateChecker
38+
@State var isSuggestionFeatureEnabledListPickerOpen = false
2839

2940
var body: some View {
3041
Section {
@@ -85,43 +96,222 @@ struct SettingsView: View {
8596
}
8697
}
8798

88-
Toggle(isOn: $settings.realtimeSuggestionToggle) {
89-
Text("Real-time suggestion")
99+
Group {
100+
Toggle(isOn: $settings.realtimeSuggestionToggle) {
101+
Text("Real-time suggestion")
102+
}
103+
.toggleStyle(.switch)
104+
105+
HStack {
106+
Toggle(isOn: $settings.disableSuggestionFeatureGlobally) {
107+
Text("Disable suggestion feature globally")
108+
}
109+
.toggleStyle(.switch)
110+
111+
Button("Enabled Projects") {
112+
isSuggestionFeatureEnabledListPickerOpen = true
113+
}
114+
}.sheet(isPresented: $isSuggestionFeatureEnabledListPickerOpen) {
115+
SuggestionFeatureEnabledProjectListView(
116+
isOpen: $isSuggestionFeatureEnabledListPickerOpen
117+
)
118+
}
119+
120+
HStack {
121+
Slider(value: $editingRealtimeSuggestionDebounce, in: 0...2, step: 0.1) {
122+
Text("Real-time suggestion fetch debounce")
123+
} onEditingChanged: { _ in
124+
settings.realtimeSuggestionDebounce = editingRealtimeSuggestionDebounce
125+
}
126+
127+
Text(
128+
"\(editingRealtimeSuggestionDebounce.formatted(.number.precision(.fractionLength(2))))s"
129+
)
130+
.font(.body)
131+
.monospacedDigit()
132+
.padding(.vertical, 2)
133+
.padding(.horizontal, 6)
134+
.background(
135+
RoundedRectangle(cornerRadius: 4, style: .continuous)
136+
.fill(Color.white.opacity(0.2))
137+
)
138+
}
139+
140+
Toggle(isOn: $settings.hideCommonPrecedingSpacesInSuggestion) {
141+
Text("Hide Common Preceding Spaces in Suggestion")
142+
}
143+
.toggleStyle(.switch)
144+
145+
Toggle(isOn: $settings.acceptSuggestionWithAccessibilityAPI) {
146+
Text("Use accessibility API to accept suggestion in widget")
147+
}
148+
.toggleStyle(.switch)
149+
}
150+
151+
Picker(selection: $settings.promptToCodeFeatureProvider) {
152+
ForEach(PromptToCodeFeatureProvider.allCases, id: \.rawValue) {
153+
switch $0 {
154+
case .openAI:
155+
Text("OpenAI").tag($0)
156+
case .githubCopilot:
157+
Text("GitHub Copilot (Less Accurate)").tag($0)
158+
}
159+
}
160+
} label: {
161+
Text("Prompt to code with")
90162
}
91-
.toggleStyle(.switch)
92163

93164
HStack {
94-
Slider(value: $editingRealtimeSuggestionDebounce, in: 0...2, step: 0.1) {
95-
Text("Real-time suggestion fetch debounce")
96-
} onEditingChanged: { _ in
97-
settings.realtimeSuggestionDebounce = editingRealtimeSuggestionDebounce
165+
TextField(text: .init(get: {
166+
"\(Int(settings.preferWidgetToStayInsideEditorWhenWidthGreaterThan))"
167+
}, set: {
168+
settings
169+
.preferWidgetToStayInsideEditorWhenWidthGreaterThan =
170+
Double(Int($0) ?? 0)
171+
})) {
172+
Text("Prefer widget to be inside editor when width greater than")
98173
}
174+
.textFieldStyle(.roundedBorder)
99175

100-
Text(
101-
"\(editingRealtimeSuggestionDebounce.formatted(.number.precision(.fractionLength(2))))s"
102-
)
103-
.font(.body)
104-
.monospacedDigit()
105-
.padding(.vertical, 2)
106-
.padding(.horizontal, 6)
107-
.background(
108-
RoundedRectangle(cornerRadius: 4, style: .continuous)
109-
.fill(Color.white.opacity(0.2))
110-
)
111-
}
112-
113-
Toggle(isOn: $settings.acceptSuggestionWithAccessibilityAPI) {
114-
Text("Use accessibility API to accept suggestion in widget")
176+
Text("px")
115177
}
116-
.toggleStyle(.switch)
117178
}
118179
}.buttonStyle(.copilot)
119180
}
120181
}
121182

183+
struct SuggestionFeatureEnabledProjectListView: View {
184+
final class Settings: ObservableObject {
185+
@AppStorage(\.suggestionFeatureEnabledProjectList)
186+
var suggestionFeatureEnabledProjectList: [String]
187+
188+
init(suggestionFeatureEnabledProjectList: AppStorage<[String]>? = nil) {
189+
if let list = suggestionFeatureEnabledProjectList {
190+
_suggestionFeatureEnabledProjectList = list
191+
}
192+
}
193+
}
194+
195+
var isOpen: Binding<Bool>
196+
@State var isAddingNewProject = false
197+
@StateObject var settings = Settings()
198+
199+
var body: some View {
200+
VStack {
201+
HStack {
202+
Button(action: {
203+
self.isOpen.wrappedValue = false
204+
}) {
205+
Image(systemName: "xmark.circle.fill")
206+
.foregroundStyle(.secondary)
207+
.padding()
208+
}
209+
.buttonStyle(.plain)
210+
Text("Enabled Projects")
211+
Spacer()
212+
Button(action: {
213+
isAddingNewProject = true
214+
}) {
215+
Image(systemName: "plus.circle.fill")
216+
.foregroundStyle(.secondary)
217+
.padding()
218+
}
219+
.buttonStyle(.plain)
220+
}
221+
.background(.black.opacity(0.2))
222+
223+
List {
224+
ForEach(
225+
settings.suggestionFeatureEnabledProjectList,
226+
id: \.self
227+
) { project in
228+
HStack {
229+
Text(project)
230+
.contextMenu {
231+
Button("Remove") {
232+
settings.suggestionFeatureEnabledProjectList.removeAll(
233+
where: { $0 == project }
234+
)
235+
}
236+
}
237+
Spacer()
238+
239+
Button(action: {
240+
settings.suggestionFeatureEnabledProjectList.removeAll(
241+
where: { $0 == project }
242+
)
243+
}) {
244+
Image(systemName: "trash.fill")
245+
.foregroundStyle(.secondary)
246+
}
247+
.buttonStyle(.plain)
248+
}
249+
}
250+
}
251+
.overlay {
252+
if settings.suggestionFeatureEnabledProjectList.isEmpty {
253+
Text("""
254+
Empty
255+
Add project with "+" button
256+
Or right clicking the circular widget
257+
""")
258+
.multilineTextAlignment(.center)
259+
}
260+
}
261+
}
262+
.frame(width: 300, height: 400)
263+
.sheet(isPresented: $isAddingNewProject) {
264+
SuggestionFeatureAddEnabledProjectView(isOpen: $isAddingNewProject, settings: settings)
265+
}
266+
}
267+
}
268+
269+
struct SuggestionFeatureAddEnabledProjectView: View {
270+
var isOpen: Binding<Bool>
271+
var settings: SuggestionFeatureEnabledProjectListView.Settings
272+
@State var rootPath = ""
273+
274+
var body: some View {
275+
VStack {
276+
Text(
277+
"Enter the root path of the project. Do not use `~` to replace /Users/yourUserName."
278+
)
279+
TextField("Root path", text: $rootPath)
280+
HStack {
281+
Spacer()
282+
Button("Cancel") {
283+
isOpen.wrappedValue = false
284+
}
285+
Button("Add") {
286+
settings.suggestionFeatureEnabledProjectList.append(rootPath)
287+
isOpen.wrappedValue = false
288+
}
289+
}.buttonStyle(.copilot)
290+
}
291+
.padding()
292+
.frame(minWidth: 500)
293+
}
294+
}
295+
296+
// MARK: - Previews
297+
122298
struct SettingsView_Preview: PreviewProvider {
123299
static var previews: some View {
124300
SettingsView()
125301
.background(.purple)
126302
}
127303
}
304+
305+
struct SuggestionFeatureEnabledProjectListView_Preview: PreviewProvider {
306+
static var previews: some View {
307+
SuggestionFeatureEnabledProjectListView(
308+
isOpen: .constant(true),
309+
settings: .init(suggestionFeatureEnabledProjectList: .init(wrappedValue: [
310+
"hello/2",
311+
"hello/3",
312+
"hello/4",
313+
], "SuggestionFeatureEnabledProjectListView_Preview"))
314+
)
315+
.background(.purple)
316+
}
317+
}

0 commit comments

Comments
 (0)