@@ -3,6 +3,7 @@ import AppKit
33import AXExtension
44import CopilotService
55import Foundation
6+ import Logger
67
78public struct NoAccessToAccessibilityAPIError : Error , LocalizedError {
89 public var errorDescription : String ? {
@@ -104,6 +105,24 @@ public enum Environment {
104105 }
105106 throw FailedToFetchFileURLError ( )
106107 }
108+
109+ public static var fetchFocusedElementURI : ( ) async throws -> URL = {
110+ guard let xcode = ActiveApplicationMonitor . activeXcode
111+ ?? ActiveApplicationMonitor . latestXcode
112+ else {
113+ throw FailedToFetchFileURLError ( )
114+ }
115+
116+ let application = AXUIElementCreateApplication ( xcode. processIdentifier)
117+ let focusedElement = application. focusedElement
118+ if focusedElement? . description != " Source Editor " {
119+ let window = application. focusedWindow
120+ let id = window? . identifier. hashValue
121+ return URL ( fileURLWithPath: " /xcode-focused-element/ \( id ?? 0 ) " )
122+ }
123+
124+ return try await fetchCurrentFileURL ( )
125+ }
107126
108127 public static var createAuthService : ( ) -> CopilotAuthServiceType = {
109128 CopilotAuthService ( )
@@ -120,27 +139,71 @@ public enum Environment {
120139 else { return }
121140 let bundleName = Bundle . main
122141 . object ( forInfoDictionaryKey: " EXTENSION_BUNDLE_NAME " ) as! String
142+
143+ await Task . yield ( )
123144
124- /// check if menu is open, if not, click the menu item.
125- let appleScript = """
126- tell application " System Events "
127- set theprocs to every process whose unix id is \( activeXcode. processIdentifier)
128- repeat with proc in theprocs
129- set the frontmost of proc to true
130- tell proc
131- repeat with theMenu in menus of menu bar 1
132- set theValue to value of attribute " AXVisibleChildren " of theMenu
133- if theValue is not {} then
134- return
135- end if
136- end repeat
137- click menu item " \( name) " of menu 1 of menu item " \( bundleName) " of menu 1 of menu bar item " Editor " of menu bar 1
138- end tell
139- end repeat
140- end tell
141- """
145+ if UserDefaults . shared. value ( for: \. triggerActionWithAccessibilityAPI) {
146+ if !activeXcode. isActive { activeXcode. activate ( ) }
147+ let app = AXUIElementCreateApplication ( activeXcode. processIdentifier)
142148
143- try await runAppleScript ( appleScript)
149+ if let editorMenu = app. menuBar? . child ( title: " Editor " ) ,
150+ let commandMenu = editorMenu. child ( title: bundleName)
151+ {
152+ if let button = commandMenu. child ( title: name, role: " AXMenuItem " ) {
153+ let error = AXUIElementPerformAction ( button, kAXPressAction as CFString )
154+ if error != AXError . success {
155+ Logger . service
156+ . error ( " Trigger action \( name) failed: \( error. localizedDescription) " )
157+ throw error
158+ }
159+ }
160+ } else if let commandMenu = app. menuBar? . child ( title: bundleName) ,
161+ let button = commandMenu. child ( title: name, role: " AXMenuItem " )
162+ {
163+ let error = AXUIElementPerformAction ( button, kAXPressAction as CFString )
164+ if error != AXError . success {
165+ Logger . service
166+ . error ( " Trigger action \( name) failed: \( error. localizedDescription) " )
167+ throw error
168+ }
169+ } else {
170+ struct CantRunCommand : Error , LocalizedError {
171+ let name : String
172+ var errorDescription : String ? {
173+ " Can't run command \( name) . "
174+ }
175+ }
176+
177+ throw CantRunCommand ( name: name)
178+ }
179+ } else {
180+ /// check if menu is open, if not, click the menu item.
181+ let appleScript = """
182+ tell application " System Events "
183+ set theprocs to every process whose unix id is \( activeXcode. processIdentifier)
184+ repeat with proc in theprocs
185+ set the frontmost of proc to true
186+ tell proc
187+ repeat with theMenu in menus of menu bar 1
188+ set theValue to value of attribute " AXVisibleChildren " of theMenu
189+ if theValue is not {} then
190+ return
191+ end if
192+ end repeat
193+ click menu item " \( name) " of menu 1 of menu item " \( bundleName) " of menu 1 of menu bar item " Editor " of menu bar 1
194+ end tell
195+ end repeat
196+ end tell
197+ """
198+
199+ do {
200+ try await runAppleScript ( appleScript)
201+ } catch {
202+ Logger . service
203+ . error ( " Trigger action \( name) failed: \( error. localizedDescription) " )
204+ throw error
205+ }
206+ }
144207 }
145208
146209 public static var makeXcodeActive : ( ) async throws -> Void = {
0 commit comments