Workflow
Saving a File with Save Participants
Intercepting a save event, allowing an extension to modify a file (e.g. formatting) before Mountain writes it to disk.
Saving a File with Save Participants
Explains the process of intercepting a save event, allowing an extension in Cocoon to modify a file (e.g. for formatting) before Mountain writes it to disk.
Data Flow
User presses Ctrl+S (editor is dirty)
-> workbench.action.files.save command
-> IEditorService.save()
-> TextFileEditorModelManager.save()
-> WorkingCopyFileService.runSaveParticipants()
-> Gather ISaveParticipants
-> ExtHostSaveParticipant.participate()
-> Wind sends $participateInSave gRPC to Cocoon
Cocoon:
-> ExtHostDocumentSaveParticipant fires onWillSaveTextDocument
-> Prettier extension calculates formatting edits
-> Extension returns Promise<TextEdit[]>
-> All extensions resolve, edits collected
-> Serialize TextEdits to DTOs
-> Return array of TextEdit DTOs to Wind
Wind/UI:
-> BulkEditService applies TextEdits to document model in memory
-> TextFileEditorModelManager proceeds to save
-> IFileService.writeFile()
-> TauriDiskFileSystemProvider -> WriteFile Effect -> TauriInvoke
Mountain:
-> FsWriter receives call
-> tokio::fs::write(path, content)
-> Success returned up the chain
Wind/UI:
-> TextFileEditorModel no longer dirty
-> UI removes filled-circle indicator from editor tab
-> Save completePhase 1: User Action and Initial Save Trigger (Wind/Sky)
- User presses
Ctrl+Sin a dirty editor.workbench.action.files.savedispatched. IEditorService.save()identifies the active editor and callssaveon itsEditorInput.TextFileEditorModelManagerdoes not immediately write to disk. It enters the Save Participants phase.- Emits a
willSaveevent, orchestrated byIWorkingCopyFileService.
Phase 2: Orchestration via Save Participants (Wind -> Cocoon -> Wind)
WorkingCopyFileService.runSaveParticipants()gathers all registeredISaveParticipants. One isExtHostSaveParticipant, responsible for communicating with extensions in Cocoon.- Calls
participate()onExtHostSaveParticipant, which makes a$participateInSavegRPC request to Cocoon with the document URI and save reason.
Phase 3: Extension Execution (Cocoon)
- Cocoon’s gRPC server dispatches to
ExtHostDocumentSaveParticipant. - Service fires
onWillSaveTextDocumentevent to all subscribed extensions. - Prettier extension calculates formatting edits, returns
Promise<TextEdit[]>. - Service collects all results, serializes
TextEditobjects to DTOs viaTypeConverter, returns to Wind.
Phase 4: Applying Edits and Final Save (Wind -> Mountain -> Disk)
- gRPC call resolves with text edits from extensions.
BulkEditServiceapplies theTextEdits to the document model in memory. Editor content now reflects formatted code.TextFileEditorModelManagerproceeds to callIFileService.writeFile().- Save follows the same path as Opening a File (Workflow #2):
IFileService->TauriDiskFileSystemProvider->WriteFileEffect ->TauriInvoke-> Mountain. tokio::fs::write(path, content)writes the formatted document to disk.TextFileEditorModelis no longer dirty. UI removes the dirty indicator.
Key Source Files
Wind/Source/Application/BulkEdit/Live.ts— bulk edit serviceWind/Source/Application/File/Live.ts— file serviceMountain/Source/FileSystem/— filesystem providers
