@theia/plugin-ext 1.46.0-next.106 → 1.46.0-next.144

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.
Files changed (115) hide show
  1. package/lib/common/plugin-api-rpc.d.ts +19 -0
  2. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  3. package/lib/common/plugin-api-rpc.js +12 -1
  4. package/lib/common/plugin-api-rpc.js.map +1 -1
  5. package/lib/main/browser/custom-editors/plugin-custom-editor-registry.d.ts +4 -8
  6. package/lib/main/browser/custom-editors/plugin-custom-editor-registry.d.ts.map +1 -1
  7. package/lib/main/browser/custom-editors/plugin-custom-editor-registry.js +18 -33
  8. package/lib/main/browser/custom-editors/plugin-custom-editor-registry.js.map +1 -1
  9. package/lib/main/browser/documents-main.d.ts +2 -1
  10. package/lib/main/browser/documents-main.d.ts.map +1 -1
  11. package/lib/main/browser/documents-main.js +2 -1
  12. package/lib/main/browser/documents-main.js.map +1 -1
  13. package/lib/main/browser/languages-main.d.ts.map +1 -1
  14. package/lib/main/browser/languages-main.js +0 -1
  15. package/lib/main/browser/languages-main.js.map +1 -1
  16. package/lib/main/browser/main-context.d.ts.map +1 -1
  17. package/lib/main/browser/main-context.js +4 -6
  18. package/lib/main/browser/main-context.js.map +1 -1
  19. package/lib/main/browser/notebooks/notebook-documents-main.d.ts +11 -5
  20. package/lib/main/browser/notebooks/notebook-documents-main.d.ts.map +1 -1
  21. package/lib/main/browser/notebooks/notebook-documents-main.js +11 -0
  22. package/lib/main/browser/notebooks/notebook-documents-main.js.map +1 -1
  23. package/lib/main/browser/notebooks/notebook-dto.js +1 -1
  24. package/lib/main/browser/notebooks/notebook-dto.js.map +1 -1
  25. package/lib/main/browser/notebooks/notebook-kernels-main.d.ts.map +1 -1
  26. package/lib/main/browser/notebooks/notebook-kernels-main.js +16 -10
  27. package/lib/main/browser/notebooks/notebook-kernels-main.js.map +1 -1
  28. package/lib/main/browser/notebooks/notebooks-main.d.ts +3 -2
  29. package/lib/main/browser/notebooks/notebooks-main.d.ts.map +1 -1
  30. package/lib/main/browser/notebooks/notebooks-main.js +21 -4
  31. package/lib/main/browser/notebooks/notebooks-main.js.map +1 -1
  32. package/lib/main/browser/notebooks/renderers/cell-output-webview.d.ts.map +1 -1
  33. package/lib/main/browser/notebooks/renderers/cell-output-webview.js +18 -1
  34. package/lib/main/browser/notebooks/renderers/cell-output-webview.js.map +1 -1
  35. package/lib/main/browser/notebooks/renderers/output-webview-internal.d.ts.map +1 -1
  36. package/lib/main/browser/notebooks/renderers/output-webview-internal.js +7 -0
  37. package/lib/main/browser/notebooks/renderers/output-webview-internal.js.map +1 -1
  38. package/lib/main/browser/plugin-contribution-handler.js +2 -2
  39. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  40. package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
  41. package/lib/main/browser/plugin-ext-frontend-module.js +3 -0
  42. package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
  43. package/lib/main/browser/terminal-main.d.ts +11 -1
  44. package/lib/main/browser/terminal-main.d.ts.map +1 -1
  45. package/lib/main/browser/terminal-main.js +37 -0
  46. package/lib/main/browser/terminal-main.js.map +1 -1
  47. package/lib/main/browser/text-editors-main.d.ts +4 -3
  48. package/lib/main/browser/text-editors-main.d.ts.map +1 -1
  49. package/lib/main/browser/text-editors-main.js +18 -6
  50. package/lib/main/browser/text-editors-main.js.map +1 -1
  51. package/lib/main/browser/view/plugin-view-registry.d.ts +6 -0
  52. package/lib/main/browser/view/plugin-view-registry.d.ts.map +1 -1
  53. package/lib/main/browser/view/plugin-view-registry.js +44 -27
  54. package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
  55. package/lib/main/browser/webview/webview-secondary-window-support.d.ts +8 -0
  56. package/lib/main/browser/webview/webview-secondary-window-support.d.ts.map +1 -0
  57. package/lib/main/browser/webview/webview-secondary-window-support.js +52 -0
  58. package/lib/main/browser/webview/webview-secondary-window-support.js.map +1 -0
  59. package/lib/plugin/notebook/notebook-document.d.ts +1 -3
  60. package/lib/plugin/notebook/notebook-document.d.ts.map +1 -1
  61. package/lib/plugin/notebook/notebook-document.js +8 -6
  62. package/lib/plugin/notebook/notebook-document.js.map +1 -1
  63. package/lib/plugin/notebook/notebook-kernels.d.ts +5 -2
  64. package/lib/plugin/notebook/notebook-kernels.d.ts.map +1 -1
  65. package/lib/plugin/notebook/notebook-kernels.js +17 -7
  66. package/lib/plugin/notebook/notebook-kernels.js.map +1 -1
  67. package/lib/plugin/notebook/notebooks.d.ts.map +1 -1
  68. package/lib/plugin/notebook/notebooks.js +11 -1
  69. package/lib/plugin/notebook/notebooks.js.map +1 -1
  70. package/lib/plugin/plugin-context.d.ts.map +1 -1
  71. package/lib/plugin/plugin-context.js +5 -1
  72. package/lib/plugin/plugin-context.js.map +1 -1
  73. package/lib/plugin/preference-registry.js +4 -4
  74. package/lib/plugin/preference-registry.js.map +1 -1
  75. package/lib/plugin/quick-open.d.ts.map +1 -1
  76. package/lib/plugin/quick-open.js +0 -1
  77. package/lib/plugin/quick-open.js.map +1 -1
  78. package/lib/plugin/terminal-ext.d.ts +3 -0
  79. package/lib/plugin/terminal-ext.d.ts.map +1 -1
  80. package/lib/plugin/terminal-ext.js +19 -0
  81. package/lib/plugin/terminal-ext.js.map +1 -1
  82. package/lib/plugin/type-converters.js +3 -2
  83. package/lib/plugin/type-converters.js.map +1 -1
  84. package/lib/plugin/webviews.d.ts +2 -0
  85. package/lib/plugin/webviews.d.ts.map +1 -1
  86. package/lib/plugin/webviews.js +7 -0
  87. package/lib/plugin/webviews.js.map +1 -1
  88. package/package.json +29 -29
  89. package/src/common/plugin-api-rpc.ts +29 -0
  90. package/src/main/browser/custom-editors/plugin-custom-editor-registry.ts +14 -36
  91. package/src/main/browser/documents-main.ts +4 -0
  92. package/src/main/browser/languages-main.ts +0 -1
  93. package/src/main/browser/main-context.ts +6 -6
  94. package/src/main/browser/notebooks/notebook-documents-main.ts +20 -5
  95. package/src/main/browser/notebooks/notebook-dto.ts +1 -1
  96. package/src/main/browser/notebooks/notebook-kernels-main.ts +15 -10
  97. package/src/main/browser/notebooks/notebooks-main.ts +19 -5
  98. package/src/main/browser/notebooks/renderers/cell-output-webview.tsx +18 -1
  99. package/src/main/browser/notebooks/renderers/output-webview-internal.ts +8 -0
  100. package/src/main/browser/plugin-contribution-handler.ts +2 -2
  101. package/src/main/browser/plugin-ext-frontend-module.ts +3 -0
  102. package/src/main/browser/terminal-main.ts +46 -0
  103. package/src/main/browser/text-editors-main.ts +25 -6
  104. package/src/main/browser/view/plugin-view-registry.ts +52 -27
  105. package/src/main/browser/webview/pre/main.js +2 -2
  106. package/src/main/browser/webview/webview-secondary-window-support.ts +47 -0
  107. package/src/plugin/notebook/notebook-document.ts +6 -8
  108. package/src/plugin/notebook/notebook-kernels.ts +22 -8
  109. package/src/plugin/notebook/notebooks.ts +13 -3
  110. package/src/plugin/plugin-context.ts +8 -2
  111. package/src/plugin/preference-registry.ts +4 -4
  112. package/src/plugin/quick-open.ts +0 -1
  113. package/src/plugin/terminal-ext.ts +20 -1
  114. package/src/plugin/type-converters.ts +5 -5
  115. package/src/plugin/webviews.ts +9 -0
