diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts index 2d32f26b8ea..0fc67bc05e4 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -3,31 +3,33 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Disposable, DisposableStore, IDisposable, MutableDisposable } from 'vs/base/common/lifecycle'; +import { Schemas } from 'vs/base/common/network'; +import { HoverProviderRegistry } from 'vs/editor/common/modes'; import * as nls from 'vs/nls'; -import { Registry } from 'vs/platform/registry/common/platform'; import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions'; -import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; -import { IQuickInputButton, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; -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 } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; -import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; -import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { IDisposable, Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle'; -import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar'; -import { configureKernelIcon, selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; -import { ThemeIcon } from 'vs/platform/theme/common/themeService'; -import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; -import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; -import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ILabelService } from 'vs/platform/label/common/label'; import { ILogService } from 'vs/platform/log/common/log'; -import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { HoverProviderRegistry } from 'vs/editor/common/modes'; -import { Schemas } from 'vs/base/common/network'; -import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IQuickInputButton, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; +import { Registry } from 'vs/platform/registry/common/platform'; +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 { 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'; +import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; +import { NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IStatusbarEntryAccessor, IStatusbarService, StatusbarAlignment } from 'vs/workbench/services/statusbar/common/statusbar'; +import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; registerAction2(class extends Action2 { constructor() { @@ -42,7 +44,7 @@ registerAction2(class extends Action2 { id: MenuId.EditorTitle, when: ContextKeyExpr.and( NOTEBOOK_IS_ACTIVE_EDITOR, - NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), + ContextKeyExpr.or(NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), NOTEBOOK_VIEW_TYPE.isEqualTo('jupyter-notebook')), ContextKeyExpr.notEquals('config.notebook.globalToolbar', true) ), group: 'navigation', @@ -50,7 +52,7 @@ registerAction2(class extends Action2 { }, { id: MenuId.NotebookToolbar, when: ContextKeyExpr.and( - NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), + ContextKeyExpr.or(NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), NOTEBOOK_VIEW_TYPE.isEqualTo('jupyter-notebook')), ContextKeyExpr.equals('config.notebook.globalToolbar', true) ), group: 'status', @@ -91,6 +93,7 @@ registerAction2(class extends Action2 { const quickInputService = accessor.get(IQuickInputService); const labelService = accessor.get(ILabelService); const logService = accessor.get(ILogService); + const viewletService = accessor.get(IViewletService); const editor = context?.notebookEditor ?? getNotebookEditorFromEditorPane(editorService.activeEditorPane); if (!editor || !editor.hasModel()) { @@ -131,7 +134,7 @@ registerAction2(class extends Action2 { iconClass: ThemeIcon.asClassName(configureKernelIcon), tooltip: nls.localize('notebook.promptKernel.setDefaultTooltip', "Set as default for '{0}' notebooks", editor.textModel.viewType) }; - const picks = all.map(kernel => { + const picks: (KernelPick | IQuickPickItem)[] = all.map(kernel => { const res = { kernel, picked: kernel.id === selected?.id, @@ -149,17 +152,30 @@ registerAction2(class extends Action2 { } { return res; } }); + if (!picks.length) { + picks.push({ + id: 'install', + label: nls.localize('installKernels', "Install kernels from the marketplace"), + }); + } + const pick = await quickInputService.pick(picks, { placeHolder: selected ? nls.localize('prompt.placeholder.change', "Change kernel for '{0}'", labelService.getUriLabel(notebook.uri, { relative: true })) : nls.localize('prompt.placeholder.select', "Select kernel for '{0}'", labelService.getUriLabel(notebook.uri, { relative: true })), onDidTriggerItemButton: (context) => { - notebookKernelService.selectKernelForNotebookType(context.item.kernel, notebook.viewType); + if ('kernel' in context.item) { + notebookKernelService.selectKernelForNotebookType(context.item.kernel, notebook.viewType); + } } }); if (pick) { - newKernel = pick.kernel; + if (pick.id === 'install') { + await this._showJupyterExtension(viewletService); + } else if ('kernel' in pick) { + newKernel = pick.kernel; + } } } @@ -169,6 +185,12 @@ 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'); + } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts index 03ea666ba38..86f287d5539 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem.ts @@ -71,12 +71,6 @@ export class NotebooKernelActionViewItem extends ActionViewItem { private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void { - if (info.all.length === 0) { - // should not happen - means "bad" context keys - this._resetAction(); - return; - } - this._action.enabled = true; const selectedOrSuggested = info.selected ?? info.suggested; if (selectedOrSuggested) { @@ -88,7 +82,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem { } } else { - // many kernels + // many kernels or no kernels this._action.label = localize('select', "Select Kernel"); this._action.tooltip = ''; }