diff --git a/.gitmodules b/.gitmodules index 418b5100..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "copilot.vim"] - path = copilot.vim - url = git@github.com:github/copilot.vim.git diff --git a/AppIcon.png b/AppIcon.png index 48f29e28..592f927b 100644 Binary files a/AppIcon.png and b/AppIcon.png differ diff --git a/Copilot for Xcode.xcodeproj/project.pbxproj b/Copilot for Xcode.xcodeproj/project.pbxproj index 303efb64..40f6c2d0 100644 --- a/Copilot for Xcode.xcodeproj/project.pbxproj +++ b/Copilot for Xcode.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ C8009BFF2941C551007AA7E8 /* ToggleRealtimeSuggestionsCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8009BFE2941C551007AA7E8 /* ToggleRealtimeSuggestionsCommand.swift */; }; C8009C032941C576007AA7E8 /* RealtimeSuggestionCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8009C022941C576007AA7E8 /* RealtimeSuggestionCommand.swift */; }; C800DBB1294C624D00B04CAC /* PrefetchSuggestionsCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C800DBB0294C624D00B04CAC /* PrefetchSuggestionsCommand.swift */; }; - C81291AE2994F8A000196E12 /* copilot in Copy CopilotLSP */ = {isa = PBXBuildFile; fileRef = C832A47B2940C71D000989F2 /* copilot */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; C81291D72994FE6900196E12 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C81291D52994FE6900196E12 /* Main.storyboard */; }; C814588F2939EFDC00135263 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C814588E2939EFDC00135263 /* Cocoa.framework */; }; C81458942939EFDC00135263 /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81458932939EFDC00135263 /* SourceEditorExtension.swift */; }; @@ -68,17 +67,6 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - C81291AD2994F88D00196E12 /* Copy CopilotLSP */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 7; - files = ( - C81291AE2994F8A000196E12 /* copilot in Copy CopilotLSP */, - ); - name = "Copy CopilotLSP"; - runOnlyForDeploymentPostprocessing = 0; - }; C814589F2939EFDC00135263 /* Embed Foundation Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -159,7 +147,7 @@ C8216B70298036EC00AD38C7 /* Helper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Helper; sourceTree = BUILT_PRODUCTS_DIR; }; C8216B72298036EC00AD38C7 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; C8216B772980370100AD38C7 /* ReloadLaunchAgent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReloadLaunchAgent.swift; sourceTree = ""; }; - C832A47B2940C71D000989F2 /* copilot */ = {isa = PBXFileReference; lastKnownFileType = folder; name = copilot; path = copilot.vim/copilot; sourceTree = ""; }; + C82E38492A1F025F00D4EADF /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; C8520300293C4D9000460097 /* Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = ""; }; C8520308293D805800460097 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptToCodeCommand.swift; sourceTree = ""; }; @@ -255,11 +243,11 @@ children = ( C887BC832965D96000931567 /* DEVELOPMENT.md */, C8520308293D805800460097 /* README.md */, + C82E38492A1F025F00D4EADF /* LICENSE */, C81E867D296FE4420026E908 /* Version.xcconfig */, C81458AD293A009600135263 /* Config.xcconfig */, C81458AE293A009800135263 /* Config.debug.xcconfig */, C8CD828229B88006008D044D /* TestPlan.xctestplan */, - C832A47B2940C71D000989F2 /* copilot */, C8189B282938979000C9DCDA /* Core */, C8189B182938972F00C9DCDA /* Copilot for Xcode */, C81458922939EFDC00135263 /* EditorExtension */, @@ -400,7 +388,6 @@ C861E60A2994F6070056CB02 /* Sources */, C861E60B2994F6070056CB02 /* Frameworks */, C861E60C2994F6070056CB02 /* Resources */, - C81291AD2994F88D00196E12 /* Copy CopilotLSP */, ); buildRules = ( ); diff --git a/Copilot for Xcode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Copilot for Xcode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b8e20a07..084a8217 100644 --- a/Copilot for Xcode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Copilot for Xcode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,14 +1,5 @@ { "pins" : [ - { - "identity" : "feedkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nmdias/FeedKit", - "state" : { - "revision" : "68493a33d862c33c9a9f67ec729b3b7df1b20ade", - "version" : "9.1.2" - } - }, { "identity" : "fseventswrapper", "kind" : "remoteSourceControl", diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon.png new file mode 100644 index 00000000..5af40630 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@128w.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@128w.png new file mode 100644 index 00000000..592f927b Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@128w.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@16w.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@16w.png new file mode 100644 index 00000000..09658ce1 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@16w.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w 1.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w 1.png new file mode 100644 index 00000000..4a7d88ed Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w 1.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w.png new file mode 100644 index 00000000..4a7d88ed Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w 1.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w 1.png new file mode 100644 index 00000000..6c4293c8 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w 1.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w.png new file mode 100644 index 00000000..6c4293c8 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w 1.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w 1.png new file mode 100644 index 00000000..db461044 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w 1.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w.png new file mode 100644 index 00000000..db461044 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@64w.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@64w.png new file mode 100644 index 00000000..42d7a164 Binary files /dev/null and b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@64w.png differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/Contents.json b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/Contents.json index a03c1da5..56acb569 100644 --- a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,61 +1,61 @@ { "images" : [ { - "filename" : "app-icon-realistic-materials_2x 9.png", + "filename" : "1024 x 1024 your icon@16w.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, { - "filename" : "app-icon-realistic-materials_2x 8.png", + "filename" : "1024 x 1024 your icon@32w 1.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, { - "filename" : "app-icon-realistic-materials_2x 7.png", + "filename" : "1024 x 1024 your icon@32w.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, { - "filename" : "app-icon-realistic-materials_2x 6.png", + "filename" : "1024 x 1024 your icon@64w.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, { - "filename" : "app-icon-realistic-materials_2x 5.png", + "filename" : "1024 x 1024 your icon@128w.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, { - "filename" : "app-icon-realistic-materials_2x 4.png", + "filename" : "1024 x 1024 your icon@256w 1.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, { - "filename" : "app-icon-realistic-materials_2x 3.png", + "filename" : "1024 x 1024 your icon@256w.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, { - "filename" : "app-icon-realistic-materials_2x 2.png", + "filename" : "1024 x 1024 your icon@512w 1.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { - "filename" : "app-icon-realistic-materials_2x 1.png", + "filename" : "1024 x 1024 your icon@512w.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { - "filename" : "app-icon-realistic-materials_2x.png", + "filename" : "1024 x 1024 your icon.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 1.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 1.png deleted file mode 100644 index 267da1f8..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 1.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 2.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 2.png deleted file mode 100644 index 267da1f8..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 2.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 3.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 3.png deleted file mode 100644 index ff87360f..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 3.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 4.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 4.png deleted file mode 100644 index ff87360f..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 4.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 5.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 5.png deleted file mode 100644 index 48f29e28..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 5.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 6.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 6.png deleted file mode 100644 index 51fc4d9b..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 6.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 7.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 7.png deleted file mode 100644 index 9f23c1ae..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 7.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 8.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 8.png deleted file mode 100644 index 9f23c1ae..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 8.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 9.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 9.png deleted file mode 100644 index 3ccd8a06..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 9.png and /dev/null differ diff --git a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x.png b/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x.png deleted file mode 100644 index 2d98e582..00000000 Binary files a/Copilot for Xcode/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x.png and /dev/null differ diff --git a/Core/Package.swift b/Core/Package.swift index bdbfe657..d4a83b9f 100644 --- a/Core/Package.swift +++ b/Core/Package.swift @@ -50,7 +50,6 @@ let package = Package( .package(url: "https://github.com/apple/swift-async-algorithms", from: "0.1.0"), .package(url: "https://github.com/raspu/Highlightr", from: "2.1.0"), .package(url: "https://github.com/JohnSundell/Splash", branch: "master"), - .package(url: "https://github.com/nmdias/FeedKit", from: "9.1.2"), .package(url: "https://github.com/gonzalezreal/swift-markdown-ui", from: "2.1.0"), .package(url: "https://github.com/sparkle-project/Sparkle", from: "2.0.0"), .package(url: "https://github.com/alfianlosari/GPTEncoder", from: "1.0.4"), @@ -230,8 +229,7 @@ let package = Package( name: "UpdateChecker", dependencies: [ "Logger", - "Sparkle", - .product(name: "FeedKit", package: "FeedKit"), + "Sparkle" ] ), .target(name: "AXExtension"), @@ -255,7 +253,13 @@ let package = Package( .target( name: "GitHubCopilotService", - dependencies: ["LanguageClient", "SuggestionModel", "XPCShared", "Preferences"] + dependencies: [ + "LanguageClient", + "SuggestionModel", + "XPCShared", + "Preferences", + "Terminal", + ] ), .testTarget( name: "GitHubCopilotServiceTests", diff --git a/Core/Sources/ChatPlugins/TerminalChatPlugin.swift b/Core/Sources/ChatPlugins/TerminalChatPlugin.swift index c7a230ef..85ab6eff 100644 --- a/Core/Sources/ChatPlugins/TerminalChatPlugin.swift +++ b/Core/Sources/ChatPlugins/TerminalChatPlugin.swift @@ -35,13 +35,20 @@ public actor TerminalChatPlugin: ChatPlugin { do { let fileURL = try await Environment.fetchCurrentFileURL() - let projectURL = try await Environment.fetchCurrentProjectRootURL(fileURL) + let projectURL = try await { + if let url = try await Environment.fetchCurrentProjectRootURLFromXcode() { + return url + } + return try await Environment.guessProjectRootURLForFile(fileURL) + }() await chatGPTService.mutateHistory { history in - history.append(.init( - role: .user, - content: originalMessage, - summary: "Run command: \(content)") + history.append( + .init( + role: .user, + content: originalMessage, + summary: "Run command: \(content)" + ) ) } @@ -49,13 +56,13 @@ public actor TerminalChatPlugin: ChatPlugin { let env = ProcessInfo.processInfo.environment let shell = env["SHELL"] ?? "/bin/bash" - + let output = terminal.streamCommand( shell, arguments: ["-i", "-l", "-c", content], - currentDirectoryPath: projectURL?.path ?? fileURL.path, + currentDirectoryPath: projectURL.path, environment: [ - "PROJECT_ROOT": projectURL?.path ?? fileURL.path, + "PROJECT_ROOT": projectURL.path, "FILE_PATH": fileURL.path, ] ) @@ -103,9 +110,10 @@ public actor TerminalChatPlugin: ChatPlugin { isCancelled = true await terminal.terminate() } - + public func stopResponding() async { isCancelled = true await terminal.terminate() } } + diff --git a/Core/Sources/CodeiumService/CodeiumInstallationManager.swift b/Core/Sources/CodeiumService/CodeiumInstallationManager.swift index 55833057..207d2855 100644 --- a/Core/Sources/CodeiumService/CodeiumInstallationManager.swift +++ b/Core/Sources/CodeiumService/CodeiumInstallationManager.swift @@ -3,7 +3,7 @@ import Terminal public struct CodeiumInstallationManager { private static var isInstalling = false - static let latestSupportedVersion: String = "1.2.17" + static let latestSupportedVersion = "1.2.17" public init() {} @@ -72,11 +72,12 @@ public struct CodeiumInstallationManager { try FileManager.default.copyItem(at: fileURL, to: targetURL) defer { try? FileManager.default.removeItem(at: targetURL) } + // uninstall continuation.yield(.uninstalling) try await uninstall() - continuation.yield(.decompressing) // extract file + continuation.yield(.decompressing) let terminal = Terminal() _ = try await terminal.runCommand( "/usr/bin/gunzip", diff --git a/Core/Sources/Environment/Environment.swift b/Core/Sources/Environment/Environment.swift index c70ebdd2..b11a025c 100644 --- a/Core/Sources/Environment/Environment.swift +++ b/Core/Sources/Environment/Environment.swift @@ -43,43 +43,47 @@ public enum Environment { } } - public static var fetchCurrentProjectRootURL: (_ fileURL: URL?) async throws - -> URL? = { fileURL in - if let xcode = ActiveApplicationMonitor.activeXcode - ?? ActiveApplicationMonitor.latestXcode - { - let application = AXUIElementCreateApplication(xcode.processIdentifier) - let focusedWindow = application.focusedWindow - for child in focusedWindow?.children ?? [] { - if child.description.starts(with: "/"), child.description.count > 1 { - let path = child.description - let trimmedNewLine = path.trimmingCharacters(in: .newlines) - var url = URL(fileURLWithPath: trimmedNewLine) - while !FileManager.default.fileIsDirectory(atPath: url.path) || - !url.pathExtension.isEmpty - { - url = url.deletingLastPathComponent() - } - return url + public static var fetchCurrentProjectRootURLFromXcode: () async throws -> URL? = { + if let xcode = ActiveApplicationMonitor.activeXcode + ?? ActiveApplicationMonitor.latestXcode + { + let application = AXUIElementCreateApplication(xcode.processIdentifier) + let focusedWindow = application.focusedWindow + for child in focusedWindow?.children ?? [] { + if child.description.starts(with: "/"), child.description.count > 1 { + let path = child.description + let trimmedNewLine = path.trimmingCharacters(in: .newlines) + var url = URL(fileURLWithPath: trimmedNewLine) + while !FileManager.default.fileIsDirectory(atPath: url.path) || + !url.pathExtension.isEmpty + { + url = url.deletingLastPathComponent() } + return url } } + } - guard var currentURL = fileURL else { return nil } - var firstDirectoryURL: URL? - while currentURL.pathComponents.count > 1 { - defer { currentURL.deleteLastPathComponent() } - guard FileManager.default.fileIsDirectory(atPath: currentURL.path) else { continue } - if firstDirectoryURL == nil { firstDirectoryURL = currentURL } - let gitURL = currentURL.appendingPathComponent(".git") - if FileManager.default.fileIsDirectory(atPath: gitURL.path) { - return currentURL - } - } + return nil + } - return firstDirectoryURL ?? fileURL + public static var guessProjectRootURLForFile: (_ fileURL: URL) async throws -> URL = { + fileURL in + var currentURL = fileURL + var firstDirectoryURL: URL? + while currentURL.pathComponents.count > 1 { + defer { currentURL.deleteLastPathComponent() } + guard FileManager.default.fileIsDirectory(atPath: currentURL.path) else { continue } + if firstDirectoryURL == nil { firstDirectoryURL = currentURL } + let gitURL = currentURL.appendingPathComponent(".git") + if FileManager.default.fileIsDirectory(atPath: gitURL.path) { + return currentURL + } } + return firstDirectoryURL ?? fileURL + } + public static var fetchCurrentFileURL: () async throws -> URL = { guard let xcode = ActiveApplicationMonitor.activeXcode ?? ActiveApplicationMonitor.latestXcode diff --git a/Core/Sources/GitHubCopilotService/GitHubCopilotInstallationManager.swift b/Core/Sources/GitHubCopilotService/GitHubCopilotInstallationManager.swift index 0789d843..62617909 100644 --- a/Core/Sources/GitHubCopilotService/GitHubCopilotInstallationManager.swift +++ b/Core/Sources/GitHubCopilotService/GitHubCopilotInstallationManager.swift @@ -4,11 +4,21 @@ import Terminal public struct GitHubCopilotInstallationManager { private static var isInstalling = false + static var downloadURL: URL { + let commitHash = "1358e8e45ecedc53daf971924a0541ddf6224faf" + let link = "https://github.com/github/copilot.vim/archive/\(commitHash).zip" + return URL(string: link)! + } + + static let latestSupportedVersion = "1.8.4" + public init() {} public enum InstallationStatus { case notInstalled - case installed + case installed(String) + case outdated(current: String, latest: String) + case unsupported(current: String, latest: String) } public func checkInstallation() -> InstallationStatus { @@ -16,12 +26,27 @@ public struct GitHubCopilotInstallationManager { else { return .notInstalled } let executableFolderURL = urls.executableURL let binaryURL = executableFolderURL.appendingPathComponent("copilot") + let versionFileURL = executableFolderURL.appendingPathComponent("version") if !FileManager.default.fileExists(atPath: binaryURL.path) { return .notInstalled } - return .installed + if FileManager.default.fileExists(atPath: versionFileURL.path), + let versionData = try? Data(contentsOf: versionFileURL), + let version = String(data: versionData, encoding: .utf8) + { + switch version.compare(Self.latestSupportedVersion) { + case .orderedAscending: + return .outdated(current: version, latest: Self.latestSupportedVersion) + case .orderedSame: + return .installed(version) + case .orderedDescending: + return .unsupported(current: version, latest: Self.latestSupportedVersion) + } + } + + return .outdated(current: "Unknown", latest: Self.latestSupportedVersion) } public enum InstallationStep { @@ -34,6 +59,7 @@ public struct GitHubCopilotInstallationManager { public enum Error: Swift.Error, LocalizedError { case isInstalling case failedToFindLanguageServer + case failedToInstallLanguageServer public var errorDescription: String? { switch self { @@ -41,6 +67,8 @@ public struct GitHubCopilotInstallationManager { return "Language server is installing." case .failedToFindLanguageServer: return "Failed to find language server. Please open an issue on GitHub." + case .failedToInstallLanguageServer: + return "Failed to install language server. Please open an issue on GitHub." } } } @@ -57,22 +85,63 @@ public struct GitHubCopilotInstallationManager { do { continuation.yield(.downloading) let urls = try GitHubCopilotBaseService.createFoldersIfNeeded() - let executable = Bundle.main.bundleURL.appendingPathComponent("Contents/Applications/CopilotForXcodeExtensionService.app/Contents/Resources/copilot") - guard FileManager.default.fileExists(atPath: executable.path) else { - throw Error.failedToFindLanguageServer - } - - let targetURL = urls.executableURL.appendingPathComponent("copilot") - try FileManager.default.copyItem( - at: executable, - to: targetURL + // download + let (fileURL, _) = try await URLSession.shared.download(from: Self.downloadURL) + let targetURL = urls.executableURL.appendingPathComponent("archive") + .appendingPathExtension("zip") + try FileManager.default.copyItem(at: fileURL, to: targetURL) + defer { try? FileManager.default.removeItem(at: targetURL) } + + // uninstall + continuation.yield(.uninstalling) + try await uninstall() + + // decompress + continuation.yield(.decompressing) + let terminal = Terminal() + + _ = try await terminal.runCommand( + "/usr/bin/unzip", + arguments: [targetURL.path], + currentDirectoryPath: urls.executableURL.path, + environment: [:] ) + let contentURLs = try FileManager.default.contentsOfDirectory( + at: urls.executableURL, + includingPropertiesForKeys: nil, + options: [] + ) + + defer { + for url in contentURLs { + try? FileManager.default.removeItem(at: url) + } + } + + guard let gitFolderURL = contentURLs + .first(where: { $0.lastPathComponent.hasPrefix("copilot.vim") }) + else { + continuation.finish(throwing: Error.failedToInstallLanguageServer) + return + } + + let lspURL = gitFolderURL.appendingPathComponent("copilot") + let installationURL = urls.executableURL.appendingPathComponent("copilot") + try FileManager.default.copyItem(at: lspURL, to: installationURL) + // update permission 755 try FileManager.default.setAttributes( [.posixPermissions: 0o755], - ofItemAtPath: targetURL.path + ofItemAtPath: installationURL.path + ) + + // create version file + let data = Self.latestSupportedVersion.data(using: .utf8) + FileManager.default.createFile( + atPath: urls.executableURL.appendingPathComponent("version").path, + contents: data ) continuation.yield(.done) @@ -89,8 +158,13 @@ public struct GitHubCopilotInstallationManager { else { return } let executableFolderURL = urls.executableURL let binaryURL = executableFolderURL.appendingPathComponent("copilot") + let versionFileURL = executableFolderURL.appendingPathComponent("version") if FileManager.default.fileExists(atPath: binaryURL.path) { try FileManager.default.removeItem(at: binaryURL) } + if FileManager.default.fileExists(atPath: versionFileURL.path) { + try FileManager.default.removeItem(at: versionFileURL) + } } } + diff --git a/Core/Sources/HostApp/AccountSettings/CopilotView.swift b/Core/Sources/HostApp/AccountSettings/CopilotView.swift index 52475571..3e586d65 100644 --- a/Core/Sources/HostApp/AccountSettings/CopilotView.swift +++ b/Core/Sources/HostApp/AccountSettings/CopilotView.swift @@ -16,17 +16,17 @@ struct CopilotView: View { init() {} } - + class ViewModel: ObservableObject { let installationManager = GitHubCopilotInstallationManager() - + @Published var installationStatus: GitHubCopilotInstallationManager.InstallationStatus @Published var installationStep: GitHubCopilotInstallationManager.InstallationStep? - + init() { installationStatus = installationManager.checkInstallation() } - + init( installationStatus: GitHubCopilotInstallationManager.InstallationStatus, installationStep: GitHubCopilotInstallationManager.InstallationStep? @@ -35,13 +35,13 @@ struct CopilotView: View { self.installationStatus = installationStatus self.installationStep = installationStep } - + func refreshInstallationStatus() { Task { @MainActor in installationStatus = installationManager.checkInstallation() } } - + func install() async throws { defer { refreshInstallationStatus() } do { @@ -92,7 +92,7 @@ struct CopilotView: View { Self.copilotAuthService = service return service } - + var installButton: some View { Button(action: { Task { @@ -108,6 +108,21 @@ struct CopilotView: View { .disabled(viewModel.installationStep != nil) } + var updateButton: some View { + Button(action: { + Task { + do { + try await viewModel.install() + } catch { + toast(Text(error.localizedDescription), .error) + } + } + }) { + Text("Update") + } + .disabled(viewModel.installationStep != nil) + } + var uninstallButton: some View { Button(action: { viewModel.uninstall() @@ -150,14 +165,26 @@ struct CopilotView: View { VStack(alignment: .leading) { HStack { - Text("Language Server Version: \(version ?? "Loading..")") switch viewModel.installationStatus { case .notInstalled: + Text("Copilot.Vim Version: Not Installed") installButton - case .installed: + case let .installed(version): + Text("Copilot.Vim Version: \(version)") + uninstallButton + case let .outdated(version, latest): + Text("Copilot.Vim Version: \(version) (Update Available: \(latest))") + updateButton + uninstallButton + case let .unsupported(version, latest): + Text("Copilot.Vim Version: \(version) (Supported Version: \(latest))") + updateButton uninstallButton } } + + Text("Language Server Version: \(version ?? "Loading..")") + Text("Status: \(status?.description ?? "Loading..")") HStack(alignment: .center) { @@ -208,6 +235,20 @@ struct CopilotView: View { Self.copilotAuthService = nil }.onChange(of: settings.nodePath) { _ in Self.copilotAuthService = nil + }.onChange(of: viewModel.installationStep) { newValue in + if let step = newValue { + switch step { + case .downloading: + toast(Text("Downloading.."), .info) + case .uninstalling: + toast(Text("Uninstalling old version.."), .info) + case .decompressing: + toast(Text("Decompressing.."), .info) + case .done: + toast(Text("Done!"), .info) + checkStatus() + } + } } } diff --git a/Core/Sources/Service/FileSaveWatcher.swift b/Core/Sources/Service/FileSaveWatcher.swift new file mode 100644 index 00000000..97c01428 --- /dev/null +++ b/Core/Sources/Service/FileSaveWatcher.swift @@ -0,0 +1,39 @@ +import Foundation + +final class FileSaveWatcher { + let url: URL + var fileHandle: FileHandle? + var source: DispatchSourceFileSystemObject? + var changeHandler: () -> Void = {} + + init(fileURL: URL) { + url = fileURL + startup() + } + + deinit { + source?.cancel() + } + + func startup() { + if let source = source { + source.cancel() + } + + fileHandle = try? FileHandle(forReadingFrom: url) + if let fileHandle = fileHandle { + source = DispatchSource.makeFileSystemObjectSource( + fileDescriptor: fileHandle.fileDescriptor, + eventMask: .link, + queue: .main + ) + + source?.setEventHandler { [weak self] in + self?.changeHandler() + self?.startup() + } + + source?.resume() + } + } +} diff --git a/Core/Sources/Service/GUI/WidgetDataSource.swift b/Core/Sources/Service/GUI/WidgetDataSource.swift index 2ade5c1f..5c67c2c4 100644 --- a/Core/Sources/Service/GUI/WidgetDataSource.swift +++ b/Core/Sources/Service/GUI/WidgetDataSource.swift @@ -41,7 +41,6 @@ final class WidgetDataSource { @discardableResult func createChatIfNeeded(for url: URL) -> ChatService { let build = { - let language = UserDefaults.shared.value(for: \.chatGPTLanguage) let service = ChatService(chatGPTService: ChatGPTService()) let provider = ChatProvider( service: service, diff --git a/Core/Sources/Service/OpenedFileRocoverableStorage.swift b/Core/Sources/Service/OpenedFileRocoverableStorage.swift new file mode 100644 index 00000000..ad715141 --- /dev/null +++ b/Core/Sources/Service/OpenedFileRocoverableStorage.swift @@ -0,0 +1,36 @@ +import Foundation +import Preferences + +@ServiceActor +final class OpenedFileRecoverableStorage { + let projectRootURL: URL + let userDefault = UserDefaults.shared + let key = "OpenedFileRecoverableStorage" + + init(projectRootURL: URL) { + self.projectRootURL = projectRootURL + } + + func openFile(fileURL: URL) { + var dict = userDefault.dictionary(forKey: key) ?? [:] + var openedFiles = Set(dict[projectRootURL.path] as? [String] ?? []) + openedFiles.insert(fileURL.path) + dict[projectRootURL.path] = Array(openedFiles) + userDefault.set(dict, forKey: key) + } + + func closeFile(fileURL: URL) { + var dict = userDefault.dictionary(forKey: key) ?? [:] + var openedFiles = dict[projectRootURL.path] as? [String] ?? [] + openedFiles.removeAll(where: { $0 == fileURL.path }) + dict[projectRootURL.path] = openedFiles + userDefault.set(dict, forKey: key) + } + + var openedFiles: [URL] { + let dict = userDefault.dictionary(forKey: key) ?? [:] + let openedFiles = dict[projectRootURL.path] as? [String] ?? [] + return openedFiles.map { URL(fileURLWithPath: $0) } + } +} + diff --git a/Core/Sources/Service/Workspace.swift b/Core/Sources/Service/Workspace.swift index bed11b6f..7056a054 100644 --- a/Core/Sources/Service/Workspace.swift +++ b/Core/Sources/Service/Workspace.swift @@ -8,8 +8,11 @@ import SuggestionInjector import SuggestionModel import SuggestionService import UserDefaultsObserver +import XcodeInspector import XPCShared +// MARK: - Filespace + @ServiceActor final class Filespace { struct Snapshot: Equatable { @@ -66,6 +69,8 @@ final class Filespace { } } +// MARK: - Workspace + @ServiceActor final class Workspace { struct SuggestionFeatureDisabledError: Error, LocalizedError { @@ -75,6 +80,7 @@ final class Workspace { } let projectRootURL: URL + let openedFileRecoverableStorage: OpenedFileRecoverableStorage var lastSuggestionUpdateTime = Environment.now() var isExpired: Bool { Environment.now().timeIntervalSince(lastSuggestionUpdateTime) > 60 * 60 * 8 @@ -93,17 +99,7 @@ final class Workspace { ], context: nil ) - private var _suggestionService: SuggestionServiceType? { - didSet { - guard _suggestionService != nil else { return } - Task { - try await Task.sleep(nanoseconds: 1_000_000_000) - for (_, filespace) in filespaces { - notifyOpenFile(filespace: filespace) - } - } - } - } + private var _suggestionService: SuggestionServiceType? private var suggestionService: SuggestionServiceType? { // Check if the workspace is disabled. @@ -144,11 +140,17 @@ final class Workspace { private init(projectRootURL: URL) { self.projectRootURL = projectRootURL + openedFileRecoverableStorage = .init(projectRootURL: projectRootURL) userDefaultsObserver.onChange = { [weak self] in guard let self else { return } _ = self.suggestionService } + + let openedFiles = openedFileRecoverableStorage.openedFiles + for fileURL in openedFiles { + _ = createFilespaceIfNeeded(fileURL: fileURL) + } } func refreshUpdateTime() { @@ -167,18 +169,37 @@ final class Workspace { return false } + /// This is the only way to create a workspace and a filespace. static func fetchOrCreateWorkspaceIfNeeded(fileURL: URL) async throws -> (workspace: Workspace, filespace: Filespace) { - // never create duplicated filespaces + // If we know which project is opened. + if let currentProjectURL = try await Environment.fetchCurrentProjectRootURLFromXcode() { + if let existed = workspaces[currentProjectURL] { + let filespace = existed.createFilespaceIfNeeded(fileURL: fileURL) + return (existed, filespace) + } + + let new = Workspace(projectRootURL: currentProjectURL) + workspaces[currentProjectURL] = new + let filespace = new.createFilespaceIfNeeded(fileURL: fileURL) + return (new, filespace) + } + + // If not, we try to reuse a filespace if found. + // + // Sometimes, we can't get the project root path from Xcode window, for example, when the + // quick open window in displayed. for workspace in workspaces.values { if let filespace = workspace.filespaces[fileURL] { return (workspace, filespace) } } - let projectURL = try await Environment.fetchCurrentProjectRootURL(fileURL) - let workspaceURL = projectURL ?? fileURL + // If we can't find an existed one, we will try to guess it. + // Most of the time we won't enter this branch, just incase. + + let workspaceURL = try await Environment.guessProjectRootURLForFile(fileURL) let workspace = { if let existed = workspaces[workspaceURL] { @@ -199,7 +220,7 @@ final class Workspace { return (workspace, filespace) } - func createFilespaceIfNeeded(fileURL: URL) -> Filespace { + private func createFilespaceIfNeeded(fileURL: URL) -> Filespace { let existedFilespace = filespaces[fileURL] let filespace = existedFilespace ?? .init(fileURL: fileURL, onSave: { [weak self] filespace in @@ -218,6 +239,8 @@ final class Workspace { } } +// MARK: - Suggestion + extension Workspace { @discardableResult func generateSuggestions( @@ -338,6 +361,7 @@ extension Workspace { func notifyOpenFile(filespace: Filespace) { refreshUpdateTime() + openedFileRecoverableStorage.openFile(fileURL: filespace.fileURL) Task { try await suggestionService?.notifyOpenTextDocument( fileURL: filespace.fileURL, @@ -366,6 +390,8 @@ extension Workspace { } } +// MARK: - Cleanup + extension Workspace { func cleanUp(availableTabs: Set) { for (fileURL, _) in filespaces { @@ -373,6 +399,7 @@ extension Workspace { Task { try await suggestionService?.notifyCloseTextDocument(fileURL: fileURL) } + openedFileRecoverableStorage.closeFile(fileURL: fileURL) filespaces[fileURL] = nil } } @@ -392,42 +419,3 @@ extension Workspace { realtimeSuggestionRequests = [] } } - -final class FileSaveWatcher { - let url: URL - var fileHandle: FileHandle? - var source: DispatchSourceFileSystemObject? - var changeHandler: () -> Void = {} - - init(fileURL: URL) { - url = fileURL - startup() - } - - deinit { - source?.cancel() - } - - func startup() { - if let source = source { - source.cancel() - } - - fileHandle = try? FileHandle(forReadingFrom: url) - if let fileHandle { - source = DispatchSource.makeFileSystemObjectSource( - fileDescriptor: fileHandle.fileDescriptor, - eventMask: .link, - queue: .main - ) - - source?.setEventHandler { [weak self] in - self?.changeHandler() - self?.startup() - } - - source?.resume() - } - } -} - diff --git a/Core/Sources/SuggestionWidget/SuggestionWidgetController.swift b/Core/Sources/SuggestionWidget/SuggestionWidgetController.swift index 162ce8d4..98afd703 100644 --- a/Core/Sources/SuggestionWidget/SuggestionWidgetController.swift +++ b/Core/Sources/SuggestionWidget/SuggestionWidgetController.swift @@ -204,7 +204,7 @@ public final class SuggestionWidgetController: NSObject { guard let activeXcode = ActiveApplicationMonitor.activeXcode else { continue } guard fullscreenDetector.isOnActiveSpace else { continue } let app = AXUIElementCreateApplication(activeXcode.processIdentifier) - if let window = app.focusedWindow { + if app.focusedWindow != nil { orderFront() } } diff --git a/Core/Sources/SuggestionWidget/WidgetView.swift b/Core/Sources/SuggestionWidget/WidgetView.swift index 7908c234..e266d7b6 100644 --- a/Core/Sources/SuggestionWidget/WidgetView.swift +++ b/Core/Sources/SuggestionWidget/WidgetView.swift @@ -228,7 +228,13 @@ struct WidgetContextMenu: View { func updateProjectPath(fileURL: URL?) { Task { - let projectURL = try? await Environment.fetchCurrentProjectRootURL(fileURL) + let projectURL: URL? = await { + if let url = try? await Environment.fetchCurrentProjectRootURLFromXcode() { + return url + } + guard let fileURL else { return nil } + return try? await Environment.guessProjectRootURLForFile(fileURL) + }() if let projectURL { Task { @MainActor in self.fileURL = fileURL diff --git a/Core/Tests/ServiceTests/Environment.swift b/Core/Tests/ServiceTests/Environment.swift index 949c7e32..c2e99b06 100644 --- a/Core/Tests/ServiceTests/Environment.swift +++ b/Core/Tests/ServiceTests/Environment.swift @@ -14,7 +14,7 @@ import XPCShared Environment.now = { Date() } - Environment.fetchCurrentProjectRootURL = { _ in + Environment.fetchCurrentProjectRootURLFromXcode = { URL(fileURLWithPath: "/path/to/project") } diff --git a/ExtensionService/AppDelegate.swift b/ExtensionService/AppDelegate.swift index 1538d48b..fecf169c 100644 --- a/ExtensionService/AppDelegate.swift +++ b/ExtensionService/AppDelegate.swift @@ -33,7 +33,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { _ = GraphicalUserInterfaceController.shared _ = RealtimeSuggestionController.shared _ = XcodeInspector.shared - AXIsProcessTrustedWithOptions(nil) + AXIsProcessTrustedWithOptions([ + kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true + ] as CFDictionary) setupQuitOnUpdate() setupQuitOnUserTerminated() xpcListener = setupXPCListener() diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon.png new file mode 100644 index 00000000..5af40630 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@128w.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@128w.png new file mode 100644 index 00000000..592f927b Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@128w.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@16w.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@16w.png new file mode 100644 index 00000000..09658ce1 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@16w.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w 1.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w 1.png new file mode 100644 index 00000000..4a7d88ed Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w 1.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w.png new file mode 100644 index 00000000..4a7d88ed Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@256w.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w 1.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w 1.png new file mode 100644 index 00000000..6c4293c8 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w 1.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w.png new file mode 100644 index 00000000..6c4293c8 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@32w.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w 1.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w 1.png new file mode 100644 index 00000000..db461044 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w 1.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w.png new file mode 100644 index 00000000..db461044 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@512w.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@64w.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@64w.png new file mode 100644 index 00000000..42d7a164 Binary files /dev/null and b/ExtensionService/Assets.xcassets/AppIcon.appiconset/1024 x 1024 your icon@64w.png differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/Contents.json b/ExtensionService/Assets.xcassets/AppIcon.appiconset/Contents.json index a03c1da5..56acb569 100644 --- a/ExtensionService/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ExtensionService/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,61 +1,61 @@ { "images" : [ { - "filename" : "app-icon-realistic-materials_2x 9.png", + "filename" : "1024 x 1024 your icon@16w.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, { - "filename" : "app-icon-realistic-materials_2x 8.png", + "filename" : "1024 x 1024 your icon@32w 1.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, { - "filename" : "app-icon-realistic-materials_2x 7.png", + "filename" : "1024 x 1024 your icon@32w.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, { - "filename" : "app-icon-realistic-materials_2x 6.png", + "filename" : "1024 x 1024 your icon@64w.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, { - "filename" : "app-icon-realistic-materials_2x 5.png", + "filename" : "1024 x 1024 your icon@128w.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, { - "filename" : "app-icon-realistic-materials_2x 4.png", + "filename" : "1024 x 1024 your icon@256w 1.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, { - "filename" : "app-icon-realistic-materials_2x 3.png", + "filename" : "1024 x 1024 your icon@256w.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, { - "filename" : "app-icon-realistic-materials_2x 2.png", + "filename" : "1024 x 1024 your icon@512w 1.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { - "filename" : "app-icon-realistic-materials_2x 1.png", + "filename" : "1024 x 1024 your icon@512w.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { - "filename" : "app-icon-realistic-materials_2x.png", + "filename" : "1024 x 1024 your icon.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 1.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 1.png deleted file mode 100644 index 267da1f8..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 1.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 2.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 2.png deleted file mode 100644 index 267da1f8..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 2.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 3.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 3.png deleted file mode 100644 index ff87360f..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 3.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 4.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 4.png deleted file mode 100644 index ff87360f..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 4.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 5.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 5.png deleted file mode 100644 index 48f29e28..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 5.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 6.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 6.png deleted file mode 100644 index 51fc4d9b..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 6.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 7.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 7.png deleted file mode 100644 index 9f23c1ae..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 7.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 8.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 8.png deleted file mode 100644 index 9f23c1ae..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 8.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 9.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 9.png deleted file mode 100644 index 3ccd8a06..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x 9.png and /dev/null differ diff --git a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x.png b/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x.png deleted file mode 100644 index 2d98e582..00000000 Binary files a/ExtensionService/Assets.xcassets/AppIcon.appiconset/app-icon-realistic-materials_2x.png and /dev/null differ diff --git a/LICENSE b/LICENSE index 99858ea1..d3e5da7b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,19 +1,689 @@ -Copyright (c) 2021 Shangxin Guo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +# Copilot for Xcode Open Source License + +This license is a combination of the GPLv3 and some additional agreements. + +As a contributor, you agree that your contributed code: +a. may be subject to a more permissive open-source license in the future. +b. can be used for commercial purposes. + +With the GPLv3 and these supplementary agreements, anyone can freely use, modify, and distribute the project, provided that: +- For commercial use of this project or forks of this project, please contact us for authorization. + +Copyright (c) 2023 Shangxin Guo + +---------- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index a9bcc9af..31662599 100644 --- a/README.md +++ b/README.md @@ -275,11 +275,4 @@ fi ## License -MIT. - -## Credits - -The app uses the LSP provided through [Copilot.vim](https://github.com/github/copilot.vim/tree/release/copilot/dist) to generate suggestions and displays them as comments or in a separate window. - -Thanks to [LSP-copilot](https://github.com/TerminalFi/LSP-copilot) for showing the way to interact with GitHub Copilot. And thanks to [LanguageClient](https://github.com/ChimeHQ/LanguageClient) for the Language Server Protocol support in Swift. - +Please check [LICENSE](LICENSE) for details. diff --git a/ScreenRecording.gif b/ScreenRecording.gif deleted file mode 100644 index a9e66e07..00000000 Binary files a/ScreenRecording.gif and /dev/null differ diff --git a/copilot.vim b/copilot.vim deleted file mode 160000 index 1358e8e4..00000000 --- a/copilot.vim +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1358e8e45ecedc53daf971924a0541ddf6224faf