@@ -301,6 +301,7 @@ export interface TerminalServiceExt {
301
301
  $handleTerminalLink(link: ProvidedTerminalLink): Promise<void>;
302
302
  getEnvironmentVariableCollection(extensionIdentifier: string): theia.GlobalEnvironmentVariableCollection;
303
303
  $setShell(shell: string): void;
304
+ $reportOutputMatch(observerId: string, groups: string[]): void;
304
305
  }
305
306
  export interface OutputChannelRegistryExt {
306
307
  createOutputChannel(name: string, pluginInfo: PluginInfo): theia.OutputChannel,
@@ -438,6 +439,20 @@ export interface TerminalServiceMain {
438
439
  * @param providerId id of the terminal link provider to be unregistered.
439
440
  */
440
441
  $unregisterTerminalLinkProvider(providerId: string): Promise<void>;
442
+
443
+ /**
444
+ * Register a new terminal observer.
445
+ * @param providerId id of the terminal link provider to be registered.
446
+ * @param nrOfLinesToMatch the number of lines to match the outputMatcherRegex against
447
+ * @param outputMatcherRegex the regex to match the output to
448
+ */
449
+ $registerTerminalObserver(id: string, nrOfLinesToMatch: number, outputMatcherRegex: string): unknown;
450
+
451
+ /**
452
+ * Unregister the terminal observer with the specified id.
453
+ * @param providerId id of the terminal observer to be unregistered.
454
+ */
455
+ $unregisterTerminalObserver(id: string): unknown;
441
456
  }
442
457
 
443
458
  export interface AutoFocus {
@@ -1548,6 +1563,16 @@ export interface WorkspaceNotebookCellEditDto {
1548
1563
  cellEdit: CellEditOperationDto;
1549
1564
  }
1550
1565
 
1566
+ export namespace WorkspaceNotebookCellEditDto {
1567
+ export function is(arg: WorkspaceNotebookCellEditDto | WorkspaceFileEditDto | WorkspaceTextEditDto): arg is WorkspaceNotebookCellEditDto {
1568
+ return !!arg
1569
+ && 'resource' in arg
1570
+ && 'cellEdit' in arg
1571
+ && arg.cellEdit !== null
1572
+ && typeof arg.cellEdit === 'object';
1573
+ }
1574
+ }
1575
+
1551
1576
  export interface WorkspaceEditDto {
1552
1577
  edits: Array<WorkspaceTextEditDto | WorkspaceFileEditDto | WorkspaceNotebookCellEditDto>;
1553
1578
  }
@@ -2449,6 +2474,10 @@ export type NotebookRawContentEventDto =
2449
2474
  readonly outputItems: NotebookOutputItemDto[];
2450
2475
  readonly append: boolean;
2451
2476
  }
2477
+ | {
2478
+ readonly kind: notebookCommon.NotebookCellsChangeType.ChangeDocumentMetadata
2479
+ readonly metadata: notebookCommon.NotebookDocumentMetadata;
2480
+ }
2452
2481
  | notebookCommon.NotebookCellsChangeLanguageEvent
2453
2482
  | notebookCommon.NotebookCellsChangeMetadataEvent
2454
2483
  | notebookCommon.NotebookCellsChangeInternalMetadataEvent
@@ -15,15 +15,11 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
18
- import { CustomEditor } from '../../../common';
18
+ import { CustomEditor, DeployedPlugin } from '../../../common';
19
19
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
20
20
  import { CustomEditorOpener } from './custom-editor-opener';
21
- import { WorkspaceCommands } from '@theia/workspace/lib/browser';
22
- import { CommandRegistry, Emitter, MenuModelRegistry } from '@theia/core';
23
- import { SelectionService } from '@theia/core/lib/common';
24
- import { UriAwareCommandHandler } from '@theia/core/lib/common/uri-command-handler';
25
- import { NavigatorContextMenu } from '@theia/navigator/lib//browser/navigator-contribution';
26
- import { ApplicationShell, DefaultOpenerService, WidgetManager, WidgetOpenerOptions } from '@theia/core/lib/browser';
21
+ import { Emitter } from '@theia/core';
22
+ import { ApplicationShell, DefaultOpenerService, OpenWithService, WidgetManager, WidgetOpenerOptions } from '@theia/core/lib/browser';
27
23
  import { CustomEditorWidget } from './custom-editor-widget';
28
24
 
29
25
  @injectable()
@@ -38,21 +34,15 @@ export class PluginCustomEditorRegistry {
38
34
  @inject(DefaultOpenerService)
39
35
  protected readonly defaultOpenerService: DefaultOpenerService;
40
36
 
41
- @inject(MenuModelRegistry)
42
- protected readonly menuModelRegistry: MenuModelRegistry;
43
-
44
- @inject(CommandRegistry)
45
- protected readonly commandRegistry: CommandRegistry;
46
-
47
- @inject(SelectionService)
48
- protected readonly selectionService: SelectionService;
49
-
50
37
  @inject(WidgetManager)
51
38
  protected readonly widgetManager: WidgetManager;
52
39
 
53
40
  @inject(ApplicationShell)
54
41
  protected readonly shell: ApplicationShell;
55
42
 
43
+ @inject(OpenWithService)
44
+ protected readonly openWithService: OpenWithService;
45
+
56
46
  @postConstruct()
57
47
  protected init(): void {
58
48
  this.widgetManager.onDidCreateWidget(({ factoryId, widget }) => {
@@ -71,7 +61,7 @@ export class PluginCustomEditorRegistry {
71
61
  });
72
62
  }
73
63
 
74
- registerCustomEditor(editor: CustomEditor): Disposable {
64
+ registerCustomEditor(editor: CustomEditor, plugin: DeployedPlugin): Disposable {
75
65
  if (this.editors.has(editor.viewType)) {
76
66
  console.warn('editor with such id already registered: ', JSON.stringify(editor));
77
67
  return Disposable.NULL;
@@ -87,26 +77,14 @@ export class PluginCustomEditorRegistry {
87
77
  this.widgetManager
88
78
  );
89
79
  toDispose.push(this.defaultOpenerService.addHandler(editorOpenHandler));
90
-
91
- const openWithCommand = WorkspaceCommands.FILE_OPEN_WITH(editorOpenHandler);
92
- toDispose.push(
93
- this.menuModelRegistry.registerMenuAction(
94
- NavigatorContextMenu.OPEN_WITH,
95
- {
96
- commandId: openWithCommand.id,
97
- label: editorOpenHandler.label
98
- }
99
- )
100
- );
101
80
  toDispose.push(
102
- this.commandRegistry.registerCommand(
103
- openWithCommand,
104
- UriAwareCommandHandler.MonoSelect(this.selectionService, {
105
- execute: uri => editorOpenHandler.open(uri),
106
- isEnabled: uri => editorOpenHandler.canHandle(uri) > 0,
107
- isVisible: uri => editorOpenHandler.canHandle(uri) > 0
108
- })
109
- )
81
+ this.openWithService.registerHandler({
82
+ id: editor.viewType,
83
+ label: editorOpenHandler.label,
84
+ providerName: plugin.metadata.model.displayName,
85
+ canHandle: uri => editorOpenHandler.canHandle(uri),
86
+ open: uri => editorOpenHandler.open(uri)
87
+ })
110
88
  );
111
89
  toDispose.push(
112
90
  editorOpenHandler.onDidOpenCustomEditor(event => this.resolveWidget(event[0], event[1]))
@@ -32,6 +32,7 @@ import { dispose } from '../../common/disposable-util';
32
32
  import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
33
33
  import * as monaco from '@theia/monaco-editor-core';
34
34
  import { TextDocumentChangeReason } from '../../plugin/types-impl';
35
+ import { NotebookDocumentsMainImpl } from './notebooks/notebook-documents-main';
35
36
 
36
37
  /*---------------------------------------------------------------------------------------------
37
38
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -90,6 +91,7 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
90
91
 
91
92
  constructor(
92
93
  editorsAndDocuments: EditorsAndDocumentsMain,
94
+ notebookDocuments: NotebookDocumentsMainImpl,
93
95
  private readonly modelService: EditorModelService,
94
96
  rpc: RPCProtocol,
95
97
  private editorManager: EditorManager,
@@ -105,6 +107,8 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
105
107
  this.toDispose.push(editorsAndDocuments.onDocumentRemove(documents => documents.forEach(this.onModelRemoved, this)));
106
108
  this.toDispose.push(modelService.onModelModeChanged(this.onModelChanged, this));
107
109
 
110
+ this.toDispose.push(notebookDocuments.onDidAddNotebookCellModel(this.onModelAdded, this));
111
+
108
112
  this.toDispose.push(modelService.onModelSaved(m => {
109
113
  this.proxy.$acceptModelSaved(m.textEditorModel.uri);
110
114
  }));
@@ -1434,7 +1434,6 @@ export function toMonacoWorkspaceEdit(data: WorkspaceEditDto | undefined): monac
1434
1434
  metadata: fileEdit.metadata
1435
1435
  };
1436
1436
  }
1437
- // TODO implement WorkspaceNotebookCellEditDto
1438
1437
  })
1439
1438
  };
1440
1439
  }
@@ -44,7 +44,6 @@ import { EditorManager } from '@theia/editor/lib/browser';
44
44
  import { EditorModelService } from './text-editor-model-service';
45
45
  import { OpenerService } from '@theia/core/lib/browser/opener-service';
46
46
  import { ApplicationShell } from '@theia/core/lib/browser/shell/application-shell';
47
- import { MonacoBulkEditService } from '@theia/monaco/lib/browser/monaco-bulk-edit-service';
48
47
  import { MainFileSystemEventService } from './main-file-system-event-service';
49
48
  import { LabelServiceMainImpl } from './label-service-main';
50
49
  import { TimelineMainImpl } from './timeline-main';
@@ -91,26 +90,27 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
91
90
 
92
91
  const editorsAndDocuments = new EditorsAndDocumentsMain(rpc, container);
93
92
 
93
+ const notebookDocumentsMain = new NotebookDocumentsMainImpl(rpc, container);
94
+ rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN, notebookDocumentsMain);
95
+
94
96
  const modelService = container.get(EditorModelService);
95
97
  const editorManager = container.get(EditorManager);
96
98
  const openerService = container.get<OpenerService>(OpenerService);
97
99
  const shell = container.get(ApplicationShell);
98
100
  const untitledResourceResolver = container.get(UntitledResourceResolver);
99
101
  const languageService = container.get(MonacoLanguages);
100
- const documentsMain = new DocumentsMainImpl(editorsAndDocuments, modelService, rpc, editorManager, openerService, shell, untitledResourceResolver, languageService);
102
+ const documentsMain = new DocumentsMainImpl(editorsAndDocuments, notebookDocumentsMain, modelService, rpc,
103
+ editorManager, openerService, shell, untitledResourceResolver, languageService);
101
104
  rpc.set(PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN, documentsMain);
102
105
 
103
106
  rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN, new NotebooksMainImpl(rpc, container, commandRegistryMain));
104
107
  rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_RENDERERS_MAIN, new NotebookRenderersMainImpl(rpc, container));
105
108
  const notebookEditorsMain = new NotebookEditorsMainImpl(rpc, container);
106
109
  rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_EDITORS_MAIN, notebookEditorsMain);
107
- const notebookDocumentsMain = new NotebookDocumentsMainImpl(rpc, container);
108
- rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_MAIN, notebookDocumentsMain);
109
110
  rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_DOCUMENTS_AND_EDITORS_MAIN, new NotebooksAndEditorsMain(rpc, container, notebookDocumentsMain, notebookEditorsMain));
110
111
  rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOK_KERNELS_MAIN, new NotebookKernelsMainImpl(rpc, container));
111
112
 
112
- const bulkEditService = container.get(MonacoBulkEditService);
113
- const editorsMain = new TextEditorsMainImpl(editorsAndDocuments, documentsMain, rpc, bulkEditService);
113
+ const editorsMain = new TextEditorsMainImpl(editorsAndDocuments, documentsMain, rpc, container);
114
114
  rpc.set(PLUGIN_RPC_CONTEXT.TEXT_EDITORS_MAIN, editorsMain);
115
115
 
116
116
  // start listening only after all clients are subscribed to events
@@ -14,24 +14,28 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { DisposableCollection } from '@theia/core';
17
+ import { DisposableCollection, Event } from '@theia/core';
18
18
  import { URI, UriComponents } from '@theia/core/lib/common/uri';
19
19
  import { interfaces } from '@theia/core/shared/inversify';
20
20
  import { NotebookModelResolverService } from '@theia/notebook/lib/browser';
21
21
  import { NotebookModel } from '@theia/notebook/lib/browser/view-model/notebook-model';
22
22
  import { NotebookCellsChangeType } from '@theia/notebook/lib/common';
23
+ import { NotebookMonacoTextModelService } from '@theia/notebook/lib/browser/service/notebook-monaco-text-model-service';
23
24
  import { MAIN_RPC_CONTEXT, NotebookCellsChangedEventDto, NotebookDataDto, NotebookDocumentsExt, NotebookDocumentsMain } from '../../../common';
24
25
  import { RPCProtocol } from '../../../common/rpc-protocol';
25
26
  import { NotebookDto } from './notebook-dto';
27
+ import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
26
28
 
27
29
  export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
28
30
 
29
- private readonly disposables = new DisposableCollection();
31
+ protected readonly disposables = new DisposableCollection();
30
32
 
31
- private readonly proxy: NotebookDocumentsExt;
32
- private readonly documentEventListenersMapping = new Map<string, DisposableCollection>();
33
+ protected readonly proxy: NotebookDocumentsExt;
34
+ protected readonly documentEventListenersMapping = new Map<string, DisposableCollection>();
33
35
 
34
- private readonly notebookModelResolverService: NotebookModelResolverService;
36
+ protected readonly notebookModelResolverService: NotebookModelResolverService;
37
+
38
+ protected notebookMonacoTextModelService: NotebookMonacoTextModelService;
35
39
 
36
40
  constructor(
37
41
  rpc: RPCProtocol,
@@ -44,6 +48,11 @@ export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
44
48
  this.disposables.push(this.notebookModelResolverService.onDidChangeDirty(model => this.proxy.$acceptDirtyStateChanged(model.uri.toComponents(), model.isDirty())));
45
49
  this.disposables.push(this.notebookModelResolverService.onDidSaveNotebook(e => this.proxy.$acceptModelSaved(e)));
46
50
 
51
+ this.notebookMonacoTextModelService = container.get(NotebookMonacoTextModelService) as NotebookMonacoTextModelService;
52
+ }
53
+
54
+ get onDidAddNotebookCellModel(): Event<MonacoEditorModel> {
55
+ return this.notebookMonacoTextModelService.onDidCreateNotebookCellModel;
47
56
  }
48
57
 
49
58
  dispose(): void {
@@ -102,6 +111,12 @@ export class NotebookDocumentsMainImpl implements NotebookDocumentsMain {
102
111
  case NotebookCellsChangeType.ChangeCellInternalMetadata:
103
112
  eventDto.rawEvents.push(e);
104
113
  break;
114
+ case NotebookCellsChangeType.ChangeDocumentMetadata:
115
+ eventDto.rawEvents.push({
116
+ kind: e.kind,
117
+ metadata: e.metadata
118
+ });
119
+ break;
105
120
  }
106
121
  }
107
122
 
@@ -94,7 +94,7 @@ export namespace NotebookDto {
94
94
  return {
95
95
  handle: cell.handle,
96
96
  uri: cell.uri.toComponents(),
97
- source: cell.text.split(eol),
97
+ source: cell.text.split(/\r?\n/g),
98
98
  eol,
99
99
  language: cell.language,
100
100
  cellKind: cell.cellKind,
@@ -27,7 +27,6 @@ import {
27
27
  CellExecution, NotebookEditorWidgetService, NotebookExecutionStateService,
28
28
  NotebookKernelChangeEvent, NotebookKernelService, NotebookService
29
29
  } from '@theia/notebook/lib/browser';
30
- import { combinedDisposable } from '@theia/monaco-editor-core/esm/vs/base/common/lifecycle';
31
30
  import { interfaces } from '@theia/core/shared/inversify';
32
31
  import { NotebookKernelSourceAction } from '@theia/notebook/lib/common';
33
32
  import { NotebookDto } from './notebook-dto';
@@ -153,6 +152,20 @@ export class NotebookKernelsMainImpl implements NotebookKernelsMain {
153
152
  }
154
153
  });
155
154
  });
155
+ this.notebookKernelService.onDidChangeSelectedKernel(e => {
156
+ if (e.newKernel) {
157
+ const newKernelHandle = Array.from(this.kernels.entries()).find(([_, [kernel]]) => kernel.id === e.newKernel)?.[0];
158
+ if (newKernelHandle !== undefined) {
159
+ this.proxy.$acceptNotebookAssociation(newKernelHandle, e.notebook.toComponents(), true);
160
+ }
161
+ } else {
162
+ const oldKernelHandle = Array.from(this.kernels.entries()).find(([_, [kernel]]) => kernel.id === e.oldKernel)?.[0];
163
+ if (oldKernelHandle !== undefined) {
164
+ this.proxy.$acceptNotebookAssociation(oldKernelHandle, e.notebook.toComponents(), false);
165
+ }
166
+
167
+ }
168
+ });
156
169
  }
157
170
 
158
171
  async $postMessage(handle: number, editorId: string | undefined, message: unknown): Promise<boolean> {
@@ -196,16 +209,8 @@ export class NotebookKernelsMainImpl implements NotebookKernelsMain {
196
209
  }
197
210
  }(handle, data, this.languageService);
198
211
 
199
- const listener = this.notebookKernelService.onDidChangeSelectedKernel(e => {
200
- if (e.oldKernel === kernel.id) {
201
- this.proxy.$acceptNotebookAssociation(handle, e.notebook.toComponents(), false);
202
- } else if (e.newKernel === kernel.id) {
203
- this.proxy.$acceptNotebookAssociation(handle, e.notebook.toComponents(), true);
204
- }
205
- });
206
-
207
212
  const registration = this.notebookKernelService.registerKernel(kernel);
208
- this.kernels.set(handle, [kernel, combinedDisposable(listener, registration)]);
213
+ this.kernels.set(handle, [kernel, registration]);
209
214
 
210
215
  }
211
216
 
@@ -14,17 +14,18 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { CancellationToken, DisposableCollection, Emitter, Event } from '@theia/core';
17
+ import { CancellationToken, DisposableCollection, Emitter, Event, URI } from '@theia/core';
18
18
  import { BinaryBuffer } from '@theia/core/lib/common/buffer';
19
- import { NotebookCellStatusBarItem, NotebookData, TransientOptions } from '@theia/notebook/lib/common';
20
- import { NotebookService } from '@theia/notebook/lib/browser';
19
+ import { CellEditType, NotebookCellModelResource, NotebookCellStatusBarItem, NotebookData, NotebookModelResource, TransientOptions } from '@theia/notebook/lib/common';
20
+ import { NotebookService, NotebookWorkspaceEdit } from '@theia/notebook/lib/browser';
21
21
  import { Disposable } from '@theia/plugin';
22
- import { CommandRegistryMain, MAIN_RPC_CONTEXT, NotebooksExt, NotebooksMain } from '../../../common';
22
+ import { CommandRegistryMain, MAIN_RPC_CONTEXT, NotebooksExt, NotebooksMain, WorkspaceEditDto, WorkspaceNotebookCellEditDto } from '../../../common';
23
23
  import { RPCProtocol } from '../../../common/rpc-protocol';
24
24
  import { NotebookDto } from './notebook-dto';
25
25
  import { UriComponents } from '@theia/core/lib/common/uri';
26
26
  import { HostedPluginSupport } from '../../../hosted/browser/hosted-plugin';
27
27
  import { NotebookModel } from '@theia/notebook/lib/browser/view-model/notebook-model';
28
+ import { NotebookCellModel } from '@theia/notebook/lib/browser/view-model/notebook-cell-model';
28
29
  import { interfaces } from '@theia/core/shared/inversify';
29
30
 
30
31
  export interface NotebookCellStatusBarItemList {
@@ -62,7 +63,9 @@ export class NotebooksMainImpl implements NotebooksMain {
62
63
  commands.registerArgumentProcessor({
63
64
  processArgument: arg => {
64
65
  if (arg instanceof NotebookModel) {
65
- return arg.uri;
66
+ return NotebookModelResource.create(arg.uri);
67
+ } else if (arg instanceof NotebookCellModel) {
68
+ return NotebookCellModelResource.create(arg.uri);
66
69
  }
67
70
  return arg;
68
71
  }
@@ -148,3 +151,14 @@ export class NotebooksMainImpl implements NotebooksMain {
148
151
  }
149
152
  }
150
153
 
154
+ export function toNotebookWorspaceEdit(dto: WorkspaceEditDto): NotebookWorkspaceEdit {
155
+ return {
156
+ edits: dto.edits.map((edit: WorkspaceNotebookCellEditDto) => ({
157
+ resource: URI.fromComponents(edit.resource),
158
+ edit: edit.cellEdit.editType === CellEditType.Replace ? {
159
+ ...edit.cellEdit,
160
+ cells: edit.cellEdit.cells.map(cell => NotebookDto.fromNotebookCellDataDto(cell))
161
+ } : edit.cellEdit
162
+ }))
163
+ };
164
+ }
@@ -99,6 +99,7 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
99
99
 
100
100
  if (this.editor) {
101
101
  this.toDispose.push(this.editor.onDidPostKernelMessage(message => {
102
+ // console.log('from extension customKernelMessage ', JSON.stringify(message));
102
103
  this.webviewWidget.sendMessage({
103
104
  type: 'customKernelMessage',
104
105
  message
@@ -106,6 +107,7 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
106
107
  }));
107
108
 
108
109
  this.toDispose.push(this.editor.onPostRendererMessage(messageObj => {
110
+ // console.log('from extension customRendererMessage ', JSON.stringify(messageObj));
109
111
  this.webviewWidget.sendMessage({
110
112
  type: 'customRendererMessage',
111
113
  ...messageObj
@@ -115,7 +117,20 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
115
117
  }
116
118
 
117
119
  this.webviewWidget = await this.widgetManager.getOrCreateWidget(WebviewWidget.FACTORY_ID, { id: this.id });
118
- this.webviewWidget.setContentOptions({ allowScripts: true });
120
+ this.webviewWidget.setContentOptions({
121
+ allowScripts: true,
122
+ // eslint-disable-next-line max-len
123
+ // list taken from https://github.com/microsoft/vscode/blob/a27099233b956dddc2536d4a0d714ab36266d897/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts#L762-L774
124
+ enableCommandUris: [
125
+ 'github-issues.authNow',
126
+ 'workbench.extensions.search',
127
+ 'workbench.action.openSettings',
128
+ '_notebook.selectKernel',
129
+ 'jupyter.viewOutput',
130
+ 'workbench.action.openLargeOutput',
131
+ 'cellOutput.enableScrolling',
132
+ ]
133
+ });
119
134
  this.webviewWidget.setHTML(await this.createWebviewContent());
120
135
 
121
136
  this.webviewWidget.onMessage((message: FromWebviewMessage) => {
@@ -188,6 +203,7 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
188
203
  this.updateOutput({ newOutputs: this.cell.outputs, start: 0, deleteCount: 0 });
189
204
  break;
190
205
  case 'customRendererMessage':
206
+ // console.log('from webview customRendererMessage ', message.rendererId, '', JSON.stringify(message.message));
191
207
  this.messagingService.getScoped(this.editor.id).postMessage(message.rendererId, message.message);
192
208
  break;
193
209
  case 'didRenderOutput':
@@ -197,6 +213,7 @@ export class CellOutputWebviewImpl implements CellOutputWebview, Disposable {
197
213
  this.editor.node.getElementsByClassName('theia-notebook-viewport')[0].children[0].scrollBy(message.deltaX, message.deltaY);
198
214
  break;
199
215
  case 'customKernelMessage':
216
+ // console.log('from webview customKernelMessage ', JSON.stringify(message.message));
200
217
  this.editor.recieveKernelMessage(message.message);
201
218
  break;
202
219
  }
@@ -573,5 +573,13 @@ export async function outputWebviewPreload(ctx: PreloadContext): Promise<void> {
573
573
  });
574
574
  window.addEventListener('wheel', handleWheel);
575
575
 
576
+ (document.head as HTMLHeadElement & { originalAppendChild: typeof document.head.appendChild }).originalAppendChild = document.head.appendChild;
577
+ (document.head as HTMLHeadElement & { originalAppendChild: typeof document.head.appendChild }).appendChild = function appendChild<T extends Node>(node: T): T {
578
+ if (node instanceof HTMLScriptElement && node.src.includes('webviewuuid')) {
579
+ node.src = node.src.replace('webviewuuid', location.hostname.split('.')[0]);
580
+ }
581
+ return this.originalAppendChild(node);
582
+ };
583
+
576
584
  theia.postMessage(<webviewCommunication.WebviewInitialized>{ type: 'initialized' });
577
585
  }
@@ -288,7 +288,7 @@ export class PluginContributionHandler {
288
288
  if (contributions.customEditors) {
289
289
  for (const customEditor of contributions.customEditors) {
290
290
  pushContribution(`customEditors.${customEditor.viewType}`,
291
- () => this.customEditorRegistry.registerCustomEditor(customEditor)
291
+ () => this.customEditorRegistry.registerCustomEditor(customEditor, plugin)
292
292
  );
293
293
  }
294
294
  }
@@ -434,7 +434,7 @@ export class PluginContributionHandler {
434
434
  if (contributions.notebooks) {
435
435
  for (const notebook of contributions.notebooks) {
436
436
  pushContribution(`notebook.${notebook.type}`,
437
- () => this.notebookTypeRegistry.registerNotebookType(notebook)
437
+ () => this.notebookTypeRegistry.registerNotebookType(notebook, plugin.metadata.model.displayName)
438
438
  );
439
439
  }
440
440
  }
@@ -90,6 +90,7 @@ import { CellOutputWebviewImpl, createCellOutputWebviewContainer } from './noteb
90
90
  import { NotebookCellModel } from '@theia/notebook/lib/browser/view-model/notebook-cell-model';
91
91
  import { NotebookModel } from '@theia/notebook/lib/browser/view-model/notebook-model';
92
92
  import { ArgumentProcessorContribution } from './command-registry-main';
93
+ import { WebviewSecondaryWindowSupport } from './webview/webview-secondary-window-support';
93
94
 
94
95
  export default new ContainerModule((bind, unbind, isBound, rebind) => {
95
96
 
@@ -187,6 +188,8 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
187
188
  bind(WebviewWidgetFactory).toDynamicValue(ctx => new WebviewWidgetFactory(ctx.container)).inSingletonScope();
188
189
  bind(WidgetFactory).toService(WebviewWidgetFactory);
189
190
  bind(WebviewContextKeys).toSelf().inSingletonScope();
191
+ bind(WebviewSecondaryWindowSupport).toSelf().inSingletonScope();
192
+ bind(FrontendApplicationContribution).toService(WebviewSecondaryWindowSupport);
190
193
  bind(FrontendApplicationContribution).toService(WebviewContextKeys);
191
194
 
192
195
  bind(CustomEditorContribution).toSelf().inSingletonScope();
@@ -30,6 +30,13 @@ import { getIconClass } from '../../plugin/terminal-ext';
30
30
  import { PluginTerminalRegistry } from './plugin-terminal-registry';
31
31
  import { CancellationToken } from '@theia/core';
32
32
  import { HostedPluginSupport } from '../../hosted/browser/hosted-plugin';
33
+ import debounce = require('@theia/core/shared/lodash.debounce');
34
+
35
+ interface TerminalObserverData {
36
+ nrOfLinesToMatch: number;
37
+ outputMatcherRegex: RegExp
38
+ disposables: DisposableCollection;
39
+ }
33
40
 
34
41
  /**
35
42
  * Plugin api service allows working with terminal emulator.
@@ -46,6 +53,7 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
46
53
  private readonly terminalLinkProviders: string[] = [];
47
54
 
48
55
  private readonly toDispose = new DisposableCollection();
56
+ private readonly observers = new Map<string, TerminalObserverData>();
49
57
 
50
58
  constructor(rpc: RPCProtocol, container: interfaces.Container) {
51
59
  this.terminals = container.get(TerminalService);
@@ -121,6 +129,8 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
121
129
  this.extProxy.$terminalOnInput(terminal.id, data);
122
130
  this.extProxy.$terminalStateChanged(terminal.id);
123
131
  }));
132
+
133
+ this.observers.forEach((observer, id) => this.observeTerminal(id, terminal, observer));
124
134
  }
125
135
 
126
136
  $write(id: string, data: string): void {
@@ -293,6 +303,42 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
293
303
  }
294
304
  }
295
305
 
306
+ $registerTerminalObserver(id: string, nrOfLinesToMatch: number, outputMatcherRegex: string): void {
307
+ const observerData = {
308
+ nrOfLinesToMatch: nrOfLinesToMatch,
309
+ outputMatcherRegex: new RegExp(outputMatcherRegex, 'm'),
310
+ disposables: new DisposableCollection()
311
+ };
312
+ this.observers.set(id, observerData);
313
+ this.terminals.all.forEach(terminal => {
314
+ this.observeTerminal(id, terminal, observerData);
315
+ });
316
+ }
317
+
318
+ protected observeTerminal(observerId: string, terminal: TerminalWidget, observerData: TerminalObserverData): void {
319
+ const doMatch = debounce(() => {
320
+ const lineCount = Math.min(observerData.nrOfLinesToMatch, terminal.buffer.length);
321
+ const lines = terminal.buffer.getLines(terminal.buffer.length - lineCount, lineCount);
322
+ const result = lines.join('\n').match(observerData.outputMatcherRegex);
323
+ if (result) {
324
+ this.extProxy.$reportOutputMatch(observerId, result.map(value => value));
325
+ }
326
+ });
327
+ observerData.disposables.push(terminal.onOutput(output => {
328
+ doMatch();
329
+ }));
330
+ }
331
+
332
+ $unregisterTerminalObserver(id: string): void {
333
+ const observer = this.observers.get(id);
334
+ if (observer) {
335
+ observer.disposables.dispose();
336
+ this.observers.delete(id);
337
+ } else {
338
+ throw new Error(`Unregistering unknown terminal observer: ${id}`);
339
+ }
340
+ }
341
+
296
342
  async provideLinks(line: string, terminal: TerminalWidget, cancellationToken?: CancellationToken | undefined): Promise<TerminalLink[]> {
297
343
  if (this.terminalLinkProviders.length < 1) {
298
344
  return [];
@@ -28,6 +28,7 @@ import {
28
28
  ThemeDecorationInstanceRenderOptions,
29
29
  DecorationOptions,
30
30
  WorkspaceEditDto,
31
+ WorkspaceNotebookCellEditDto,
31
32
  DocumentsMain,
32
33
  WorkspaceEditMetadataDto,
33
34
  } from '../../common/plugin-api-rpc';
@@ -46,7 +47,10 @@ import { ResourceEdit } from '@theia/monaco-editor-core/esm/vs/editor/browser/se
46
47
  import { IDecorationRenderOptions } from '@theia/monaco-editor-core/esm/vs/editor/common/editorCommon';
47
48
  import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
48
49
  import { ICodeEditorService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/codeEditorService';
49
- import { URI } from '@theia/core';
50
+ import { ArrayUtils, URI } from '@theia/core';
51
+ import { toNotebookWorspaceEdit } from './notebooks/notebooks-main';
52
+ import { interfaces } from '@theia/core/shared/inversify';
53
+ import { NotebookService } from '@theia/notebook/lib/browser';
50
54
 
51
55
  export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
52
56
 
@@ -55,13 +59,20 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
55
59
  private readonly editorsToDispose = new Map<string, DisposableCollection>();
56
60
  private readonly fileEndpoint = new Endpoint({ path: 'file' }).getRestUrl();
57
61
 
62
+ private readonly bulkEditService: MonacoBulkEditService;
63
+ private readonly notebookService: NotebookService;
64
+
58
65
  constructor(
59
66
  private readonly editorsAndDocuments: EditorsAndDocumentsMain,
60
67
  private readonly documents: DocumentsMain,
61
68
  rpc: RPCProtocol,
62
- private readonly bulkEditService: MonacoBulkEditService,
69
+ container: interfaces.Container
63
70
  ) {
64
71
  this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.TEXT_EDITORS_EXT);
72
+
73
+ this.bulkEditService = container.get(MonacoBulkEditService);
74
+ this.notebookService = container.get(NotebookService);
75
+
65
76
  this.toDispose.push(editorsAndDocuments);
66
77
  this.toDispose.push(editorsAndDocuments.onTextEditorAdd(editors => editors.forEach(this.onTextEditorAdd, this)));
67
78
  this.toDispose.push(editorsAndDocuments.onTextEditorRemove(editors => editors.forEach(this.onTextEditorRemove, this)));
@@ -128,11 +139,19 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
128
139
  }
129
140
 
130
141
  async $tryApplyWorkspaceEdit(dto: WorkspaceEditDto, metadata?: WorkspaceEditMetadataDto): Promise<boolean> {
131
- const workspaceEdit = toMonacoWorkspaceEdit(dto);
142
+ const [notebookEdits, monacoEdits] = ArrayUtils.partition(dto.edits, edit => WorkspaceNotebookCellEditDto.is(edit));
132
143
  try {
133
- const edits = ResourceEdit.convert(workspaceEdit);
134
- const { isApplied } = await this.bulkEditService.apply(edits, { respectAutoSaveConfig: metadata?.isRefactoring });
135
- return isApplied;
144
+ if (notebookEdits.length > 0) {
145
+ const workspaceEdit = toNotebookWorspaceEdit({ edits: notebookEdits });
146
+ return this.notebookService.applyWorkspaceEdit(workspaceEdit);
147
+ }
148
+ if (monacoEdits.length > 0) {
149
+ const workspaceEdit = toMonacoWorkspaceEdit({ edits: monacoEdits });
150
+ const edits = ResourceEdit.convert(workspaceEdit);
151
+ const { isApplied } = await this.bulkEditService.apply(edits, { respectAutoSaveConfig: metadata?.isRefactoring });
152
+ return isApplied;
153
+ }
154
+ return false;
136
155
  } catch {
137
156
  return false;
138
157
  }