Add notebook context key for whether an extension that provides kernels is installed

This commit is contained in:
Rob Lourens 2021-07-25 18:06:04 -07:00
parent b89ec7e9ce
commit 2d9304976b
4 changed files with 46 additions and 17 deletions

View file

@ -19,7 +19,7 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSION_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { NOTEBOOK_ACTIONS_CATEGORY, SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { getNotebookEditorFromEditorPane, INotebookEditor, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { getNotebookEditorFromEditorPane, INotebookEditor, KERNEL_EXTENSIONS, NOTEBOOK_MISSING_KERNEL_EXTENSION, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget';
import { configureKernelIcon, selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
@ -44,7 +44,7 @@ registerAction2(class extends Action2 {
id: MenuId.EditorTitle,
when: ContextKeyExpr.and(
NOTEBOOK_IS_ACTIVE_EDITOR,
ContextKeyExpr.or(NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), NOTEBOOK_VIEW_TYPE.isEqualTo('jupyter-notebook')),
ContextKeyExpr.or(NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), NOTEBOOK_MISSING_KERNEL_EXTENSION),
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true)
),
group: 'navigation',
@ -52,7 +52,7 @@ registerAction2(class extends Action2 {
}, {
id: MenuId.NotebookToolbar,
when: ContextKeyExpr.and(
ContextKeyExpr.or(NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), NOTEBOOK_VIEW_TYPE.isEqualTo('jupyter-notebook')),
ContextKeyExpr.or(NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), NOTEBOOK_MISSING_KERNEL_EXTENSION),
ContextKeyExpr.equals('config.notebook.globalToolbar', true)
),
group: 'status',
@ -152,7 +152,7 @@ registerAction2(class extends Action2 {
}
{ return res; }
});
if (!picks.length) {
if (!all.length && KERNEL_EXTENSIONS.get(notebook.viewType)) {
picks.push({
id: 'install',
label: nls.localize('installKernels', "Install kernels from the marketplace"),
@ -172,7 +172,7 @@ registerAction2(class extends Action2 {
if (pick) {
if (pick.id === 'install') {
await this._showJupyterExtension(viewletService);
await this._showKernelExtension(viewletService, notebook.viewType);
} else if ('kernel' in pick) {
newKernel = pick.kernel;
}
@ -186,10 +186,13 @@ registerAction2(class extends Action2 {
return false;
}
private async _showJupyterExtension(viewletService: IViewletService) {
const viewlet = await viewletService.openViewlet(EXTENSION_VIEWLET_ID, true);
const view = viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer | undefined;
view?.search('@id:ms-toolsai.jupyter');
private async _showKernelExtension(viewletService: IViewletService, viewType: string) {
const extId = KERNEL_EXTENSIONS.get(viewType);
if (extId) {
const viewlet = await viewletService.openViewlet(EXTENSION_VIEWLET_ID, true);
const view = viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer | undefined;
view?.search(`@id:${extId}`);
}
}
});

View file

@ -73,7 +73,7 @@ export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey<boolean>('notebo
export const NOTEBOOK_KERNEL_COUNT = new RawContextKey<number>('notebookKernelCount', 0);
export const NOTEBOOK_KERNEL_SELECTED = new RawContextKey<boolean>('notebookKernelSelected', false);
export const NOTEBOOK_INTERRUPTIBLE_KERNEL = new RawContextKey<boolean>('notebookInterruptibleKernel', false);
export const NOTEBOOK_MISSING_KERNEL_EXTENSION = new RawContextKey<boolean>('notebookMissingKernelExtension', false);
export const NOTEBOOK_HAS_OUTPUTS = new RawContextKey<boolean>('notebookHasOutputs', false);
//#endregion
@ -86,6 +86,17 @@ export const QUIT_EDIT_CELL_COMMAND_ID = 'notebook.cell.quitEdit';
//#endregion
//#region Notebook extensions
// Hardcoding viewType/extension ID for now. TODO these should be replaced once we can
// look them up in the marketplace dynamically.
export const JUPYTER_EXTENSION_ID = 'ms-toolsai.jupyter';
export const KERNEL_EXTENSIONS = new Map<string, string>([
['jupyter-notebook', JUPYTER_EXTENSION_ID],
]);
//#endregion
//#region Output related types
export const enum RenderOutputType {
Mainframe,

View file

@ -5,10 +5,11 @@
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICellViewModel, INotebookEditor, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SELECTED, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { ICellViewModel, INotebookEditor, KERNEL_EXTENSIONS, NOTEBOOK_MISSING_KERNEL_EXTENSION, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SELECTED, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
export class NotebookEditorContextKeys {
@ -18,7 +19,8 @@ export class NotebookEditorContextKeys {
private readonly _someCellRunning: IContextKey<boolean>;
private readonly _hasOutputs: IContextKey<boolean>;
private readonly _useConsolidatedOutputButton: IContextKey<boolean>;
private _viewType!: IContextKey<string>;
private readonly _viewType!: IContextKey<string>;
private readonly _missingKernelExtension: IContextKey<boolean>;
private readonly _disposables = new DisposableStore();
private readonly _viewModelDisposables = new DisposableStore();
@ -29,6 +31,7 @@ export class NotebookEditorContextKeys {
private readonly _editor: INotebookEditor,
@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
@IContextKeyService contextKeyService: IContextKeyService,
@IExtensionService private readonly _extensionService: IExtensionService
) {
this._notebookKernelCount = NOTEBOOK_KERNEL_COUNT.bindTo(contextKeyService);
this._notebookKernelSelected = NOTEBOOK_KERNEL_SELECTED.bindTo(contextKeyService);
@ -37,6 +40,7 @@ export class NotebookEditorContextKeys {
this._useConsolidatedOutputButton = NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON.bindTo(contextKeyService);
this._hasOutputs = NOTEBOOK_HAS_OUTPUTS.bindTo(contextKeyService);
this._viewType = NOTEBOOK_VIEW_TYPE.bindTo(contextKeyService);
this._missingKernelExtension = NOTEBOOK_MISSING_KERNEL_EXTENSION.bindTo(contextKeyService);
this._handleDidChangeModel();
this._updateForNotebookOptions();
@ -44,9 +48,8 @@ export class NotebookEditorContextKeys {
this._disposables.add(_editor.onDidChangeModel(this._handleDidChangeModel, this));
this._disposables.add(_notebookKernelService.onDidAddKernel(this._updateKernelContext, this));
this._disposables.add(_notebookKernelService.onDidChangeSelectedNotebooks(this._updateKernelContext, this));
this._disposables.add(_editor.notebookOptions.onDidChangeOptions(() => {
this._updateForNotebookOptions();
}));
this._disposables.add(_editor.notebookOptions.onDidChangeOptions(this._updateForNotebookOptions, this));
this._disposables.add(_extensionService.onDidChangeExtensions(this._updateForInstalledExtension, this));
}
dispose(): void {
@ -118,6 +121,7 @@ export class NotebookEditorContextKeys {
}
recomputeOutputsExistence();
this._updateForInstalledExtension();
this._viewModelDisposables.add(this._editor.viewModel.onDidChangeViewCells(e => {
e.splices.reverse().forEach(splice => {
@ -131,6 +135,17 @@ export class NotebookEditorContextKeys {
this._viewType.set(this._editor.viewModel.viewType);
}
private async _updateForInstalledExtension(): Promise<void> {
if (!this._editor.hasModel()) {
return;
}
const viewType = this._editor.viewModel.viewType;
const kernelExtensionId = KERNEL_EXTENSIONS.get(viewType);
this._missingKernelExtension.set(
!!kernelExtensionId && !(await this._extensionService.getExtension(kernelExtensionId)));
}
private _updateKernelContext(): void {
if (!this._editor.hasModel()) {
this._notebookKernelCount.reset();

View file

@ -23,7 +23,7 @@ import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/commo
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSION_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { CodeCellRenderTemplate, ICellOutputViewModel, ICellViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CodeCellRenderTemplate, ICellOutputViewModel, ICellViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, JUPYTER_EXTENSION_ID, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { mimetypeIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
@ -440,7 +440,7 @@ export class CellOutputElement extends Disposable {
private async _showJupyterExtension() {
const viewlet = await this.viewletService.openViewlet(EXTENSION_VIEWLET_ID, true);
const view = viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer | undefined;
view?.search('@id:ms-toolsai.jupyter');
view?.search(`@id:${JUPYTER_EXTENSION_ID}`);
}
private _generateRendererInfo(renderId: string | undefined): string {