提交 ebb2e250 编写于 作者: J Johannes Rieken

add CellContentProvider, more injection

上级 6395ca17
......@@ -14,9 +14,15 @@ import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchCo
import { IEditorInput } from 'vs/workbench/common/editor';
import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
import { INotebookService, NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { INotebookService, NotebookService, parseCellUri } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService';
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';
// Output renderers registration
......@@ -25,7 +31,6 @@ import 'vs/workbench/contrib/notebook/browser/output/transforms/errorTransform';
import 'vs/workbench/contrib/notebook/browser/output/transforms/richTransform';
// Actions
import 'vs/workbench/contrib/notebook/browser/notebookActions';
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
......@@ -89,7 +94,48 @@ export class NotebookContribution implements IWorkbenchContribution {
}
}
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> {
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) {
if (cell.handle === data.cellHandle) {
return this._modelService.createModel(
cell.source.join('\n'),
this._modeService.createByFilepathOrFirstLine(resource, cell.source[0]),
resource
);
}
}
return null;
}
}
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(NotebookContribution, LifecyclePhase.Starting);
workbenchContributionsRegistry.registerWorkbenchContribution(CellContentProvider, LifecyclePhase.Starting);
registerSingleton(INotebookService, NotebookService);
......@@ -11,14 +11,11 @@ import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
import 'vs/css!./notebook';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { contrastBorder, editorBackground, focusBorder, foreground, textBlockQuoteBackground, textBlockQuoteBorder, textLinkActiveForeground, textLinkForeground, textPreformatForeground } from 'vs/platform/theme/common/colorRegistry';
......@@ -27,7 +24,7 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions, IEditorMemento } from 'vs/workbench/common/editor';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { INotebookService, createCellUri } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/output/outputRenderer';
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/renderers/backLayerWebView';
import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/renderers/cellRenderer';
......@@ -36,6 +33,7 @@ import { CELL_MARGIN, INotebook } from 'vs/workbench/contrib/notebook/common/not
import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
const $ = DOM.$;
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';
......@@ -70,8 +68,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IModelService private readonly modelService: IModelService,
@IModeService private readonly modeService: IModeService,
@IStorageService storageService: IStorageService,
@IWebviewService private webviewService: IWebviewService,
@INotebookService private notebookService: INotebookService,
......@@ -79,7 +75,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEnvironmentService private readonly environmentSerice: IEnvironmentService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IOpenerService private readonly openerService: IOpenerService
@ITextModelService private readonly textModelService: ITextModelService,
) {
super(NotebookEditor.ID, telemetryService, themeService, storageService);
......@@ -222,7 +218,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
.then(() => {
return input.resolve();
})
.then(model => {
.then(async model => {
if (this.model !== undefined && this.model.textModel === model.textModel && this.webview !== null) {
return;
}
......@@ -249,10 +245,12 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
this.notebook = model.getNotebook();
this.webview.updateRendererPreloads(this.notebook.renderers);
this.viewType = input.viewType;
this.viewCells = this.notebook!.cells.map(cell => {
this.viewCells = await Promise.all(this.notebook!.cells.map(async cell => {
const uri = createCellUri(input.viewType!, this.notebook!, cell);
const ref = await this.textModelService.createModelReference(uri);
const isEditing = viewState && viewState.editingCells[cell.handle];
return new CellViewModel(input.viewType!, this.notebook!.handle, cell, !!isEditing, this.modelService, this.modeService, this.openerService, this.notebookService, this.themeService);
});
return this.instantiationService.createInstance(CellViewModel, input.viewType!, this.notebook!.handle, cell, ref.object.textEditorModel, !!isEditing);
}));
const updateScrollPosition = () => {
let scrollTop = this.list?.scrollTop || 0;
......@@ -383,7 +381,9 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
const insertIndex = direction === 'above' ? index : index + 1;
let newModeCell = await this.notebookService.createNotebookCell(this.viewType!, this.notebook!.uri, insertIndex, language, type);
let newCell = new CellViewModel(this.viewType!, this.notebook!.handle, newModeCell!, false, this.modelService, this.modeService, this.openerService, this.notebookService, this.themeService);
let uri = createCellUri(this.viewType!, this.notebook!, newModeCell!);
let ref = await this.textModelService.createModelReference(uri);
let newCell = this.instantiationService.createInstance(CellViewModel, this.viewType!, this.notebook!.handle, newModeCell!, ref.object.textEditorModel, false);
this.viewCells!.splice(insertIndex, 0, newCell);
this.model!.insertCell(newCell.cell, insertIndex);
......
......@@ -12,6 +12,28 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr
import { Emitter, Event } from 'vs/base/common/event';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { INotebook, ICell, INotebookMimeTypeSelector } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { basename, extname } from 'vs/base/common/path';
export function createCellUri(viewType: string, notebook: INotebook, cell: ICell): URI {
//vscode-notebook://<viewType>/cell_<cellHandle>.ext
return URI.from({
scheme: 'vscode-notebook',
authority: viewType,
path: `/cell_${cell.handle}.${cell.cell_type === 'markdown' ? 'md' : 'py'}`,
query: notebook.uri.toString()
});
}
export function parseCellUri(resource: URI): { viewType: string, notebook: URI, cellHandle: number } | undefined {
//vscode-notebook://<viewType>/cell_<cellHandle>.ext
const match = /cell_(\d+)/.exec(basename(resource.path, extname(resource.path)));
if (!match) {
return undefined;
}
const viewType = resource.authority;
const notebook = URI.parse(resource.query);
return { viewType, notebook, cellHandle: parseInt(match[1]) };
}
function MODEL_ID(resource: URI): string {
return resource.toString();
......@@ -144,25 +166,24 @@ export class NotebookService extends Disposable implements INotebookService {
}
async resolveNotebook(viewType: string, uri: URI): Promise<INotebook | undefined> {
let provider = this._notebookProviders.get(viewType);
const provider = this._notebookProviders.get(viewType);
if (!provider) {
return undefined;
}
if (provider) {
let notebookModel = await provider.controller.resolveNotebook(viewType, uri);
if (notebookModel) {
// new notebook model created
const modelId = MODEL_ID(uri);
const modelData = new ModelData(
notebookModel,
(model) => this._onWillDispose(model),
);
this._models[modelId] = modelData;
return modelData.model;
}
const notebookModel = await provider.controller.resolveNotebook(viewType, uri);
if (!notebookModel) {
return undefined;
}
return;
// new notebook model created
const modelId = MODEL_ID(uri);
const modelData = new ModelData(
notebookModel,
(model) => this._onWillDispose(model),
);
this._models[modelId] = modelData;
return modelData.model;
}
updateNotebookActiveCell(viewType: string, resource: URI, cellHandle: number): void {
......
......@@ -3,21 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IModelService } from 'vs/editor/common/services/modelService';
import { URI } from 'vs/base/common/uri';
import { Disposable } from 'vs/base/common/lifecycle';
import { ITextModel } from 'vs/editor/common/model';
import { IModeService } from 'vs/editor/common/services/modeService';
import { Emitter } from 'vs/base/common/event';
import * as UUID from 'vs/base/common/uuid';
import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/renderers/mdRenderer';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class CellViewModel extends Disposable {
private _textModel: ITextModel | null = null;
private _mdRenderer: MarkdownRenderer | null = null;
private _html: HTMLElement | null = null;
private _dynamicHeight: number | null = null;
......@@ -51,24 +46,26 @@ export class CellViewModel extends Disposable {
get dynamicHeight(): number | null {
return this._dynamicHeight;
}
id: string;
readonly id: string = UUID.generateUuid();
constructor(
public viewType: string,
public notebookHandle: number,
public cell: ICell,
readonly viewType: string,
readonly notebookHandle: number,
readonly cell: ICell,
private _textModel: ITextModel,
private _isEditing: boolean,
private readonly modelService: IModelService,
private readonly modeService: IModeService,
private readonly openerService: IOpenerService,
private readonly notebookService: INotebookService,
private readonly themeService: IThemeService) {
@IInstantiationService private readonly _instaService: IInstantiationService,
) {
super();
this.id = UUID.generateUuid();
this._register(this._textModel.onDidChangeContent(() => {
this.cell.isDirty = true;
}));
if (this.cell.onDidChangeOutputs) {
this.cell.onDidChangeOutputs(() => {
this._register(this.cell.onDidChangeOutputs(() => {
this._onDidChangeOutputs.fire();
});
}));
}
}
hasDynamicHeight() {
......@@ -107,7 +104,7 @@ export class CellViewModel extends Disposable {
this._html = null;
}
save() {
if (this._textModel && (this.cell.isDirty || this.isEditing)) {
if (this.cell.isDirty || this.isEditing) {
let cnt = this._textModel.getLineCount();
this.cell.source = this._textModel.getLinesContent().map((str, index) => str + (index !== cnt - 1 ? '\n' : ''));
}
......@@ -115,6 +112,7 @@ export class CellViewModel extends Disposable {
getText(): string {
return this.cell.source.join('\n');
}
getHTML(): HTMLElement | null {
if (this.cellType === 'markdown') {
if (this._html) {
......@@ -126,25 +124,14 @@ export class CellViewModel extends Disposable {
}
return null;
}
getTextModel(): ITextModel {
if (!this._textModel) {
let mode = this.modeService.create(this.cellType === 'markdown' ? 'markdown' : this.cell.language);
let ext = this.cellType === 'markdown' ? 'md' : 'py';
let resource = URI.parse(`notebookcell-${Date.now()}.${ext}`);
resource = resource.with({ authority: `notebook+${this.viewType}-${this.notebookHandle}-${this.cell.handle}` });
let content = this.cell.source.join('\n');
this._textModel = this.modelService.createModel(content, mode, resource, false);
this._register(this._textModel);
this._register(this._textModel.onDidChangeContent(() => {
this.cell.isDirty = true;
}));
}
return this._textModel;
}
getMarkdownRenderer() {
if (!this._mdRenderer) {
this._mdRenderer = new MarkdownRenderer(this.viewType, this.modeService, this.openerService, this.notebookService, this.themeService);
this._mdRenderer = this._instaService.createInstance(MarkdownRenderer, this.viewType);
}
return this._mdRenderer;
}
......
......@@ -30,10 +30,10 @@ export class MarkdownRenderer extends Disposable {
constructor(
private readonly viewType: string,
private readonly _modeService: IModeService,
private readonly _openerService: IOpenerService,
private readonly _notebookService: INotebookService,
private readonly _themeService: IThemeService
@IModeService private readonly _modeService: IModeService,
@IOpenerService private readonly _openerService: IOpenerService,
@INotebookService private readonly _notebookService: INotebookService,
@IThemeService private readonly _themeService: IThemeService,
) {
super();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册