notebook.contribution.ts 8.7 KB
Newer Older
P
Peng Lyu 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

R
rebornix 已提交
6 7
import * as nls from 'vs/nls';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
8
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
P
Peng Lyu 已提交
9
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
10 11 12
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
P
Peng Lyu 已提交
13 14
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorDescriptor, Extensions as EditorExtensions, IEditorRegistry } from 'vs/workbench/browser/editor';
15
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
16 17
import { IEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, IEditorInputFactory, EditorInput } from 'vs/workbench/common/editor';
import { NotebookEditor, NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookEditor';
18
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
R
rebornix 已提交
19
import { INotebookService, NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
20 21
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService';
22 23 24 25 26 27
import { ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService';
import { ITextModel } from 'vs/editor/common/model';
import { URI } from 'vs/base/common/uri';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IDisposable } from 'vs/base/common/lifecycle';
28 29
import { assertType } from 'vs/base/common/types';
import { parse } from 'vs/base/common/marshalling';
R
rebornix 已提交
30
import { parseCellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
31 32
import { ResourceMap } from 'vs/base/common/map';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
R
rebornix 已提交
33 34 35

// Output renderers registration

R
rebornix 已提交
36 37 38
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/streamTransform';
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/errorTransform';
import 'vs/workbench/contrib/notebook/browser/view/output/transforms/richTransform';
R
rebornix 已提交
39

40
// Actions
R
rebornix 已提交
41
import 'vs/workbench/contrib/notebook/browser/contrib/notebookActions';
42
import { basename } from 'vs/base/common/resources';
P
Peng Lyu 已提交
43 44 45 46 47 48 49 50 51 52 53 54

Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
	EditorDescriptor.create(
		NotebookEditor,
		NotebookEditor.ID,
		'Notebook Editor'
	),
	[
		new SyncDescriptor(NotebookEditorInput)
	]
);

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(
	NotebookEditorInput.ID,
	class implements IEditorInputFactory {
		canSerialize(): boolean {
			return true;
		}
		serialize(input: EditorInput): string {
			assertType(input instanceof NotebookEditorInput);
			return JSON.stringify({
				resource: input.resource,
				name: input.name,
				viewType: input.viewType,
			});
		}
		deserialize(instantiationService: IInstantiationService, raw: string) {
			type Data = { resource: URI, name: string, viewType: string };
			const data = <Data>parse(raw);
			if (!data) {
				return undefined;
			}
			const { resource, name, viewType } = data;
			if (!data || !URI.isUri(resource) || typeof name !== 'string' || typeof viewType !== 'string') {
				return undefined;
			}
			// TODO@joh,peng this is disabled because the note-editor isn't fit for being
			// restorted (as it seems)
			if ('true') {
				return undefined;
			}
			return instantiationService.createInstance(NotebookEditorInput, resource, name, viewType);
		}
	}
);

89
export class NotebookContribution implements IWorkbenchContribution {
90
	private _resourceMapping = new ResourceMap<NotebookEditorInput>();
P
Peng Lyu 已提交
91 92 93

	constructor(
		@IEditorService private readonly editorService: IEditorService,
R
rebornix 已提交
94
		@INotebookService private readonly notebookService: INotebookService,
P
Peng Lyu 已提交
95
		@IInstantiationService private readonly instantiationService: IInstantiationService
96

P
Peng Lyu 已提交
97
	) {
P
Peng Lyu 已提交
98
		this.editorService.overrideOpenEditor((editor, options, group) => this.onEditorOpening(editor, options, group));
R
rebornix 已提交
99

R
rebornix 已提交
100 101 102
		this.editorService.onDidActiveEditorChange(() => {
			if (this.editorService.activeEditor && this.editorService.activeEditor! instanceof NotebookEditorInput) {
				let editorInput = this.editorService.activeEditor! as NotebookEditorInput;
J
Johannes Rieken 已提交
103
				this.notebookService.updateActiveNotebookDocument(editorInput.viewType!, editorInput.resource!);
R
rebornix 已提交
104 105
			}
		});
P
Peng Lyu 已提交
106 107
	}

108 109 110 111 112
	private onEditorOpening(originalInput: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined {
		let resource = originalInput.resource;
		if (!resource) {
			return undefined;
		}
113

114 115 116 117 118 119
		const data = parseCellUri(resource);
		if (data) {
			// cell-uri -> open (container) notebook
			const name = basename(data.notebook);
			const input = this.instantiationService.createInstance(NotebookEditorInput, data.notebook, name, data.viewType);
			this._resourceMapping.set(resource, input);
120
			return { override: this.editorService.openEditor(input, new NotebookEditorOptions({ ...options, forceReload: true, cellOptions: { resource, options } }), group) };
121 122
		}

123 124
		const notebookProviders = this.notebookService.getContributedNotebookProviders(resource);
		const viewType = !isFalsyOrEmpty(notebookProviders) ? notebookProviders[0].id : undefined;
R
rebornix 已提交
125
		if (viewType === undefined) {
R
rebornix 已提交
126
			return undefined;
R
rebornix 已提交
127 128
		}

129 130
		if (this._resourceMapping.has(resource)) {
			const input = this._resourceMapping.get(resource);
P
Peng Lyu 已提交
131

R
rebornix 已提交
132
			if (!input!.isDisposed()) {
133
				return { override: this.editorService.openEditor(input!, new NotebookEditorOptions(options || {}).with({ ignoreOverrides: true }), group) };
R
rebornix 已提交
134
			}
P
Peng Lyu 已提交
135 136
		}

137 138
		const input = this.instantiationService.createInstance(NotebookEditorInput, resource, originalInput.getName(), viewType);
		this._resourceMapping.set(resource, input);
139

R
rebornix 已提交
140
		return { override: this.editorService.openEditor(input, options, group) };
P
Peng Lyu 已提交
141 142 143
	}
}

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
class CellContentProvider implements ITextModelContentProvider {

	private readonly _registration: IDisposable;

	constructor(
		@ITextModelService textModelService: ITextModelService,
		@IModelService private readonly _modelService: IModelService,
		@IModeService private readonly _modeService: IModeService,
		@INotebookService private readonly _notebookService: INotebookService,
	) {
		this._registration = textModelService.registerTextModelContentProvider('vscode-notebook', this);
	}

	dispose(): void {
		this._registration.dispose();
	}

	async provideTextContent(resource: URI): Promise<ITextModel | null> {
J
Johannes Rieken 已提交
162 163 164 165
		const existing = this._modelService.getModel(resource);
		if (existing) {
			return existing;
		}
166 167 168 169 170 171 172 173 174
		const data = parseCellUri(resource);
		if (!data) {
			return null;
		}
		const notebook = await this._notebookService.resolveNotebook(data.viewType, data.notebook);
		if (!notebook) {
			return null;
		}
		for (let cell of notebook.cells) {
175
			if (cell.uri.toString() === resource.toString()) {
R
rebornix 已提交
176
				let bufferFactory = cell.resolveTextBufferFactory();
177
				return this._modelService.createModel(
R
rebornix 已提交
178
					bufferFactory,
R
rebornix 已提交
179
					cell.language ? this._modeService.create(cell.language) : this._modeService.createByFilepathOrFirstLine(resource, cell.source[0]),
180 181 182 183 184 185 186 187 188
					resource
				);
			}
		}

		return null;
	}
}

189 190
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(NotebookContribution, LifecyclePhase.Starting);
191
workbenchContributionsRegistry.registerWorkbenchContribution(CellContentProvider, LifecyclePhase.Starting);
R
rebornix 已提交
192 193

registerSingleton(INotebookService, NotebookService);
R
rebornix 已提交
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
configurationRegistry.registerConfiguration({
	id: 'notebook',
	order: 100,
	title: nls.localize('notebookConfigurationTitle', "Notebook"),
	type: 'object',
	properties: {
		'notebook.displayOrder': {
			markdownDescription: nls.localize('notebook.displayOrder.description', "Priority list for output mime types"),
			type: ['array'],
			items: {
				type: 'string'
			},
			default: []
		}
	}
});