@@ -8,7 +8,9 @@ use tauri::{AppHandle, Emitter, Manager, Runtime};
88
99use super :: pane_state:: PaneStateStore ;
1010use super :: protocol:: { INTERNAL_ERROR , INVALID_PARAMS } ;
11- use crate :: commands:: ui:: { set_view_mode, toggle_hidden_files} ;
11+ use crate :: commands:: ui:: {
12+ copy_to_clipboard, get_info, quick_look, set_view_mode, show_in_finder, toggle_hidden_files,
13+ } ;
1214
1315/// Result of tool execution.
1416pub type ToolResult = Result < Value , ToolError > ;
@@ -63,13 +65,20 @@ pub fn execute_tool<R: Runtime>(app: &AppHandle<R>, name: &str, params: &Value)
6365fn execute_app_command < R : Runtime > ( app : & AppHandle < R > , name : & str ) -> ToolResult {
6466 match name {
6567 "app_quit" => {
66- app. emit ( "mcp-action" , json ! ( { "action" : "quit" } ) )
67- . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
68+ app. exit ( 0 ) ;
6869 Ok ( json ! ( { "success" : true } ) )
6970 }
7071 "app_hide" => {
71- app. emit ( "mcp-action" , json ! ( { "action" : "hide" } ) )
72- . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
72+ // Use macOS NSApplication hide (same as ⌘H)
73+ #[ cfg( target_os = "macos" ) ]
74+ {
75+ use objc2:: MainThreadMarker ;
76+ use objc2_app_kit:: NSApplication ;
77+ if let Some ( mtm) = MainThreadMarker :: new ( ) {
78+ let app_instance = NSApplication :: sharedApplication ( mtm) ;
79+ app_instance. hide ( None ) ;
80+ }
81+ }
7382 Ok ( json ! ( { "success" : true } ) )
7483 }
7584 "app_about" => {
@@ -108,16 +117,6 @@ fn execute_pane_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResul
108117 . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
109118 Ok ( json ! ( { "success" : true } ) )
110119 }
111- "pane_leftVolumeChooser" => {
112- app. emit ( "mcp-action" , json ! ( { "action" : "leftVolumeChooser" } ) )
113- . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
114- Ok ( json ! ( { "success" : true } ) )
115- }
116- "pane_rightVolumeChooser" => {
117- app. emit ( "mcp-action" , json ! ( { "action" : "rightVolumeChooser" } ) )
118- . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
119- Ok ( json ! ( { "success" : true } ) )
120- }
121120 _ => Err ( ToolError :: invalid_params ( format ! ( "Unknown pane command: {name}" ) ) ) ,
122121 }
123122}
@@ -166,31 +165,54 @@ fn execute_sort_command<R: Runtime>(app: &AppHandle<R>, name: &str) -> ToolResul
166165}
167166
168167/// Execute a file command.
168+ /// Gets the selected file from PaneStateStore and operates on it directly.
169169fn execute_file_command < R : Runtime > ( app : & AppHandle < R > , name : & str ) -> ToolResult {
170- let action = match name {
171- "file_showInFinder" => "showInFinder" ,
172- "file_copyPath" => "copyPath" ,
173- "file_copyFilename" => "copyFilename" ,
174- "file_quickLook" => "quickLook" ,
175- "file_getInfo" => "getInfo" ,
176- _ => return Err ( ToolError :: invalid_params ( format ! ( "Unknown file command: {name}" ) ) ) ,
170+ // Get the selected file from pane state
171+ let store = app
172+ . try_state :: < PaneStateStore > ( )
173+ . ok_or_else ( || ToolError :: internal ( "Pane state not initialized" ) ) ?;
174+
175+ let focused = store. get_focused_pane ( ) ;
176+ let pane = if focused == "right" {
177+ store. get_right ( )
178+ } else {
179+ store. get_left ( )
177180 } ;
178181
179- app. emit ( "mcp-action" , json ! ( { "action" : action, "type" : "file" } ) )
180- . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
181- Ok ( json ! ( { "success" : true } ) )
182+ let selected = pane
183+ . files
184+ . get ( pane. selected_index )
185+ . ok_or_else ( || ToolError :: internal ( "No file selected" ) ) ?;
186+
187+ match name {
188+ "file_showInFinder" => {
189+ show_in_finder ( selected. path . clone ( ) ) . map_err ( ToolError :: internal) ?;
190+ Ok ( json ! ( { "success" : true , "path" : selected. path} ) )
191+ }
192+ "file_copyPath" => {
193+ copy_to_clipboard ( app. clone ( ) , selected. path . clone ( ) ) . map_err ( ToolError :: internal) ?;
194+ Ok ( json ! ( { "success" : true , "copied" : selected. path} ) )
195+ }
196+ "file_copyFilename" => {
197+ copy_to_clipboard ( app. clone ( ) , selected. name . clone ( ) ) . map_err ( ToolError :: internal) ?;
198+ Ok ( json ! ( { "success" : true , "copied" : selected. name} ) )
199+ }
200+ "file_quickLook" => {
201+ quick_look ( selected. path . clone ( ) ) . map_err ( ToolError :: internal) ?;
202+ Ok ( json ! ( { "success" : true , "path" : selected. path} ) )
203+ }
204+ "file_getInfo" => {
205+ get_info ( selected. path . clone ( ) ) . map_err ( ToolError :: internal) ?;
206+ Ok ( json ! ( { "success" : true , "path" : selected. path} ) )
207+ }
208+ _ => Err ( ToolError :: invalid_params ( format ! ( "Unknown file command: {name}" ) ) ) ,
209+ }
182210}
183211
184212/// Execute a volume command.
213+ /// Note: volume listing is now a resource (cmdr://volumes), not a tool.
185214fn execute_volume_command < R : Runtime > ( app : & AppHandle < R > , name : & str , params : & Value ) -> ToolResult {
186215 match name {
187- "volume_list" => {
188- // Request volume list from frontend - it will respond via event
189- app. emit ( "mcp-volume-list-request" , ( ) )
190- . map_err ( |e| ToolError :: internal ( e. to_string ( ) ) ) ?;
191- // For now, return a placeholder - real implementation needs async response
192- Ok ( json ! ( { "note" : "Volume list requested, check mcp-volume-list-response event" } ) )
193- }
194216 "volume_selectLeft" | "volume_selectRight" => {
195217 let index = params
196218 . get ( "index" )
0 commit comments