Mountain/Command/
Bootstrap.rs1#![allow(non_snake_case, non_camel_case_types)]
14
15use std::{future::Future, pin::Pin, sync::Arc};
16
17use Common::{
18 DTO::WorkSpaceEditDTO::WorkSpaceEditDTO,
19 Document::OpenDocument::OpenDocument,
20 Effect::ApplicationRunTime::ApplicationRunTime as _,
21 Environment::Requires::Requires,
22 Error::CommonError::CommonError,
23 LanguageFeature::LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
24 UserInterface::ShowOpenDialog::ShowOpenDialog,
25 WorkSpace::ApplyWorkSpaceEdit::ApplyWorkSpaceEdit,
26};
27use log::info;
28use serde_json::{Value, json};
29use tauri::{AppHandle, WebviewWindow, Wry};
30use url::Url;
31
32use crate::{
33 ApplicationState::{
34 ApplicationState::{ApplicationState, MapLockError},
35 DTO::TreeViewStateDTO::TreeViewStateDTO,
36 },
37 Environment::CommandProvider::CommandHandler,
38 FileSystem::FileExplorerViewProvider::FileExplorerViewProvider,
39 RunTime::ApplicationRunTime::ApplicationRunTime,
40};
41
42fn CommandHelloWorld(
46 _ApplicationHandle:AppHandle<Wry>,
47
48 _Window:WebviewWindow<Wry>,
49
50 _RunTime:Arc<ApplicationRunTime>,
51
52 _Argument:Value,
53) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> {
54 Box::pin(async move {
55 info!("[Native Command] Hello from Mountain!");
56
57 Ok(json!("Hello from Mountain's native command!"))
58 })
59}
60
61fn CommandOpenFile(
63 _ApplicationHandle:AppHandle<Wry>,
64
65 _Window:WebviewWindow<Wry>,
66
67 RunTime:Arc<ApplicationRunTime>,
68
69 _Argument:Value,
70) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> {
71 Box::pin(async move {
72 info!("[Native Command] Executing Open File...");
73
74 let DialogResult = RunTime.Run(ShowOpenDialog(None)).await.map_err(|Error| Error.to_string())?;
75
76 if let Some(Paths) = DialogResult {
77 if let Some(Path) = Paths.first() {
78 let URI = Url::from_file_path(Path).map_err(|_| "Invalid file path".to_string())?;
80
81 let OpenDocumentEffect = OpenDocument(json!({ "external": URI.to_string() }), None, None);
82
83 RunTime.Run(OpenDocumentEffect).await.map_err(|Error| Error.to_string())?;
84 }
85 }
86
87 Ok(Value::Null)
88 })
89}
90
91fn CommandFormatDocument(
93 _ApplicationHandle:AppHandle<Wry>,
94
95 _Window:WebviewWindow<Wry>,
96
97 RunTime:Arc<ApplicationRunTime>,
98
99 _Argument:Value,
100) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> {
101 Box::pin(async move {
102 info!("[Native Command] Executing Format Document...");
103
104 let AppState = &RunTime.Environment.ApplicationState;
105
106 let URIString = AppState
107 .ActiveDocumentURI
108 .lock()
109 .map_err(MapLockError)
110 .map_err(|Error| Error.to_string())?
111 .clone()
112 .ok_or("No active document URI found in state".to_string())?;
113
114 let URI = Url::parse(&URIString).map_err(|_| "Invalid URI in window state".to_string())?;
115
116 let Options = json!({ "tabSize": 4, "insertSpaces": true });
118
119 let LanguageProvider:Arc<dyn LanguageFeatureProviderRegistry> = RunTime.Environment.Require();
121
122 let EditsOption = LanguageProvider
123 .ProvideDocumentFormattingEdits(URI.clone(), Options)
124 .await
125 .map_err(|Error| Error.to_string())?;
126
127 if let Some(Edits) = EditsOption {
128 if Edits.is_empty() {
129 info!("[Native Command] No formatting changes to apply.");
130
131 return Ok(Value::Null);
132 }
133
134 let WorkSpaceEdit = WorkSpaceEditDTO {
136 Edits:vec![(
137 serde_json::to_value(&URI).map_err(|Error| Error.to_string())?,
138 Edits
139 .into_iter()
140 .map(serde_json::to_value)
141 .collect::<Result<Vec<_>, _>>()
142 .map_err(|Error| Error.to_string())?,
143 )],
144 };
145
146 info!("[Native Command] Applying formatting edits...");
148
149 RunTime
150 .Run(ApplyWorkSpaceEdit(WorkSpaceEdit))
151 .await
152 .map_err(|Error| Error.to_string())?;
153 } else {
154 info!("[Native Command] No formatting provider found for this document.");
155 }
156
157 Ok(Value::Null)
158 })
159}
160
161pub fn RegisterNativeCommands(
165 AppHandle:&AppHandle<Wry>,
166
167 ApplicationState:&Arc<ApplicationState>,
168) -> Result<(), CommonError> {
169 let mut CommandRegistry = ApplicationState.CommandRegistry.lock().map_err(MapLockError)?;
171
172 info!("[Bootstrap] Registering native commands...");
173
174 CommandRegistry.insert("mountain.helloWorld".to_string(), CommandHandler::Native(CommandHelloWorld));
175
176 CommandRegistry.insert("mountain.openFile".to_string(), CommandHandler::Native(CommandOpenFile));
177
178 CommandRegistry.insert(
179 "workbench.action.files.openFile".to_string(),
180 CommandHandler::Native(CommandOpenFile),
181 );
182
183 CommandRegistry.insert(
184 "editor.action.formatDocument".to_string(),
185 CommandHandler::Native(CommandFormatDocument),
186 );
187
188 info!("[Bootstrap] {} native commands registered.", CommandRegistry.len());
189
190 drop(CommandRegistry);
191
192 let mut TreeViewRegistry = ApplicationState.ActiveTreeViews.lock().map_err(MapLockError)?;
194
195 info!("[Bootstrap] Registering native tree view providers...");
196
197 let ExplorerViewID = "workbench.view.explorer".to_string();
198
199 let ExplorerProvider = Arc::new(FileExplorerViewProvider::New(AppHandle.clone()));
200
201 TreeViewRegistry.insert(
202 ExplorerViewID.clone(),
203 TreeViewStateDTO {
204 ViewIdentifier:ExplorerViewID,
205
206 Provider:Some(ExplorerProvider),
207
208 SideCarIdentifier:None,
210
211 CanSelectMany:true,
212
213 HasHandleDrag:false,
214
215 HasHandleDrop:false,
216
217 Message:None,
218
219 Title:Some("Explorer".to_string()),
220
221 Description:None,
222 },
223 );
224
225 info!("[Bootstrap] {} native tree view providers registered.", TreeViewRegistry.len());
226
227 Ok(())
228}