@theia/plugin-ext 1.53.0-next.55 → 1.53.0-next.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -54
- package/lib/common/plugin-api-rpc.d.ts +1 -4
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +9 -9
- package/lib/main/browser/editors-and-documents-main.d.ts.map +1 -1
- package/lib/main/browser/editors-and-documents-main.js +14 -2
- package/lib/main/browser/editors-and-documents-main.js.map +1 -1
- package/lib/main/browser/notebooks/notebook-documents-and-editors-main.d.ts.map +1 -1
- package/lib/main/browser/notebooks/notebook-documents-and-editors-main.js +2 -0
- package/lib/main/browser/notebooks/notebook-documents-and-editors-main.js.map +1 -1
- package/lib/main/browser/notebooks/renderers/cell-output-webview.js +86 -86
- package/lib/main/browser/plugin-icon-theme-service.js +20 -20
- package/lib/main/browser/plugin-shared-style.js +14 -14
- package/lib/main/browser/tabs/tabs-main.d.ts +1 -1
- package/lib/main/browser/tabs/tabs-main.d.ts.map +1 -1
- package/lib/main/browser/tabs/tabs-main.js +1 -1
- package/lib/main/browser/tabs/tabs-main.js.map +1 -1
- package/lib/main/browser/text-editor-main.d.ts +6 -3
- package/lib/main/browser/text-editor-main.d.ts.map +1 -1
- package/lib/main/browser/text-editor-main.js +39 -5
- package/lib/main/browser/text-editor-main.js.map +1 -1
- package/lib/main/browser/view/plugin-view-registry.js +3 -3
- package/lib/main/browser/webview/webview-frontend-security-warnings.js +2 -2
- package/lib/main/browser/webview/webview-secondary-window-support.js +10 -10
- package/lib/main/browser/workspace-main.d.ts +0 -2
- package/lib/main/browser/workspace-main.d.ts.map +1 -1
- package/lib/main/node/plugin-service.d.ts +1 -1
- package/lib/main/node/webview-backend-security-warnings.js +6 -6
- package/lib/plugin/languages.d.ts +0 -1
- package/lib/plugin/languages.d.ts.map +1 -1
- package/lib/plugin/notebook/notebook-kernels.d.ts +0 -2
- package/lib/plugin/notebook/notebook-kernels.d.ts.map +1 -1
- package/lib/plugin/notebook/notebooks.d.ts +1 -0
- package/lib/plugin/notebook/notebooks.d.ts.map +1 -1
- package/lib/plugin/notebook/notebooks.js +22 -2
- package/lib/plugin/notebook/notebooks.js.map +1 -1
- package/lib/plugin/scm.d.ts +0 -1
- package/lib/plugin/scm.d.ts.map +1 -1
- package/lib/plugin/terminal-ext.d.ts +0 -1
- package/lib/plugin/terminal-ext.d.ts.map +1 -1
- package/lib/plugin/text-editor.d.ts +1 -1
- package/lib/plugin/text-editor.d.ts.map +1 -1
- package/lib/plugin/text-editor.js.map +1 -1
- package/lib/plugin/type-converters.d.ts +0 -1
- package/lib/plugin/type-converters.d.ts.map +1 -1
- package/lib/plugin/types-impl.d.ts +2 -3
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/workspace.d.ts +0 -4
- package/lib/plugin/workspace.d.ts.map +1 -1
- package/package.json +28 -28
- package/src/common/arrays.ts +70 -70
- package/src/common/assert.ts +23 -23
- package/src/common/cache.ts +51 -51
- package/src/common/character-classifier.ts +73 -73
- package/src/common/collections.ts +54 -54
- package/src/common/commands.ts +19 -19
- package/src/common/connection.ts +137 -137
- package/src/common/disposable-util.ts +39 -39
- package/src/common/editor-options.ts +74 -74
- package/src/common/env.ts +19 -19
- package/src/common/errors.ts +63 -63
- package/src/common/id-generator.ts +26 -26
- package/src/common/index.ts +24 -24
- package/src/common/language-pack-service.ts +34 -34
- package/src/common/link-computer.ts +354 -354
- package/src/common/object-identifier.ts +33 -33
- package/src/common/objects.ts +50 -50
- package/src/common/paths-util.ts +158 -158
- package/src/common/plugin-api-rpc-model.ts +907 -907
- package/src/common/plugin-api-rpc.ts +2753 -2752
- package/src/common/plugin-ext-api-contribution.ts +115 -115
- package/src/common/plugin-identifiers.ts +84 -84
- package/src/common/plugin-protocol.ts +1094 -1094
- package/src/common/reference-map.ts +38 -38
- package/src/common/rpc-protocol.ts +306 -306
- package/src/common/semantic-tokens-dto.ts +182 -182
- package/src/common/test-types.ts +154 -154
- package/src/common/types.ts +129 -129
- package/src/common/uint.ts +37 -37
- package/src/common/uri-components.ts +81 -81
- package/src/hosted/browser/hosted-plugin-watcher.ts +54 -54
- package/src/hosted/browser/hosted-plugin.ts +635 -635
- package/src/hosted/browser/plugin-worker.ts +52 -52
- package/src/hosted/browser/worker/debug-stub.ts +29 -29
- package/src/hosted/browser/worker/plugin-manifest-loader.ts +114 -114
- package/src/hosted/browser/worker/worker-env-ext.ts +40 -40
- package/src/hosted/browser/worker/worker-main.ts +212 -212
- package/src/hosted/browser/worker/worker-plugin-module.ts +80 -80
- package/src/hosted/common/hosted-plugin.ts +456 -456
- package/src/hosted/node/hosted-plugin-cli-contribution.ts +75 -75
- package/src/hosted/node/hosted-plugin-deployer-handler.ts +274 -274
- package/src/hosted/node/hosted-plugin-localization-service.ts +410 -410
- package/src/hosted/node/hosted-plugin-process.ts +248 -248
- package/src/hosted/node/hosted-plugin-protocol.ts +49 -49
- package/src/hosted/node/hosted-plugin.ts +116 -116
- package/src/hosted/node/metadata-scanner.ts +64 -64
- package/src/hosted/node/plugin-activation-events.ts +112 -112
- package/src/hosted/node/plugin-ext-hosted-backend-module.ts +94 -94
- package/src/hosted/node/plugin-host-module.ts +69 -69
- package/src/hosted/node/plugin-host-proxy.ts +82 -82
- package/src/hosted/node/plugin-host-rpc.ts +377 -377
- package/src/hosted/node/plugin-host.ts +110 -110
- package/src/hosted/node/plugin-language-pack-service.ts +43 -43
- package/src/hosted/node/plugin-manifest-loader.ts +32 -32
- package/src/hosted/node/plugin-reader.ts +136 -136
- package/src/hosted/node/plugin-service.ts +197 -197
- package/src/hosted/node/scanners/backend-init-theia.ts +71 -71
- package/src/hosted/node/scanners/file-plugin-uri-factory.ts +32 -32
- package/src/hosted/node/scanners/grammars-reader.ts +57 -57
- package/src/hosted/node/scanners/plugin-uri-factory.ts +33 -33
- package/src/hosted/node/scanners/scanner-theia.ts +963 -963
- package/src/hosted/node-electron/plugin-ext-hosted-electron-backend-module.ts +26 -26
- package/src/hosted/node-electron/scanner-theia-electron.ts +32 -32
- package/src/main/browser/authentication-main.ts +401 -401
- package/src/main/browser/clipboard-main.ts +38 -38
- package/src/main/browser/command-registry-main.ts +130 -130
- package/src/main/browser/commands.ts +104 -104
- package/src/main/browser/comments/comment-glyph-widget.ts +66 -66
- package/src/main/browser/comments/comment-thread-widget.tsx +696 -696
- package/src/main/browser/comments/comments-context-key-service.ts +68 -68
- package/src/main/browser/comments/comments-contribution.ts +268 -268
- package/src/main/browser/comments/comments-decorator.ts +110 -110
- package/src/main/browser/comments/comments-main.ts +482 -482
- package/src/main/browser/comments/comments-service.ts +205 -205
- package/src/main/browser/custom-editors/custom-editor-opener.tsx +205 -205
- package/src/main/browser/custom-editors/custom-editor-service.ts +108 -108
- package/src/main/browser/custom-editors/custom-editor-undo-redo-handler.ts +41 -41
- package/src/main/browser/custom-editors/custom-editor-widget-factory.ts +44 -44
- package/src/main/browser/custom-editors/custom-editor-widget.ts +127 -127
- package/src/main/browser/custom-editors/custom-editors-main.ts +526 -526
- package/src/main/browser/custom-editors/plugin-custom-editor-registry.ts +126 -126
- package/src/main/browser/data-transfer/data-transfer-type-converters.ts +68 -68
- package/src/main/browser/debug/debug-main.ts +397 -397
- package/src/main/browser/debug/plugin-debug-adapter-contribution.ts +48 -48
- package/src/main/browser/debug/plugin-debug-configuration-provider.ts +63 -63
- package/src/main/browser/debug/plugin-debug-service.ts +427 -427
- package/src/main/browser/debug/plugin-debug-session-contribution-registry.ts +76 -76
- package/src/main/browser/debug/plugin-debug-session-factory.ts +115 -115
- package/src/main/browser/decorations/decorations-main.ts +146 -146
- package/src/main/browser/dialogs/modal-notification.ts +112 -112
- package/src/main/browser/dialogs/style/modal-notification.css +123 -123
- package/src/main/browser/dialogs-main.ts +185 -185
- package/src/main/browser/documents-main.ts +275 -275
- package/src/main/browser/editors-and-documents-main.ts +448 -425
- package/src/main/browser/env-main.ts +60 -60
- package/src/main/browser/file-system-main-impl.ts +267 -267
- package/src/main/browser/hierarchy/hierarchy-types-converters.ts +189 -189
- package/src/main/browser/keybindings/keybindings-contribution-handler.ts +66 -66
- package/src/main/browser/label-service-main.ts +51 -51
- package/src/main/browser/languages-main.ts +1439 -1439
- package/src/main/browser/localization-main.ts +34 -34
- package/src/main/browser/main-context.ts +210 -210
- package/src/main/browser/main-file-system-event-service.ts +76 -76
- package/src/main/browser/menus/menus-contribution-handler.ts +172 -172
- package/src/main/browser/menus/plugin-menu-command-adapter.ts +358 -358
- package/src/main/browser/menus/vscode-theia-menu-mappings.ts +118 -118
- package/src/main/browser/message-registry-main.ts +43 -43
- package/src/main/browser/notebooks/notebook-documents-and-editors-main.ts +252 -249
- package/src/main/browser/notebooks/notebook-documents-main.ts +202 -202
- package/src/main/browser/notebooks/notebook-dto.ts +131 -131
- package/src/main/browser/notebooks/notebook-editors-main.ts +88 -88
- package/src/main/browser/notebooks/notebook-kernels-main.ts +339 -339
- package/src/main/browser/notebooks/notebook-renderers-main.ts +47 -47
- package/src/main/browser/notebooks/notebooks-main.ts +164 -164
- package/src/main/browser/notebooks/renderers/cell-output-webview.tsx +452 -452
- package/src/main/browser/notebooks/renderers/output-webview-internal.ts +636 -636
- package/src/main/browser/notebooks/renderers/webview-communication.ts +107 -107
- package/src/main/browser/notification-main.ts +26 -26
- package/src/main/browser/output-channel-registry-main.ts +53 -53
- package/src/main/browser/plugin-authentication-service.ts +71 -71
- package/src/main/browser/plugin-contribution-handler.ts +698 -698
- package/src/main/browser/plugin-ext-frontend-module.ts +291 -291
- package/src/main/browser/plugin-ext-widget.tsx +132 -132
- package/src/main/browser/plugin-frontend-contribution.ts +70 -70
- package/src/main/browser/plugin-frontend-view-contribution.ts +38 -38
- package/src/main/browser/plugin-icon-service.ts +92 -92
- package/src/main/browser/plugin-icon-theme-service.ts +625 -625
- package/src/main/browser/plugin-shared-style.ts +154 -154
- package/src/main/browser/plugin-storage.ts +55 -55
- package/src/main/browser/plugin-terminal-registry.ts +27 -27
- package/src/main/browser/preference-registry-main.ts +123 -123
- package/src/main/browser/quick-open-main.ts +367 -367
- package/src/main/browser/scm-main.ts +472 -472
- package/src/main/browser/secrets-main.ts +82 -82
- package/src/main/browser/selection-provider-command.ts +45 -45
- package/src/main/browser/status-bar-message-registry-main.ts +90 -90
- package/src/main/browser/style/comments.css +345 -345
- package/src/main/browser/style/index.css +84 -84
- package/src/main/browser/style/plugin-sidebar.css +73 -73
- package/src/main/browser/style/tree.css +54 -54
- package/src/main/browser/style/webview.css +55 -55
- package/src/main/browser/tabs/tabs-main.ts +388 -384
- package/src/main/browser/tasks-main.ts +268 -268
- package/src/main/browser/terminal-main.ts +370 -370
- package/src/main/browser/test-main.ts +632 -632
- package/src/main/browser/text-editor-main.ts +519 -478
- package/src/main/browser/text-editor-model-service.ts +111 -111
- package/src/main/browser/text-editors-main.ts +234 -234
- package/src/main/browser/theme-icon-override.ts +246 -246
- package/src/main/browser/theming-main.ts +42 -42
- package/src/main/browser/timeline-main.ts +80 -80
- package/src/main/browser/uri-main.ts +72 -72
- package/src/main/browser/view/dnd-file-content-store.ts +42 -42
- package/src/main/browser/view/plugin-tree-view-node-label-provider.ts +81 -81
- package/src/main/browser/view/plugin-view-registry.ts +967 -967
- package/src/main/browser/view/plugin-view-widget.ts +221 -221
- package/src/main/browser/view/tree-view-decorator-service.ts +51 -51
- package/src/main/browser/view/tree-view-widget.tsx +931 -931
- package/src/main/browser/view/tree-views-main.ts +205 -205
- package/src/main/browser/view/view-context-key-service.ts +64 -64
- package/src/main/browser/webview/pre/fake.html +14 -14
- package/src/main/browser/webview/pre/host.js +130 -130
- package/src/main/browser/webview/pre/index.html +17 -17
- package/src/main/browser/webview/pre/main.js +682 -682
- package/src/main/browser/webview/pre/service-worker.js +296 -296
- package/src/main/browser/webview/webview-context-keys.ts +62 -62
- package/src/main/browser/webview/webview-environment.ts +87 -87
- package/src/main/browser/webview/webview-frontend-security-warnings.ts +59 -59
- package/src/main/browser/webview/webview-preferences.ts +72 -72
- package/src/main/browser/webview/webview-resource-cache.ts +88 -88
- package/src/main/browser/webview/webview-secondary-window-support.ts +47 -47
- package/src/main/browser/webview/webview-theme-data-provider.ts +124 -124
- package/src/main/browser/webview/webview.ts +718 -718
- package/src/main/browser/webview-views/webview-views-main.ts +154 -154
- package/src/main/browser/webview-views/webview-views.ts +43 -43
- package/src/main/browser/webviews-main.ts +287 -287
- package/src/main/browser/window-activity-tracker.ts +96 -96
- package/src/main/browser/window-state-main.ts +85 -85
- package/src/main/browser/workspace-main.ts +424 -424
- package/src/main/common/basic-message-registry-main.ts +53 -53
- package/src/main/common/basic-notification-main.ts +86 -86
- package/src/main/common/env-main.ts +44 -44
- package/src/main/common/plugin-paths-protocol.ts +26 -26
- package/src/main/common/plugin-theia-environment.ts +36 -36
- package/src/main/common/webview-protocol.ts +28 -28
- package/src/main/electron-browser/plugin-ext-frontend-electron-module.ts +25 -25
- package/src/main/electron-browser/webview/electron-webview-widget-factory.ts +59 -59
- package/src/main/node/errors.spec.ts +37 -37
- package/src/main/node/handlers/plugin-theia-directory-handler.ts +137 -137
- package/src/main/node/handlers/plugin-theia-file-handler.ts +66 -66
- package/src/main/node/paths/const.ts +21 -21
- package/src/main/node/paths/plugin-paths-service.ts +163 -163
- package/src/main/node/plugin-cli-contribution.ts +85 -85
- package/src/main/node/plugin-deployer-contribution.ts +35 -35
- package/src/main/node/plugin-deployer-directory-handler-context-impl.ts +45 -45
- package/src/main/node/plugin-deployer-entry-impl.ts +132 -132
- package/src/main/node/plugin-deployer-file-handler-context-impl.ts +33 -33
- package/src/main/node/plugin-deployer-impl.ts +375 -375
- package/src/main/node/plugin-deployer-proxy-entry-impl.ts +96 -96
- package/src/main/node/plugin-deployer-resolver-context-impl.ts +55 -55
- package/src/main/node/plugin-ext-backend-module.ts +106 -106
- package/src/main/node/plugin-github-resolver.ts +139 -139
- package/src/main/node/plugin-http-resolver.ts +92 -92
- package/src/main/node/plugin-localization-server.ts +42 -42
- package/src/main/node/plugin-mgmt-cli-contribution.ts +64 -64
- package/src/main/node/plugin-remote-cli-contribution.ts +36 -36
- package/src/main/node/plugin-remote-copy-contribution.ts +36 -36
- package/src/main/node/plugin-server-handler.ts +69 -69
- package/src/main/node/plugin-service.ts +97 -97
- package/src/main/node/plugin-theia-deployer-participant.ts +32 -32
- package/src/main/node/plugin-uninstallation-manager.ts +74 -74
- package/src/main/node/plugins-key-value-storage.spec.ts +110 -110
- package/src/main/node/plugins-key-value-storage.ts +161 -161
- package/src/main/node/resolvers/local-directory-plugin-deployer-resolver.ts +37 -37
- package/src/main/node/resolvers/local-plugin-deployer-resolver.ts +56 -56
- package/src/main/node/temp-dir-util.ts +36 -36
- package/src/main/node/webview-backend-security-warnings.ts +45 -45
- package/src/main/style/status-bar.css +35 -35
- package/src/plugin/authentication-ext.ts +140 -140
- package/src/plugin/clipboard-ext.ts +43 -43
- package/src/plugin/command-registry.ts +219 -219
- package/src/plugin/comments.ts +549 -549
- package/src/plugin/custom-editors.ts +334 -334
- package/src/plugin/debug/debug-ext.ts +549 -549
- package/src/plugin/debug/plugin-debug-adapter-creator.ts +50 -50
- package/src/plugin/debug/plugin-debug-adapter-session.ts +106 -106
- package/src/plugin/debug/plugin-debug-adapter-tracker.ts +85 -85
- package/src/plugin/decorations.ts +140 -140
- package/src/plugin/dialogs.ts +96 -96
- package/src/plugin/document-data.ts +366 -366
- package/src/plugin/documents.ts +283 -283
- package/src/plugin/editors-and-documents.ts +176 -176
- package/src/plugin/env.ts +134 -134
- package/src/plugin/file-system-event-service-ext-impl.ts +256 -256
- package/src/plugin/file-system-ext-impl.ts +415 -415
- package/src/plugin/known-commands.spec.ts +50 -50
- package/src/plugin/known-commands.ts +429 -429
- package/src/plugin/label-service.ts +36 -36
- package/src/plugin/languages/call-hierarchy.ts +124 -124
- package/src/plugin/languages/code-action.ts +162 -162
- package/src/plugin/languages/color.ts +75 -75
- package/src/plugin/languages/completion.ts +183 -183
- package/src/plugin/languages/declaration.ts +72 -72
- package/src/plugin/languages/definition.ts +73 -73
- package/src/plugin/languages/diagnostics.ts +325 -325
- package/src/plugin/languages/document-drop-edit.ts +44 -44
- package/src/plugin/languages/document-formatting.ts +47 -47
- package/src/plugin/languages/document-highlight.ts +61 -61
- package/src/plugin/languages/evaluatable-expression.ts +47 -47
- package/src/plugin/languages/folding.ts +46 -46
- package/src/plugin/languages/hover.ts +58 -58
- package/src/plugin/languages/implementation.ts +73 -73
- package/src/plugin/languages/inlay-hints.ts +149 -149
- package/src/plugin/languages/inline-completion.ts +126 -126
- package/src/plugin/languages/inline-values.ts +50 -50
- package/src/plugin/languages/lens.ts +102 -102
- package/src/plugin/languages/link-provider.ts +81 -81
- package/src/plugin/languages/linked-editing-range.ts +48 -48
- package/src/plugin/languages/on-type-formatting.ts +50 -50
- package/src/plugin/languages/outline.ts +126 -126
- package/src/plugin/languages/range-formatting.ts +48 -48
- package/src/plugin/languages/reference.ts +58 -58
- package/src/plugin/languages/rename.ts +130 -130
- package/src/plugin/languages/selection-range.ts +80 -80
- package/src/plugin/languages/semantic-highlighting.ts +211 -211
- package/src/plugin/languages/signature.ts +82 -82
- package/src/plugin/languages/type-definition.ts +73 -73
- package/src/plugin/languages/type-hierarchy.ts +117 -117
- package/src/plugin/languages/util.ts +26 -26
- package/src/plugin/languages/workspace-symbol.ts +66 -66
- package/src/plugin/languages-utils.ts +68 -68
- package/src/plugin/languages.ts +1022 -1022
- package/src/plugin/localization-ext.ts +89 -89
- package/src/plugin/markdown-string.ts +115 -115
- package/src/plugin/message-registry.ts +70 -70
- package/src/plugin/node/debug/debug.spec.ts +98 -98
- package/src/plugin/node/debug/plugin-node-debug-adapter-creator.ts +167 -167
- package/src/plugin/node/env-node-ext.ts +64 -64
- package/src/plugin/node/plugin-container-module.ts +165 -165
- package/src/plugin/notebook/notebook-document.ts +446 -446
- package/src/plugin/notebook/notebook-documents.ts +58 -58
- package/src/plugin/notebook/notebook-editor.ts +116 -116
- package/src/plugin/notebook/notebook-editors.ts +71 -71
- package/src/plugin/notebook/notebook-kernels.ts +631 -631
- package/src/plugin/notebook/notebook-renderers.ts +71 -71
- package/src/plugin/notebook/notebooks.ts +470 -449
- package/src/plugin/notification.ts +80 -80
- package/src/plugin/output-channel/log-output-channel.ts +108 -108
- package/src/plugin/output-channel/output-channel-item.ts +73 -73
- package/src/plugin/output-channel-registry.ts +52 -52
- package/src/plugin/path.spec.ts +40 -40
- package/src/plugin/path.ts +68 -68
- package/src/plugin/plugin-context.ts +1606 -1606
- package/src/plugin/plugin-icon-path.ts +53 -53
- package/src/plugin/plugin-manager.ts +508 -508
- package/src/plugin/plugin-storage.ts +138 -138
- package/src/plugin/preference-registry.spec.ts +288 -288
- package/src/plugin/preference-registry.ts +335 -335
- package/src/plugin/prefix-sum-computer.ts +218 -218
- package/src/plugin/quick-open.ts +735 -735
- package/src/plugin/scm.ts +919 -919
- package/src/plugin/secrets-ext.ts +104 -104
- package/src/plugin/status-bar/status-bar-item.ts +193 -193
- package/src/plugin/status-bar-message-registry.ts +103 -103
- package/src/plugin/tabs.ts +431 -431
- package/src/plugin/tasks/task-provider.ts +57 -57
- package/src/plugin/tasks/tasks.ts +252 -252
- package/src/plugin/telemetry-ext.ts +298 -298
- package/src/plugin/terminal-ext.ts +569 -569
- package/src/plugin/test-item.ts +174 -174
- package/src/plugin/tests.ts +545 -545
- package/src/plugin/text-editor.ts +581 -581
- package/src/plugin/text-editors.ts +157 -157
- package/src/plugin/theming.ts +73 -73
- package/src/plugin/timeline.ts +186 -186
- package/src/plugin/tree/tree-views.ts +682 -682
- package/src/plugin/type-converters.spec.ts +476 -476
- package/src/plugin/type-converters.ts +1768 -1768
- package/src/plugin/types-impl.spec.ts +85 -85
- package/src/plugin/types-impl.ts +4011 -4011
- package/src/plugin/uri-ext.ts +60 -60
- package/src/plugin/webview-views.ts +228 -228
- package/src/plugin/webviews.ts +468 -468
- package/src/plugin/window-state.ts +75 -75
- package/src/plugin/word-helper.ts +162 -162
- package/src/plugin/workspace.ts +505 -505
- package/src/plugin-ext-backend-electron-module.ts +24 -24
- package/src/plugin-ext-backend-module.ts +24 -24
- package/src/plugin-ext-frontend-electron-module.ts +19 -19
- package/src/plugin-ext-frontend-module.ts +19 -19
|
@@ -1,526 +1,526 @@
|
|
|
1
|
-
// *****************************************************************************
|
|
2
|
-
// Copyright (C) 2021 SAP SE or an SAP affiliate company and others.
|
|
3
|
-
//
|
|
4
|
-
// This program and the accompanying materials are made available under the
|
|
5
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
-
//
|
|
8
|
-
// This Source Code may also be made available under the following Secondary
|
|
9
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
-
// with the GNU Classpath Exception which is available at
|
|
12
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
-
//
|
|
14
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
-
// *****************************************************************************
|
|
16
|
-
/*---------------------------------------------------------------------------------------------
|
|
17
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
18
|
-
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
19
|
-
*--------------------------------------------------------------------------------------------*/
|
|
20
|
-
// some code copied and modified from https://github.com/microsoft/vscode/blob/53eac52308c4611000a171cc7bf1214293473c78/src/vs/workbench/api/browser/mainThreadCustomEditors.ts
|
|
21
|
-
|
|
22
|
-
import { interfaces } from '@theia/core/shared/inversify';
|
|
23
|
-
import { MAIN_RPC_CONTEXT, CustomEditorsMain, CustomEditorsExt, CustomTextEditorCapabilities } from '../../../common/plugin-api-rpc';
|
|
24
|
-
import { RPCProtocol } from '../../../common/rpc-protocol';
|
|
25
|
-
import { HostedPluginSupport } from '../../../hosted/browser/hosted-plugin';
|
|
26
|
-
import { PluginCustomEditorRegistry } from './plugin-custom-editor-registry';
|
|
27
|
-
import { Emitter } from '@theia/core';
|
|
28
|
-
import { UriComponents } from '../../../common/uri-components';
|
|
29
|
-
import { URI } from '@theia/core/shared/vscode-uri';
|
|
30
|
-
import TheiaURI from '@theia/core/lib/common/uri';
|
|
31
|
-
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
|
|
32
|
-
import { Reference } from '@theia/core/lib/common/reference';
|
|
33
|
-
import { CancellationToken, CancellationTokenSource } from '@theia/core/lib/common/cancellation';
|
|
34
|
-
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
|
|
35
|
-
import { EditorModelService } from '../text-editor-model-service';
|
|
36
|
-
import { CustomEditorService } from './custom-editor-service';
|
|
37
|
-
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
38
|
-
import { UndoRedoService } from '@theia/editor/lib/browser/undo-redo-service';
|
|
39
|
-
import { WebviewsMainImpl } from '../webviews-main';
|
|
40
|
-
import { WidgetManager } from '@theia/core/lib/browser/widget-manager';
|
|
41
|
-
import { ApplicationShell, LabelProvider, Saveable, SaveOptions } from '@theia/core/lib/browser';
|
|
42
|
-
import { WebviewPanelOptions } from '@theia/plugin';
|
|
43
|
-
import { EditorPreferences } from '@theia/editor/lib/browser';
|
|
44
|
-
|
|
45
|
-
const enum CustomEditorModelType {
|
|
46
|
-
Custom,
|
|
47
|
-
Text,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export class CustomEditorsMainImpl implements CustomEditorsMain, Disposable {
|
|
51
|
-
protected readonly pluginService: HostedPluginSupport;
|
|
52
|
-
protected readonly shell: ApplicationShell;
|
|
53
|
-
protected readonly textModelService: EditorModelService;
|
|
54
|
-
protected readonly fileService: FileService;
|
|
55
|
-
protected readonly customEditorService: CustomEditorService;
|
|
56
|
-
protected readonly undoRedoService: UndoRedoService;
|
|
57
|
-
protected readonly customEditorRegistry: PluginCustomEditorRegistry;
|
|
58
|
-
protected readonly labelProvider: LabelProvider;
|
|
59
|
-
protected readonly widgetManager: WidgetManager;
|
|
60
|
-
protected readonly editorPreferences: EditorPreferences;
|
|
61
|
-
private readonly proxy: CustomEditorsExt;
|
|
62
|
-
private readonly editorProviders = new Map<string, Disposable>();
|
|
63
|
-
|
|
64
|
-
constructor(rpc: RPCProtocol,
|
|
65
|
-
container: interfaces.Container,
|
|
66
|
-
readonly webviewsMain: WebviewsMainImpl,
|
|
67
|
-
) {
|
|
68
|
-
this.pluginService = container.get(HostedPluginSupport);
|
|
69
|
-
this.shell = container.get(ApplicationShell);
|
|
70
|
-
this.textModelService = container.get(EditorModelService);
|
|
71
|
-
this.fileService = container.get(FileService);
|
|
72
|
-
this.customEditorService = container.get(CustomEditorService);
|
|
73
|
-
this.undoRedoService = container.get(UndoRedoService);
|
|
74
|
-
this.customEditorRegistry = container.get(PluginCustomEditorRegistry);
|
|
75
|
-
this.labelProvider = container.get(LabelProvider);
|
|
76
|
-
this.editorPreferences = container.get(EditorPreferences);
|
|
77
|
-
this.widgetManager = container.get(WidgetManager);
|
|
78
|
-
this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.CUSTOM_EDITORS_EXT);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
dispose(): void {
|
|
82
|
-
for (const disposable of this.editorProviders.values()) {
|
|
83
|
-
disposable.dispose();
|
|
84
|
-
}
|
|
85
|
-
this.editorProviders.clear();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
$registerTextEditorProvider(
|
|
89
|
-
viewType: string, options: WebviewPanelOptions, capabilities: CustomTextEditorCapabilities): void {
|
|
90
|
-
this.registerEditorProvider(CustomEditorModelType.Text, viewType, options, capabilities, true);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
$registerCustomEditorProvider(viewType: string, options: WebviewPanelOptions, supportsMultipleEditorsPerDocument: boolean): void {
|
|
94
|
-
this.registerEditorProvider(CustomEditorModelType.Custom, viewType, options, {}, supportsMultipleEditorsPerDocument);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
protected async registerEditorProvider(
|
|
98
|
-
modelType: CustomEditorModelType,
|
|
99
|
-
viewType: string,
|
|
100
|
-
options: WebviewPanelOptions,
|
|
101
|
-
capabilities: CustomTextEditorCapabilities,
|
|
102
|
-
supportsMultipleEditorsPerDocument: boolean,
|
|
103
|
-
): Promise<void> {
|
|
104
|
-
if (this.editorProviders.has(viewType)) {
|
|
105
|
-
throw new Error(`Provider for ${viewType} already registered`);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const disposables = new DisposableCollection();
|
|
109
|
-
|
|
110
|
-
disposables.push(
|
|
111
|
-
this.customEditorRegistry.registerResolver(viewType, async widget => {
|
|
112
|
-
|
|
113
|
-
const { resource, identifier } = widget;
|
|
114
|
-
widget.options = options;
|
|
115
|
-
|
|
116
|
-
const cancellationSource = new CancellationTokenSource();
|
|
117
|
-
let modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, cancellationSource.token);
|
|
118
|
-
widget.modelRef = modelRef;
|
|
119
|
-
|
|
120
|
-
widget.onDidDispose(() => {
|
|
121
|
-
// If the model is still dirty, make sure we have time to save it
|
|
122
|
-
if (modelRef.object.dirty) {
|
|
123
|
-
const sub = modelRef.object.onDirtyChanged(() => {
|
|
124
|
-
if (!modelRef.object.dirty) {
|
|
125
|
-
sub.dispose();
|
|
126
|
-
modelRef.dispose();
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
modelRef.dispose();
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
if (capabilities.supportsMove) {
|
|
136
|
-
const onMoveCancelTokenSource = new CancellationTokenSource();
|
|
137
|
-
widget.onMove(async (newResource: TheiaURI) => {
|
|
138
|
-
const oldModel = modelRef;
|
|
139
|
-
modelRef = await this.getOrCreateCustomEditorModel(modelType, newResource, viewType, onMoveCancelTokenSource.token);
|
|
140
|
-
this.proxy.$onMoveCustomEditor(identifier.id, newResource.toComponents(), viewType);
|
|
141
|
-
oldModel.dispose();
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
this.webviewsMain.hookWebview(widget);
|
|
146
|
-
widget.title.label = this.labelProvider.getName(resource);
|
|
147
|
-
|
|
148
|
-
const _cancellationSource = new CancellationTokenSource();
|
|
149
|
-
await this.proxy.$resolveWebviewEditor(
|
|
150
|
-
resource.toComponents(),
|
|
151
|
-
identifier.id,
|
|
152
|
-
viewType,
|
|
153
|
-
widget.title.label,
|
|
154
|
-
widget.viewState.position,
|
|
155
|
-
options,
|
|
156
|
-
_cancellationSource.token
|
|
157
|
-
);
|
|
158
|
-
})
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
this.editorProviders.set(viewType, disposables);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
$unregisterEditorProvider(viewType: string): void {
|
|
165
|
-
const provider = this.editorProviders.get(viewType);
|
|
166
|
-
if (!provider) {
|
|
167
|
-
throw new Error(`No provider for ${viewType} registered`);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
provider.dispose();
|
|
171
|
-
this.editorProviders.delete(viewType);
|
|
172
|
-
|
|
173
|
-
this.customEditorService.models.disposeAllModelsForView(viewType);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
protected async getOrCreateCustomEditorModel(
|
|
177
|
-
modelType: CustomEditorModelType,
|
|
178
|
-
resource: TheiaURI,
|
|
179
|
-
viewType: string,
|
|
180
|
-
cancellationToken: CancellationToken,
|
|
181
|
-
): Promise<Reference<CustomEditorModel>> {
|
|
182
|
-
const existingModel = this.customEditorService.models.tryRetain(resource, viewType);
|
|
183
|
-
if (existingModel) {
|
|
184
|
-
return existingModel;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
switch (modelType) {
|
|
188
|
-
case CustomEditorModelType.Text: {
|
|
189
|
-
const model = CustomTextEditorModel.create(viewType, resource, this.textModelService, this.fileService);
|
|
190
|
-
return this.customEditorService.models.add(resource, viewType, model);
|
|
191
|
-
}
|
|
192
|
-
case CustomEditorModelType.Custom: {
|
|
193
|
-
const model = MainCustomEditorModel.create(this.proxy, viewType, resource, this.undoRedoService, this.fileService, cancellationToken);
|
|
194
|
-
return this.customEditorService.models.add(resource, viewType, model);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
protected async getCustomEditorModel(resourceComponents: UriComponents, viewType: string): Promise<MainCustomEditorModel> {
|
|
200
|
-
const resource = URI.revive(resourceComponents);
|
|
201
|
-
const model = await this.customEditorService.models.get(new TheiaURI(resource), viewType);
|
|
202
|
-
if (!model || !(model instanceof MainCustomEditorModel)) {
|
|
203
|
-
throw new Error('Could not find model for custom editor');
|
|
204
|
-
}
|
|
205
|
-
return model;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async $onDidEdit(resourceComponents: UriComponents, viewType: string, editId: number, label: string | undefined): Promise<void> {
|
|
209
|
-
const model = await this.getCustomEditorModel(resourceComponents, viewType);
|
|
210
|
-
model.pushEdit(editId, label);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
async $onContentChange(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
|
214
|
-
const model = await this.getCustomEditorModel(resourceComponents, viewType);
|
|
215
|
-
model.changeContent();
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export interface CustomEditorModel extends Saveable, Disposable {
|
|
220
|
-
readonly viewType: string;
|
|
221
|
-
readonly resource: URI;
|
|
222
|
-
readonly readonly: boolean;
|
|
223
|
-
readonly dirty: boolean;
|
|
224
|
-
|
|
225
|
-
revert(options?: Saveable.RevertOptions): Promise<void>;
|
|
226
|
-
saveCustomEditor(options?: SaveOptions): Promise<void>;
|
|
227
|
-
saveCustomEditorAs(resource: TheiaURI, targetResource: TheiaURI, options?: SaveOptions): Promise<void>;
|
|
228
|
-
|
|
229
|
-
undo(): void;
|
|
230
|
-
redo(): void;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export class MainCustomEditorModel implements CustomEditorModel {
|
|
234
|
-
private currentEditIndex: number = -1;
|
|
235
|
-
private savePoint: number = -1;
|
|
236
|
-
private isDirtyFromContentChange = false;
|
|
237
|
-
private ongoingSave?: CancellationTokenSource;
|
|
238
|
-
private readonly edits: Array<number> = [];
|
|
239
|
-
private readonly toDispose = new DisposableCollection();
|
|
240
|
-
|
|
241
|
-
private readonly onDirtyChangedEmitter = new Emitter<void>();
|
|
242
|
-
readonly onDirtyChanged = this.onDirtyChangedEmitter.event;
|
|
243
|
-
|
|
244
|
-
private readonly onContentChangedEmitter = new Emitter<void>();
|
|
245
|
-
readonly onContentChanged = this.onContentChangedEmitter.event;
|
|
246
|
-
|
|
247
|
-
static async create(
|
|
248
|
-
proxy: CustomEditorsExt,
|
|
249
|
-
viewType: string,
|
|
250
|
-
resource: TheiaURI,
|
|
251
|
-
undoRedoService: UndoRedoService,
|
|
252
|
-
fileService: FileService,
|
|
253
|
-
cancellation: CancellationToken,
|
|
254
|
-
): Promise<MainCustomEditorModel> {
|
|
255
|
-
const { editable } = await proxy.$createCustomDocument(resource.toComponents(), viewType, {}, cancellation);
|
|
256
|
-
return new MainCustomEditorModel(proxy, viewType, resource, editable, undoRedoService, fileService);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
constructor(
|
|
260
|
-
private proxy: CustomEditorsExt,
|
|
261
|
-
readonly viewType: string,
|
|
262
|
-
private readonly editorResource: TheiaURI,
|
|
263
|
-
private readonly editable: boolean,
|
|
264
|
-
private readonly undoRedoService: UndoRedoService,
|
|
265
|
-
private readonly fileService: FileService
|
|
266
|
-
) {
|
|
267
|
-
this.toDispose.push(this.onDirtyChangedEmitter);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
get resource(): URI {
|
|
271
|
-
return URI.from(this.editorResource.toComponents());
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
get dirty(): boolean {
|
|
275
|
-
if (this.isDirtyFromContentChange) {
|
|
276
|
-
return true;
|
|
277
|
-
}
|
|
278
|
-
if (this.edits.length > 0) {
|
|
279
|
-
return this.savePoint !== this.currentEditIndex;
|
|
280
|
-
}
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
get readonly(): boolean {
|
|
285
|
-
return !this.editable;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
setProxy(proxy: CustomEditorsExt): void {
|
|
289
|
-
this.proxy = proxy;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
dispose(): void {
|
|
293
|
-
if (this.editable) {
|
|
294
|
-
this.undoRedoService.removeElements(this.editorResource);
|
|
295
|
-
}
|
|
296
|
-
this.proxy.$disposeCustomDocument(this.resource, this.viewType);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
changeContent(): void {
|
|
300
|
-
this.change(() => {
|
|
301
|
-
this.isDirtyFromContentChange = true;
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
pushEdit(editId: number, label: string | undefined): void {
|
|
306
|
-
if (!this.editable) {
|
|
307
|
-
throw new Error('Document is not editable');
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
this.change(() => {
|
|
311
|
-
this.spliceEdits(editId);
|
|
312
|
-
this.currentEditIndex = this.edits.length - 1;
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
this.undoRedoService.pushElement(
|
|
316
|
-
this.editorResource,
|
|
317
|
-
() => this.undo(),
|
|
318
|
-
() => this.redo(),
|
|
319
|
-
);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async revert(options?: Saveable.RevertOptions): Promise<void> {
|
|
323
|
-
if (!this.editable) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
if (this.currentEditIndex === this.savePoint && !this.isDirtyFromContentChange) {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const cancellationSource = new CancellationTokenSource();
|
|
332
|
-
this.proxy.$revert(this.resource, this.viewType, cancellationSource.token);
|
|
333
|
-
this.change(() => {
|
|
334
|
-
this.isDirtyFromContentChange = false;
|
|
335
|
-
this.currentEditIndex = this.savePoint;
|
|
336
|
-
this.spliceEdits();
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
async save(options?: SaveOptions): Promise<void> {
|
|
341
|
-
await this.saveCustomEditor(options);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
async saveCustomEditor(options?: SaveOptions): Promise<void> {
|
|
345
|
-
if (!this.editable) {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
const cancelable = new CancellationTokenSource();
|
|
350
|
-
const savePromise = this.proxy.$onSave(this.resource, this.viewType, cancelable.token);
|
|
351
|
-
this.ongoingSave?.cancel();
|
|
352
|
-
this.ongoingSave = cancelable;
|
|
353
|
-
|
|
354
|
-
try {
|
|
355
|
-
await savePromise;
|
|
356
|
-
|
|
357
|
-
if (this.ongoingSave === cancelable) { // Make sure we are still doing the same save
|
|
358
|
-
this.change(() => {
|
|
359
|
-
this.isDirtyFromContentChange = false;
|
|
360
|
-
this.savePoint = this.currentEditIndex;
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
} finally {
|
|
364
|
-
if (this.ongoingSave === cancelable) { // Make sure we are still doing the same save
|
|
365
|
-
this.ongoingSave = undefined;
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
async saveCustomEditorAs(resource: TheiaURI, targetResource: TheiaURI, options?: SaveOptions): Promise<void> {
|
|
371
|
-
if (this.editable) {
|
|
372
|
-
const source = new CancellationTokenSource();
|
|
373
|
-
await this.proxy.$onSaveAs(this.resource, this.viewType, targetResource.toComponents(), source.token);
|
|
374
|
-
this.change(() => {
|
|
375
|
-
this.savePoint = this.currentEditIndex;
|
|
376
|
-
});
|
|
377
|
-
} else {
|
|
378
|
-
// Since the editor is readonly, just copy the file over
|
|
379
|
-
await this.fileService.copy(resource, targetResource, { overwrite: false });
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
async undo(): Promise<void> {
|
|
384
|
-
if (!this.editable) {
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
if (this.currentEditIndex < 0) {
|
|
389
|
-
// nothing to undo
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const undoneEdit = this.edits[this.currentEditIndex];
|
|
394
|
-
this.change(() => {
|
|
395
|
-
--this.currentEditIndex;
|
|
396
|
-
});
|
|
397
|
-
await this.proxy.$undo(this.resource, this.viewType, undoneEdit, this.dirty);
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
async redo(): Promise<void> {
|
|
401
|
-
if (!this.editable) {
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if (this.currentEditIndex >= this.edits.length - 1) {
|
|
406
|
-
// nothing to redo
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const redoneEdit = this.edits[this.currentEditIndex + 1];
|
|
411
|
-
this.change(() => {
|
|
412
|
-
++this.currentEditIndex;
|
|
413
|
-
});
|
|
414
|
-
await this.proxy.$redo(this.resource, this.viewType, redoneEdit, this.dirty);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
private spliceEdits(editToInsert?: number): void {
|
|
418
|
-
const start = this.currentEditIndex + 1;
|
|
419
|
-
const toRemove = this.edits.length - this.currentEditIndex;
|
|
420
|
-
|
|
421
|
-
const removedEdits = typeof editToInsert === 'number'
|
|
422
|
-
? this.edits.splice(start, toRemove, editToInsert)
|
|
423
|
-
: this.edits.splice(start, toRemove);
|
|
424
|
-
|
|
425
|
-
if (removedEdits.length) {
|
|
426
|
-
this.proxy.$disposeEdits(this.resource, this.viewType, removedEdits);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
private change(makeEdit: () => void): void {
|
|
431
|
-
const wasDirty = this.dirty;
|
|
432
|
-
makeEdit();
|
|
433
|
-
|
|
434
|
-
if (this.dirty !== wasDirty) {
|
|
435
|
-
this.onDirtyChangedEmitter.fire();
|
|
436
|
-
}
|
|
437
|
-
this.onContentChangedEmitter.fire();
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// copied from https://github.com/microsoft/vscode/blob/53eac52308c4611000a171cc7bf1214293473c78/src/vs/workbench/contrib/customEditor/common/customTextEditorModel.ts
|
|
443
|
-
export class CustomTextEditorModel implements CustomEditorModel {
|
|
444
|
-
private readonly toDispose = new DisposableCollection();
|
|
445
|
-
private readonly onDirtyChangedEmitter = new Emitter<void>();
|
|
446
|
-
readonly onDirtyChanged = this.onDirtyChangedEmitter.event;
|
|
447
|
-
private readonly onContentChangedEmitter = new Emitter<void>();
|
|
448
|
-
readonly onContentChanged = this.onContentChangedEmitter.event;
|
|
449
|
-
|
|
450
|
-
static async create(
|
|
451
|
-
viewType: string,
|
|
452
|
-
resource: TheiaURI,
|
|
453
|
-
editorModelService: EditorModelService,
|
|
454
|
-
fileService: FileService,
|
|
455
|
-
): Promise<CustomTextEditorModel> {
|
|
456
|
-
const model = await editorModelService.createModelReference(resource);
|
|
457
|
-
model.object.suppressOpenEditorWhenDirty = true;
|
|
458
|
-
return new CustomTextEditorModel(viewType, resource, model, fileService);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
constructor(
|
|
462
|
-
readonly viewType: string,
|
|
463
|
-
readonly editorResource: TheiaURI,
|
|
464
|
-
private readonly model: Reference<MonacoEditorModel>,
|
|
465
|
-
private readonly fileService: FileService,
|
|
466
|
-
) {
|
|
467
|
-
this.toDispose.push(
|
|
468
|
-
this.editorTextModel.onDirtyChanged(e => {
|
|
469
|
-
this.onDirtyChangedEmitter.fire();
|
|
470
|
-
})
|
|
471
|
-
);
|
|
472
|
-
this.toDispose.push(
|
|
473
|
-
this.editorTextModel.onContentChanged(e => {
|
|
474
|
-
this.onContentChangedEmitter.fire();
|
|
475
|
-
})
|
|
476
|
-
);
|
|
477
|
-
this.toDispose.push(this.onDirtyChangedEmitter);
|
|
478
|
-
this.toDispose.push(this.onContentChangedEmitter);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
dispose(): void {
|
|
482
|
-
this.toDispose.dispose();
|
|
483
|
-
this.model.dispose();
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
get resource(): URI {
|
|
487
|
-
return URI.from(this.editorResource.toComponents());
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
get dirty(): boolean {
|
|
491
|
-
return this.editorTextModel.dirty;
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
get readonly(): boolean {
|
|
495
|
-
return Boolean(this.editorTextModel.readOnly);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
get editorTextModel(): MonacoEditorModel {
|
|
499
|
-
return this.model.object;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
revert(options?: Saveable.RevertOptions): Promise<void> {
|
|
503
|
-
return this.editorTextModel.revert(options);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
save(options?: SaveOptions): Promise<void> {
|
|
507
|
-
return this.saveCustomEditor(options);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
saveCustomEditor(options?: SaveOptions): Promise<void> {
|
|
511
|
-
return this.editorTextModel.save(options);
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
async saveCustomEditorAs(resource: TheiaURI, targetResource: TheiaURI, options?: SaveOptions): Promise<void> {
|
|
515
|
-
await this.saveCustomEditor(options);
|
|
516
|
-
await this.fileService.copy(resource, targetResource, { overwrite: false });
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
undo(): void {
|
|
520
|
-
this.editorTextModel.undo();
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
redo(): void {
|
|
524
|
-
this.editorTextModel.redo();
|
|
525
|
-
}
|
|
526
|
-
}
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2021 SAP SE or an SAP affiliate company and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
/*---------------------------------------------------------------------------------------------
|
|
17
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
18
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
19
|
+
*--------------------------------------------------------------------------------------------*/
|
|
20
|
+
// some code copied and modified from https://github.com/microsoft/vscode/blob/53eac52308c4611000a171cc7bf1214293473c78/src/vs/workbench/api/browser/mainThreadCustomEditors.ts
|
|
21
|
+
|
|
22
|
+
import { interfaces } from '@theia/core/shared/inversify';
|
|
23
|
+
import { MAIN_RPC_CONTEXT, CustomEditorsMain, CustomEditorsExt, CustomTextEditorCapabilities } from '../../../common/plugin-api-rpc';
|
|
24
|
+
import { RPCProtocol } from '../../../common/rpc-protocol';
|
|
25
|
+
import { HostedPluginSupport } from '../../../hosted/browser/hosted-plugin';
|
|
26
|
+
import { PluginCustomEditorRegistry } from './plugin-custom-editor-registry';
|
|
27
|
+
import { Emitter } from '@theia/core';
|
|
28
|
+
import { UriComponents } from '../../../common/uri-components';
|
|
29
|
+
import { URI } from '@theia/core/shared/vscode-uri';
|
|
30
|
+
import TheiaURI from '@theia/core/lib/common/uri';
|
|
31
|
+
import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
|
|
32
|
+
import { Reference } from '@theia/core/lib/common/reference';
|
|
33
|
+
import { CancellationToken, CancellationTokenSource } from '@theia/core/lib/common/cancellation';
|
|
34
|
+
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
|
|
35
|
+
import { EditorModelService } from '../text-editor-model-service';
|
|
36
|
+
import { CustomEditorService } from './custom-editor-service';
|
|
37
|
+
import { FileService } from '@theia/filesystem/lib/browser/file-service';
|
|
38
|
+
import { UndoRedoService } from '@theia/editor/lib/browser/undo-redo-service';
|
|
39
|
+
import { WebviewsMainImpl } from '../webviews-main';
|
|
40
|
+
import { WidgetManager } from '@theia/core/lib/browser/widget-manager';
|
|
41
|
+
import { ApplicationShell, LabelProvider, Saveable, SaveOptions } from '@theia/core/lib/browser';
|
|
42
|
+
import { WebviewPanelOptions } from '@theia/plugin';
|
|
43
|
+
import { EditorPreferences } from '@theia/editor/lib/browser';
|
|
44
|
+
|
|
45
|
+
const enum CustomEditorModelType {
|
|
46
|
+
Custom,
|
|
47
|
+
Text,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class CustomEditorsMainImpl implements CustomEditorsMain, Disposable {
|
|
51
|
+
protected readonly pluginService: HostedPluginSupport;
|
|
52
|
+
protected readonly shell: ApplicationShell;
|
|
53
|
+
protected readonly textModelService: EditorModelService;
|
|
54
|
+
protected readonly fileService: FileService;
|
|
55
|
+
protected readonly customEditorService: CustomEditorService;
|
|
56
|
+
protected readonly undoRedoService: UndoRedoService;
|
|
57
|
+
protected readonly customEditorRegistry: PluginCustomEditorRegistry;
|
|
58
|
+
protected readonly labelProvider: LabelProvider;
|
|
59
|
+
protected readonly widgetManager: WidgetManager;
|
|
60
|
+
protected readonly editorPreferences: EditorPreferences;
|
|
61
|
+
private readonly proxy: CustomEditorsExt;
|
|
62
|
+
private readonly editorProviders = new Map<string, Disposable>();
|
|
63
|
+
|
|
64
|
+
constructor(rpc: RPCProtocol,
|
|
65
|
+
container: interfaces.Container,
|
|
66
|
+
readonly webviewsMain: WebviewsMainImpl,
|
|
67
|
+
) {
|
|
68
|
+
this.pluginService = container.get(HostedPluginSupport);
|
|
69
|
+
this.shell = container.get(ApplicationShell);
|
|
70
|
+
this.textModelService = container.get(EditorModelService);
|
|
71
|
+
this.fileService = container.get(FileService);
|
|
72
|
+
this.customEditorService = container.get(CustomEditorService);
|
|
73
|
+
this.undoRedoService = container.get(UndoRedoService);
|
|
74
|
+
this.customEditorRegistry = container.get(PluginCustomEditorRegistry);
|
|
75
|
+
this.labelProvider = container.get(LabelProvider);
|
|
76
|
+
this.editorPreferences = container.get(EditorPreferences);
|
|
77
|
+
this.widgetManager = container.get(WidgetManager);
|
|
78
|
+
this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.CUSTOM_EDITORS_EXT);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
dispose(): void {
|
|
82
|
+
for (const disposable of this.editorProviders.values()) {
|
|
83
|
+
disposable.dispose();
|
|
84
|
+
}
|
|
85
|
+
this.editorProviders.clear();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
$registerTextEditorProvider(
|
|
89
|
+
viewType: string, options: WebviewPanelOptions, capabilities: CustomTextEditorCapabilities): void {
|
|
90
|
+
this.registerEditorProvider(CustomEditorModelType.Text, viewType, options, capabilities, true);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
$registerCustomEditorProvider(viewType: string, options: WebviewPanelOptions, supportsMultipleEditorsPerDocument: boolean): void {
|
|
94
|
+
this.registerEditorProvider(CustomEditorModelType.Custom, viewType, options, {}, supportsMultipleEditorsPerDocument);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
protected async registerEditorProvider(
|
|
98
|
+
modelType: CustomEditorModelType,
|
|
99
|
+
viewType: string,
|
|
100
|
+
options: WebviewPanelOptions,
|
|
101
|
+
capabilities: CustomTextEditorCapabilities,
|
|
102
|
+
supportsMultipleEditorsPerDocument: boolean,
|
|
103
|
+
): Promise<void> {
|
|
104
|
+
if (this.editorProviders.has(viewType)) {
|
|
105
|
+
throw new Error(`Provider for ${viewType} already registered`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const disposables = new DisposableCollection();
|
|
109
|
+
|
|
110
|
+
disposables.push(
|
|
111
|
+
this.customEditorRegistry.registerResolver(viewType, async widget => {
|
|
112
|
+
|
|
113
|
+
const { resource, identifier } = widget;
|
|
114
|
+
widget.options = options;
|
|
115
|
+
|
|
116
|
+
const cancellationSource = new CancellationTokenSource();
|
|
117
|
+
let modelRef = await this.getOrCreateCustomEditorModel(modelType, resource, viewType, cancellationSource.token);
|
|
118
|
+
widget.modelRef = modelRef;
|
|
119
|
+
|
|
120
|
+
widget.onDidDispose(() => {
|
|
121
|
+
// If the model is still dirty, make sure we have time to save it
|
|
122
|
+
if (modelRef.object.dirty) {
|
|
123
|
+
const sub = modelRef.object.onDirtyChanged(() => {
|
|
124
|
+
if (!modelRef.object.dirty) {
|
|
125
|
+
sub.dispose();
|
|
126
|
+
modelRef.dispose();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
modelRef.dispose();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (capabilities.supportsMove) {
|
|
136
|
+
const onMoveCancelTokenSource = new CancellationTokenSource();
|
|
137
|
+
widget.onMove(async (newResource: TheiaURI) => {
|
|
138
|
+
const oldModel = modelRef;
|
|
139
|
+
modelRef = await this.getOrCreateCustomEditorModel(modelType, newResource, viewType, onMoveCancelTokenSource.token);
|
|
140
|
+
this.proxy.$onMoveCustomEditor(identifier.id, newResource.toComponents(), viewType);
|
|
141
|
+
oldModel.dispose();
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.webviewsMain.hookWebview(widget);
|
|
146
|
+
widget.title.label = this.labelProvider.getName(resource);
|
|
147
|
+
|
|
148
|
+
const _cancellationSource = new CancellationTokenSource();
|
|
149
|
+
await this.proxy.$resolveWebviewEditor(
|
|
150
|
+
resource.toComponents(),
|
|
151
|
+
identifier.id,
|
|
152
|
+
viewType,
|
|
153
|
+
widget.title.label,
|
|
154
|
+
widget.viewState.position,
|
|
155
|
+
options,
|
|
156
|
+
_cancellationSource.token
|
|
157
|
+
);
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
this.editorProviders.set(viewType, disposables);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
$unregisterEditorProvider(viewType: string): void {
|
|
165
|
+
const provider = this.editorProviders.get(viewType);
|
|
166
|
+
if (!provider) {
|
|
167
|
+
throw new Error(`No provider for ${viewType} registered`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
provider.dispose();
|
|
171
|
+
this.editorProviders.delete(viewType);
|
|
172
|
+
|
|
173
|
+
this.customEditorService.models.disposeAllModelsForView(viewType);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
protected async getOrCreateCustomEditorModel(
|
|
177
|
+
modelType: CustomEditorModelType,
|
|
178
|
+
resource: TheiaURI,
|
|
179
|
+
viewType: string,
|
|
180
|
+
cancellationToken: CancellationToken,
|
|
181
|
+
): Promise<Reference<CustomEditorModel>> {
|
|
182
|
+
const existingModel = this.customEditorService.models.tryRetain(resource, viewType);
|
|
183
|
+
if (existingModel) {
|
|
184
|
+
return existingModel;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
switch (modelType) {
|
|
188
|
+
case CustomEditorModelType.Text: {
|
|
189
|
+
const model = CustomTextEditorModel.create(viewType, resource, this.textModelService, this.fileService);
|
|
190
|
+
return this.customEditorService.models.add(resource, viewType, model);
|
|
191
|
+
}
|
|
192
|
+
case CustomEditorModelType.Custom: {
|
|
193
|
+
const model = MainCustomEditorModel.create(this.proxy, viewType, resource, this.undoRedoService, this.fileService, cancellationToken);
|
|
194
|
+
return this.customEditorService.models.add(resource, viewType, model);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
protected async getCustomEditorModel(resourceComponents: UriComponents, viewType: string): Promise<MainCustomEditorModel> {
|
|
200
|
+
const resource = URI.revive(resourceComponents);
|
|
201
|
+
const model = await this.customEditorService.models.get(new TheiaURI(resource), viewType);
|
|
202
|
+
if (!model || !(model instanceof MainCustomEditorModel)) {
|
|
203
|
+
throw new Error('Could not find model for custom editor');
|
|
204
|
+
}
|
|
205
|
+
return model;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async $onDidEdit(resourceComponents: UriComponents, viewType: string, editId: number, label: string | undefined): Promise<void> {
|
|
209
|
+
const model = await this.getCustomEditorModel(resourceComponents, viewType);
|
|
210
|
+
model.pushEdit(editId, label);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async $onContentChange(resourceComponents: UriComponents, viewType: string): Promise<void> {
|
|
214
|
+
const model = await this.getCustomEditorModel(resourceComponents, viewType);
|
|
215
|
+
model.changeContent();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface CustomEditorModel extends Saveable, Disposable {
|
|
220
|
+
readonly viewType: string;
|
|
221
|
+
readonly resource: URI;
|
|
222
|
+
readonly readonly: boolean;
|
|
223
|
+
readonly dirty: boolean;
|
|
224
|
+
|
|
225
|
+
revert(options?: Saveable.RevertOptions): Promise<void>;
|
|
226
|
+
saveCustomEditor(options?: SaveOptions): Promise<void>;
|
|
227
|
+
saveCustomEditorAs(resource: TheiaURI, targetResource: TheiaURI, options?: SaveOptions): Promise<void>;
|
|
228
|
+
|
|
229
|
+
undo(): void;
|
|
230
|
+
redo(): void;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export class MainCustomEditorModel implements CustomEditorModel {
|
|
234
|
+
private currentEditIndex: number = -1;
|
|
235
|
+
private savePoint: number = -1;
|
|
236
|
+
private isDirtyFromContentChange = false;
|
|
237
|
+
private ongoingSave?: CancellationTokenSource;
|
|
238
|
+
private readonly edits: Array<number> = [];
|
|
239
|
+
private readonly toDispose = new DisposableCollection();
|
|
240
|
+
|
|
241
|
+
private readonly onDirtyChangedEmitter = new Emitter<void>();
|
|
242
|
+
readonly onDirtyChanged = this.onDirtyChangedEmitter.event;
|
|
243
|
+
|
|
244
|
+
private readonly onContentChangedEmitter = new Emitter<void>();
|
|
245
|
+
readonly onContentChanged = this.onContentChangedEmitter.event;
|
|
246
|
+
|
|
247
|
+
static async create(
|
|
248
|
+
proxy: CustomEditorsExt,
|
|
249
|
+
viewType: string,
|
|
250
|
+
resource: TheiaURI,
|
|
251
|
+
undoRedoService: UndoRedoService,
|
|
252
|
+
fileService: FileService,
|
|
253
|
+
cancellation: CancellationToken,
|
|
254
|
+
): Promise<MainCustomEditorModel> {
|
|
255
|
+
const { editable } = await proxy.$createCustomDocument(resource.toComponents(), viewType, {}, cancellation);
|
|
256
|
+
return new MainCustomEditorModel(proxy, viewType, resource, editable, undoRedoService, fileService);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
constructor(
|
|
260
|
+
private proxy: CustomEditorsExt,
|
|
261
|
+
readonly viewType: string,
|
|
262
|
+
private readonly editorResource: TheiaURI,
|
|
263
|
+
private readonly editable: boolean,
|
|
264
|
+
private readonly undoRedoService: UndoRedoService,
|
|
265
|
+
private readonly fileService: FileService
|
|
266
|
+
) {
|
|
267
|
+
this.toDispose.push(this.onDirtyChangedEmitter);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
get resource(): URI {
|
|
271
|
+
return URI.from(this.editorResource.toComponents());
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
get dirty(): boolean {
|
|
275
|
+
if (this.isDirtyFromContentChange) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
if (this.edits.length > 0) {
|
|
279
|
+
return this.savePoint !== this.currentEditIndex;
|
|
280
|
+
}
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
get readonly(): boolean {
|
|
285
|
+
return !this.editable;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
setProxy(proxy: CustomEditorsExt): void {
|
|
289
|
+
this.proxy = proxy;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
dispose(): void {
|
|
293
|
+
if (this.editable) {
|
|
294
|
+
this.undoRedoService.removeElements(this.editorResource);
|
|
295
|
+
}
|
|
296
|
+
this.proxy.$disposeCustomDocument(this.resource, this.viewType);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
changeContent(): void {
|
|
300
|
+
this.change(() => {
|
|
301
|
+
this.isDirtyFromContentChange = true;
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
pushEdit(editId: number, label: string | undefined): void {
|
|
306
|
+
if (!this.editable) {
|
|
307
|
+
throw new Error('Document is not editable');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
this.change(() => {
|
|
311
|
+
this.spliceEdits(editId);
|
|
312
|
+
this.currentEditIndex = this.edits.length - 1;
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
this.undoRedoService.pushElement(
|
|
316
|
+
this.editorResource,
|
|
317
|
+
() => this.undo(),
|
|
318
|
+
() => this.redo(),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async revert(options?: Saveable.RevertOptions): Promise<void> {
|
|
323
|
+
if (!this.editable) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (this.currentEditIndex === this.savePoint && !this.isDirtyFromContentChange) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const cancellationSource = new CancellationTokenSource();
|
|
332
|
+
this.proxy.$revert(this.resource, this.viewType, cancellationSource.token);
|
|
333
|
+
this.change(() => {
|
|
334
|
+
this.isDirtyFromContentChange = false;
|
|
335
|
+
this.currentEditIndex = this.savePoint;
|
|
336
|
+
this.spliceEdits();
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async save(options?: SaveOptions): Promise<void> {
|
|
341
|
+
await this.saveCustomEditor(options);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
async saveCustomEditor(options?: SaveOptions): Promise<void> {
|
|
345
|
+
if (!this.editable) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const cancelable = new CancellationTokenSource();
|
|
350
|
+
const savePromise = this.proxy.$onSave(this.resource, this.viewType, cancelable.token);
|
|
351
|
+
this.ongoingSave?.cancel();
|
|
352
|
+
this.ongoingSave = cancelable;
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
await savePromise;
|
|
356
|
+
|
|
357
|
+
if (this.ongoingSave === cancelable) { // Make sure we are still doing the same save
|
|
358
|
+
this.change(() => {
|
|
359
|
+
this.isDirtyFromContentChange = false;
|
|
360
|
+
this.savePoint = this.currentEditIndex;
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
} finally {
|
|
364
|
+
if (this.ongoingSave === cancelable) { // Make sure we are still doing the same save
|
|
365
|
+
this.ongoingSave = undefined;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async saveCustomEditorAs(resource: TheiaURI, targetResource: TheiaURI, options?: SaveOptions): Promise<void> {
|
|
371
|
+
if (this.editable) {
|
|
372
|
+
const source = new CancellationTokenSource();
|
|
373
|
+
await this.proxy.$onSaveAs(this.resource, this.viewType, targetResource.toComponents(), source.token);
|
|
374
|
+
this.change(() => {
|
|
375
|
+
this.savePoint = this.currentEditIndex;
|
|
376
|
+
});
|
|
377
|
+
} else {
|
|
378
|
+
// Since the editor is readonly, just copy the file over
|
|
379
|
+
await this.fileService.copy(resource, targetResource, { overwrite: false });
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async undo(): Promise<void> {
|
|
384
|
+
if (!this.editable) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (this.currentEditIndex < 0) {
|
|
389
|
+
// nothing to undo
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const undoneEdit = this.edits[this.currentEditIndex];
|
|
394
|
+
this.change(() => {
|
|
395
|
+
--this.currentEditIndex;
|
|
396
|
+
});
|
|
397
|
+
await this.proxy.$undo(this.resource, this.viewType, undoneEdit, this.dirty);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
async redo(): Promise<void> {
|
|
401
|
+
if (!this.editable) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (this.currentEditIndex >= this.edits.length - 1) {
|
|
406
|
+
// nothing to redo
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const redoneEdit = this.edits[this.currentEditIndex + 1];
|
|
411
|
+
this.change(() => {
|
|
412
|
+
++this.currentEditIndex;
|
|
413
|
+
});
|
|
414
|
+
await this.proxy.$redo(this.resource, this.viewType, redoneEdit, this.dirty);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
private spliceEdits(editToInsert?: number): void {
|
|
418
|
+
const start = this.currentEditIndex + 1;
|
|
419
|
+
const toRemove = this.edits.length - this.currentEditIndex;
|
|
420
|
+
|
|
421
|
+
const removedEdits = typeof editToInsert === 'number'
|
|
422
|
+
? this.edits.splice(start, toRemove, editToInsert)
|
|
423
|
+
: this.edits.splice(start, toRemove);
|
|
424
|
+
|
|
425
|
+
if (removedEdits.length) {
|
|
426
|
+
this.proxy.$disposeEdits(this.resource, this.viewType, removedEdits);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private change(makeEdit: () => void): void {
|
|
431
|
+
const wasDirty = this.dirty;
|
|
432
|
+
makeEdit();
|
|
433
|
+
|
|
434
|
+
if (this.dirty !== wasDirty) {
|
|
435
|
+
this.onDirtyChangedEmitter.fire();
|
|
436
|
+
}
|
|
437
|
+
this.onContentChangedEmitter.fire();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// copied from https://github.com/microsoft/vscode/blob/53eac52308c4611000a171cc7bf1214293473c78/src/vs/workbench/contrib/customEditor/common/customTextEditorModel.ts
|
|
443
|
+
export class CustomTextEditorModel implements CustomEditorModel {
|
|
444
|
+
private readonly toDispose = new DisposableCollection();
|
|
445
|
+
private readonly onDirtyChangedEmitter = new Emitter<void>();
|
|
446
|
+
readonly onDirtyChanged = this.onDirtyChangedEmitter.event;
|
|
447
|
+
private readonly onContentChangedEmitter = new Emitter<void>();
|
|
448
|
+
readonly onContentChanged = this.onContentChangedEmitter.event;
|
|
449
|
+
|
|
450
|
+
static async create(
|
|
451
|
+
viewType: string,
|
|
452
|
+
resource: TheiaURI,
|
|
453
|
+
editorModelService: EditorModelService,
|
|
454
|
+
fileService: FileService,
|
|
455
|
+
): Promise<CustomTextEditorModel> {
|
|
456
|
+
const model = await editorModelService.createModelReference(resource);
|
|
457
|
+
model.object.suppressOpenEditorWhenDirty = true;
|
|
458
|
+
return new CustomTextEditorModel(viewType, resource, model, fileService);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
constructor(
|
|
462
|
+
readonly viewType: string,
|
|
463
|
+
readonly editorResource: TheiaURI,
|
|
464
|
+
private readonly model: Reference<MonacoEditorModel>,
|
|
465
|
+
private readonly fileService: FileService,
|
|
466
|
+
) {
|
|
467
|
+
this.toDispose.push(
|
|
468
|
+
this.editorTextModel.onDirtyChanged(e => {
|
|
469
|
+
this.onDirtyChangedEmitter.fire();
|
|
470
|
+
})
|
|
471
|
+
);
|
|
472
|
+
this.toDispose.push(
|
|
473
|
+
this.editorTextModel.onContentChanged(e => {
|
|
474
|
+
this.onContentChangedEmitter.fire();
|
|
475
|
+
})
|
|
476
|
+
);
|
|
477
|
+
this.toDispose.push(this.onDirtyChangedEmitter);
|
|
478
|
+
this.toDispose.push(this.onContentChangedEmitter);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
dispose(): void {
|
|
482
|
+
this.toDispose.dispose();
|
|
483
|
+
this.model.dispose();
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
get resource(): URI {
|
|
487
|
+
return URI.from(this.editorResource.toComponents());
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
get dirty(): boolean {
|
|
491
|
+
return this.editorTextModel.dirty;
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
get readonly(): boolean {
|
|
495
|
+
return Boolean(this.editorTextModel.readOnly);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
get editorTextModel(): MonacoEditorModel {
|
|
499
|
+
return this.model.object;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
revert(options?: Saveable.RevertOptions): Promise<void> {
|
|
503
|
+
return this.editorTextModel.revert(options);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
save(options?: SaveOptions): Promise<void> {
|
|
507
|
+
return this.saveCustomEditor(options);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
saveCustomEditor(options?: SaveOptions): Promise<void> {
|
|
511
|
+
return this.editorTextModel.save(options);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
async saveCustomEditorAs(resource: TheiaURI, targetResource: TheiaURI, options?: SaveOptions): Promise<void> {
|
|
515
|
+
await this.saveCustomEditor(options);
|
|
516
|
+
await this.fileService.copy(resource, targetResource, { overwrite: false });
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
undo(): void {
|
|
520
|
+
this.editorTextModel.undo();
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
redo(): void {
|
|
524
|
+
this.editorTextModel.redo();
|
|
525
|
+
}
|
|
526
|
+
}
|