Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/microsoft/vscode.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Rieken <johannes.rieken@gmail.com>2022-05-04 09:42:43 +0300
committerGitHub <noreply@github.com>2022-05-04 09:42:43 +0300
commit12c535e2bd7f261a94a5aa1267fa940055706f8c (patch)
tree63456f645a98a08889b97032c5312237f95f5d4d /src/vs/workbench/contrib/notebook
parent4ef3ed3ce8d7ab1857d41454449d32f946d3ac8c (diff)
parent9556854c8fc9199b4ffd06b4e17140e8fb78d0f4 (diff)
Merge branch 'main' into joh/cellUri
Diffstat (limited to 'src/vs/workbench/contrib/notebook')
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts82
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts2
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts23
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts18
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts135
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts (renamed from src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts)179
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/editActions.ts69
-rw-r--r--src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts9
-rw-r--r--src/vs/workbench/contrib/notebook/browser/media/notebook.css2
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts19
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts4
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookEditor.ts7
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts34
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts41
-rw-r--r--src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts11
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts11
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts13
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts2
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts13
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts3
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts23
-rw-r--r--src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts3
-rw-r--r--src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts8
-rw-r--r--src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts4
-rw-r--r--src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts26
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookCommon.ts10
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts2
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts8
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts15
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookKernelService.ts35
-rw-r--r--src/vs/workbench/contrib/notebook/common/notebookOptions.ts70
-rw-r--r--src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts38
-rw-r--r--src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts6
-rw-r--r--src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts5
-rw-r--r--src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts5
-rw-r--r--src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts5
39 files changed, 672 insertions, 286 deletions
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts
index f1834e4ee96..750af12fdf4 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts
@@ -5,16 +5,21 @@
import { CancellationToken } from 'vs/base/common/cancellation';
import { Disposable } from 'vs/base/common/lifecycle';
+import { ResourceMap } from 'vs/base/common/map';
import { URI } from 'vs/base/common/uri';
import { ILanguageService } from 'vs/editor/common/languages/language';
import { localize } from 'vs/nls';
+import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Registry } from 'vs/platform/registry/common/platform';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
-import { CHANGE_CELL_LANGUAGE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
+import { CHANGE_CELL_LANGUAGE, DETECT_CELL_LANGUAGE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookCellStatusBarService } from 'vs/workbench/contrib/notebook/common/notebookCellStatusBarService';
import { CellKind, CellStatusbarAlignment, INotebookCellStatusBarItem, INotebookCellStatusBarItemList, INotebookCellStatusBarItemProvider } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
+import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
class CellStatusBarLanguagePickerProvider implements INotebookCellStatusBarItemProvider {
@@ -50,6 +55,80 @@ class CellStatusBarLanguagePickerProvider implements INotebookCellStatusBarItemP
}
}
+class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarItemProvider {
+
+ readonly viewType = '*';
+
+ private cache = new ResourceMap<{
+ lastUpdate: number;
+ lastCellLang: string;
+ lastGuess?: string;
+ }>();
+
+ constructor(
+ @INotebookService private readonly _notebookService: INotebookService,
+ @INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
+ @ILanguageService private readonly _languageService: ILanguageService,
+ @IConfigurationService private readonly _configurationService: IConfigurationService,
+ @ILanguageDetectionService private readonly _languageDetectionService: ILanguageDetectionService,
+ @IKeybindingService private readonly _keybindingService: IKeybindingService,
+ ) { }
+
+ async provideCellStatusBarItems(uri: URI, index: number, token: CancellationToken): Promise<INotebookCellStatusBarItemList | undefined> {
+ const doc = this._notebookService.getNotebookTextModel(uri);
+ const cell = doc?.cells[index];
+ if (!cell) { return; }
+
+ const enablementConfig = this._configurationService.getValue('workbench.editor.languageDetectionHints');
+ const enabled = enablementConfig === 'always' || enablementConfig === 'notebookEditors';
+ if (!enabled) {
+ return;
+ }
+
+ const currentLanguageId = cell.cellKind === CellKind.Markup ?
+ 'markdown' :
+ (this._languageService.getLanguageIdByLanguageName(cell.language) || cell.language);
+
+ if (!this.cache.has(uri)) {
+ this.cache.set(uri, { lastCellLang: currentLanguageId, lastUpdate: 0 });
+ }
+
+ const cached = this.cache.get(uri)!;
+ if (cached.lastUpdate < Date.now() - 1000 || cached.lastCellLang !== currentLanguageId) {
+ cached.lastUpdate = Date.now();
+ cached.lastCellLang = currentLanguageId;
+
+ const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(doc);
+
+ if (kernel) {
+ const availableLangs = [];
+ availableLangs.push(...kernel.supportedLanguages, 'markdown');
+ cached.lastGuess = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs);
+ }
+ }
+
+ const items: INotebookCellStatusBarItem[] = [];
+ if (cached.lastGuess && currentLanguageId !== cached.lastGuess) {
+ const detectedName = this._languageService.getLanguageName(cached.lastGuess) || cached.lastGuess;
+ let tooltip = localize('notebook.cell.status.autoDetectLanguage', "Accept Detected Language: {0}", detectedName);
+ const keybinding = this._keybindingService.lookupKeybinding(DETECT_CELL_LANGUAGE);
+ const label = keybinding?.getLabel();
+ if (label) {
+ tooltip += ` (${label})`;
+ }
+ items.push({
+ text: '$(lightbulb-autofix)',
+ command: DETECT_CELL_LANGUAGE,
+ tooltip,
+ alignment: CellStatusbarAlignment.Right,
+ priority: -Number.MAX_SAFE_INTEGER + 1
+ });
+ }
+
+ return { items };
+ }
+}
+
class BuiltinCellStatusBarProviders extends Disposable {
constructor(
@IInstantiationService instantiationService: IInstantiationService,
@@ -58,6 +137,7 @@ class BuiltinCellStatusBarProviders extends Disposable {
const builtinProviders = [
CellStatusBarLanguagePickerProvider,
+ CellStatusBarLanguageDetectionProvider,
];
builtinProviders.forEach(p => {
this._register(notebookCellStatusBarService.registerCellStatusBarItemProvider(instantiationService.createInstance(p)));
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts
index 10037c96943..8fbc0999419 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts
@@ -27,7 +27,7 @@ import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation
import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
import { CATEGORIES } from 'vs/workbench/common/actions';
-import { IOutputService } from 'vs/workbench/contrib/output/common/output';
+import { IOutputService } from 'vs/workbench/services/output/common/output';
import { rendererLogChannelId } from 'vs/workbench/contrib/logs/common/logConstants';
import { ILogService } from 'vs/platform/log/common/log';
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 cb7ab0f8586..920669194f6 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts
@@ -28,7 +28,7 @@ import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/note
import { configureKernelIcon, selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
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 { INotebookKernel, INotebookKernelService, NotebookKernelType } 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 { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
@@ -38,7 +38,7 @@ import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeat
registerAction2(class extends Action2 {
constructor() {
super({
- id: '_notebook.selectKernel',
+ id: SELECT_KERNEL_ID,
category: NOTEBOOK_ACTIONS_CATEGORY,
title: { value: nls.localize('notebookActions.selectKernel', "Select Notebook Kernel"), original: 'Select Notebook Kernel' },
// precondition: NOTEBOOK_IS_ACTIVE_EDITOR,
@@ -182,12 +182,7 @@ registerAction2(class extends Action2 {
return res;
}
const quickPickItems: QuickPickInput<IQuickPickItem | KernelPick>[] = [];
- if (!all.length) {
- quickPickItems.push({
- id: 'install',
- label: nls.localize('installKernels', "Install kernels from the marketplace"),
- });
- } else {
+ if (all.length) {
// Always display suggested kernels on the top.
if (suggestions.length) {
quickPickItems.push({
@@ -210,6 +205,14 @@ registerAction2(class extends Action2 {
});
}
+ if (!all.find(item => item.type === NotebookKernelType.Resolved)) {
+ // there is no resolved kernel, show the install from marketplace
+ quickPickItems.push({
+ id: 'install',
+ label: nls.localize('installKernels', "Install kernels from the marketplace"),
+ });
+ }
+
const pick = await quickInputService.pick(quickPickItems, {
placeHolder: selected
? nls.localize('prompt.placeholder.change', "Change kernel for '{0}'", labelService.getUriLabel(notebook.uri, { relative: true }))
@@ -381,7 +384,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution {
tooltip: isSuggested ? nls.localize('tooltop', "{0} (suggestion)", tooltip) : tooltip,
command: SELECT_KERNEL_ID,
},
- '_notebook.selectKernel',
+ SELECT_KERNEL_ID,
StatusbarAlignment.RIGHT,
10
));
@@ -399,7 +402,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution {
command: SELECT_KERNEL_ID,
backgroundColor: { id: 'statusBarItem.prominentBackground' }
},
- '_notebook.selectKernel',
+ SELECT_KERNEL_ID,
StatusbarAlignment.RIGHT,
10
));
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts
index f1b0150286c..2f5d35ba93f 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/findModel.ts
@@ -88,7 +88,7 @@ export class FindModel extends Disposable {
};
}
- find(previous: boolean) {
+ find(option: { previous: boolean } | { index: number }) {
if (!this.findMatches.length) {
return;
}
@@ -96,14 +96,20 @@ export class FindModel extends Disposable {
// let currCell;
if (!this._findMatchesStarts) {
this.set(this._findMatches, true);
+ if ('index' in option) {
+ this._currentMatch = option.index;
+ }
} else {
// const currIndex = this._findMatchesStarts!.getIndexOf(this._currentMatch);
// currCell = this._findMatches[currIndex.index].cell;
const totalVal = this._findMatchesStarts.getTotalSum();
- if (this._currentMatch === -1) {
- this._currentMatch = previous ? totalVal - 1 : 0;
+ if ('index' in option) {
+ this._currentMatch = option.index;
+ }
+ else if (this._currentMatch === -1) {
+ this._currentMatch = option.previous ? totalVal - 1 : 0;
} else {
- const nextVal = (this._currentMatch + (previous ? -1 : 1) + totalVal) % totalVal;
+ const nextVal = (this._currentMatch + (option.previous ? -1 : 1) + totalVal) % totalVal;
this._currentMatch = nextVal;
}
}
@@ -157,8 +163,8 @@ export class FindModel extends Disposable {
}
async research() {
- this._throttledDelayer.trigger(() => {
- this._research();
+ return this._throttledDelayer.trigger(() => {
+ return this._research();
});
}
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts
new file mode 100644
index 00000000000..f1ff2386aa7
--- /dev/null
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts
@@ -0,0 +1,135 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import 'vs/css!./media/notebookFind';
+import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
+import { Schemas } from 'vs/base/common/network';
+import { isEqual } from 'vs/base/common/resources';
+import { URI } from 'vs/base/common/uri';
+import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
+import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
+import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
+import { ITextModel } from 'vs/editor/common/model';
+import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/browser/findController';
+import { localize } from 'vs/nls';
+import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
+import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
+import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
+import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
+import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget';
+import { getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
+import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
+import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
+import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
+
+registerNotebookContribution(NotebookFindWidget.id, NotebookFindWidget);
+
+registerAction2(class extends Action2 {
+ constructor() {
+ super({
+ id: 'notebook.hideFind',
+ title: { value: localize('notebookActions.hideFind', "Hide Find in Notebook"), original: 'Hide Find in Notebook' },
+ keybinding: {
+ when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED),
+ primary: KeyCode.Escape,
+ weight: KeybindingWeight.WorkbenchContrib
+ }
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise<void> {
+ const editorService = accessor.get(IEditorService);
+ const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
+
+ if (!editor) {
+ return;
+ }
+
+ const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
+ controller.hide();
+ editor.focus();
+ }
+});
+
+registerAction2(class extends Action2 {
+ constructor() {
+ super({
+ id: 'notebook.find',
+ title: { value: localize('notebookActions.findInNotebook', "Find in Notebook"), original: 'Find in Notebook' },
+ keybinding: {
+ when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, EditorContextKeys.focus.toNegated()),
+ primary: KeyCode.KeyF | KeyMod.CtrlCmd,
+ weight: KeybindingWeight.WorkbenchContrib
+ }
+ });
+ }
+
+ async run(accessor: ServicesAccessor): Promise<void> {
+ const editorService = accessor.get(IEditorService);
+ const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
+
+ if (!editor) {
+ return;
+ }
+
+ const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
+ controller.show();
+ }
+});
+
+function notebookContainsTextModel(uri: URI, textModel: ITextModel) {
+ if (textModel.uri.scheme === Schemas.vscodeNotebookCell) {
+ const cellUri = CellUri.parse(textModel.uri);
+ if (cellUri && isEqual(cellUri.notebook, uri)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+StartFindAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => {
+ const editorService = accessor.get(IEditorService);
+ const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
+
+ if (!editor) {
+ return false;
+ }
+
+ if (!editor.hasEditorFocus() && !editor.hasWebviewFocus()) {
+ const codeEditorService = accessor.get(ICodeEditorService);
+ // check if the active pane contains the active text editor
+ const textEditor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
+ if (editor.hasModel() && textEditor && textEditor.hasModel() && notebookContainsTextModel(editor.textModel.uri, textEditor.getModel())) {
+ // the active text editor is in notebook editor
+ } else {
+ return false;
+ }
+ }
+
+ const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
+ controller.show();
+ return true;
+});
+
+StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => {
+ const editorService = accessor.get(IEditorService);
+ const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
+
+ if (!editor) {
+ return false;
+ }
+
+ const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
+ if (controller) {
+ controller.replace();
+ return true;
+ }
+
+ return false;
+});
+
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts
index 9e7e660b6b0..329490a8431 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget.ts
@@ -614,7 +614,7 @@ export abstract class SimpleFindReplaceWidget extends Widget {
this._findInput.focus();
}
- public show(initialInput?: string): void {
+ public show(initialInput?: string, options?: { focus?: boolean }): void {
if (initialInput && !this._isVisible) {
this._findInput.setValue(initialInput);
}
@@ -625,7 +625,9 @@ export abstract class SimpleFindReplaceWidget extends Widget {
this._domNode.classList.add('visible', 'visible-transition');
this._domNode.setAttribute('aria-hidden', 'false');
- this.focus();
+ if (options?.focus ?? true) {
+ this.focus();
+ }
}, 0);
}
diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts
index 662b1929a2e..c027d8137d4 100644
--- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts
+++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts
@@ -3,46 +3,42 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import 'vs/css!./media/notebookFind';
+import * as DOM from 'vs/base/browser/dom';
+import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { alert as alertFn } from 'vs/base/browser/ui/aria/aria';
+import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import * as strings from 'vs/base/common/strings';
-import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
-import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
-import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
-import { INotebookEditor, CellEditState, INotebookEditorContribution, getNotebookEditorFromEditorPane } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { Range } from 'vs/editor/common/core/range';
+import { FindMatch } from 'vs/editor/common/model';
import { MATCHES_LIMIT } from 'vs/editor/contrib/find/browser/findModel';
-import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
-import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
-import { IThemeService } from 'vs/platform/theme/common/themeService';
-import * as DOM from 'vs/base/browser/dom';
-import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
-import { registerAction2, Action2, IMenuService } from 'vs/platform/actions/common/actions';
-import { localize } from 'vs/nls';
-import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
-import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
-import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { FindReplaceState } from 'vs/editor/contrib/find/browser/findState';
-import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/browser/findController';
-import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { NLS_MATCHES_LOCATION, NLS_NO_RESULTS } from 'vs/editor/contrib/find/browser/findWidget';
+import { localize } from 'vs/nls';
+import { IMenuService } from 'vs/platform/actions/common/actions';
+import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
+import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { IThemeService } from 'vs/platform/theme/common/themeService';
+import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters';
import { FindModel } from 'vs/workbench/contrib/notebook/browser/contrib/find/findModel';
-import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
-import { FindMatch, ITextModel } from 'vs/editor/common/model';
import { SimpleFindReplaceWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget';
-import { NotebookFindFilters } from 'vs/workbench/contrib/notebook/browser/contrib/find/findFilters';
-import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
-import { Schemas } from 'vs/base/common/network';
-import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-import { URI } from 'vs/base/common/uri';
-import { isEqual } from 'vs/base/common/resources';
+import { CellEditState, INotebookEditor, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
+import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
const FIND_HIDE_TRANSITION = 'find-hide-transition';
const FIND_SHOW_TRANSITION = 'find-show-transition';
let MAX_MATCHES_COUNT_WIDTH = 69;
const PROGRESS_BAR_DELAY = 200; // show progress for at least 200ms
+export interface IShowNotebookFindWidgetOptions {
+ isRegex?: boolean;
+ wholeWord?: boolean;
+ matchCase?: boolean;
+ matchIndex?: number;
+ focus?: boolean;
+}
+
export class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEditorContribution {
static id: string = 'workbench.notebook.find';
protected _findWidgetFocused: IContextKey<boolean>;
@@ -104,7 +100,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
private _onFindInputKeyDown(e: IKeyboardEvent): void {
if (e.equals(KeyCode.Enter)) {
- this._findModel.find(false);
+ this.find(false);
e.preventDefault();
return;
} else if (e.equals(KeyMod.Shift | KeyCode.Enter)) {
@@ -125,8 +121,12 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
return false;
}
+ private findIndex(index: number): void {
+ this._findModel.find({ index });
+ }
+
protected find(previous: boolean): void {
- this._findModel.find(previous);
+ this._findModel.find({ previous });
}
protected replaceOne() {
@@ -141,7 +141,7 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
this._findModel.ensureFindMatches();
if (this._findModel.currentMatch < 0) {
- this._findModel.find(false);
+ this._findModel.find({ previous: false });
}
const currentMatch = this._findModel.getCurrentMatch();
@@ -213,10 +213,18 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
protected onFindInputFocusTrackerFocus(): void { }
protected onFindInputFocusTrackerBlur(): void { }
- override show(initialInput?: string): void {
- super.show(initialInput);
+ override async show(initialInput?: string, options?: IShowNotebookFindWidgetOptions): Promise<void> {
+ super.show(initialInput, options);
this._state.change({ searchString: initialInput ?? '', isRevealed: true }, false);
- this._findInput.select();
+
+ if (typeof options?.matchIndex === 'number') {
+ if (!this._findModel.findMatches.length) {
+ await this._findModel.research();
+ }
+ this.findIndex(options.matchIndex);
+ } else {
+ this._findInput.select();
+ }
if (this._showTimeout === null) {
if (this._hideTimeout !== null) {
@@ -343,110 +351,3 @@ export class NotebookFindWidget extends SimpleFindReplaceWidget implements INote
super.dispose();
}
}
-
-registerNotebookContribution(NotebookFindWidget.id, NotebookFindWidget);
-
-registerAction2(class extends Action2 {
- constructor() {
- super({
- id: 'notebook.hideFind',
- title: { value: localize('notebookActions.hideFind', "Hide Find in Notebook"), original: 'Hide Find in Notebook' },
- keybinding: {
- when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED),
- primary: KeyCode.Escape,
- weight: KeybindingWeight.WorkbenchContrib
- }
- });
- }
-
- async run(accessor: ServicesAccessor): Promise<void> {
- const editorService = accessor.get(IEditorService);
- const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
-
- if (!editor) {
- return;
- }
-
- const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
- controller.hide();
- editor.focus();
- }
-});
-
-registerAction2(class extends Action2 {
- constructor() {
- super({
- id: 'notebook.find',
- title: { value: localize('notebookActions.findInNotebook', "Find in Notebook"), original: 'Find in Notebook' },
- keybinding: {
- when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR, EditorContextKeys.focus.toNegated()),
- primary: KeyCode.KeyF | KeyMod.CtrlCmd,
- weight: KeybindingWeight.WorkbenchContrib
- }
- });
- }
-
- async run(accessor: ServicesAccessor): Promise<void> {
- const editorService = accessor.get(IEditorService);
- const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
-
- if (!editor) {
- return;
- }
-
- const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
- controller.show();
- }
-});
-
-function notebookContainsTextModel(uri: URI, textModel: ITextModel) {
- if (textModel.uri.scheme === Schemas.vscodeNotebookCell) {
- const cellUri = CellUri.parse(textModel.uri);
- if (cellUri && isEqual(cellUri.notebook, uri)) {
- return true;
- }
- }
-
- return false;
-}
-
-StartFindAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => {
- const editorService = accessor.get(IEditorService);
- const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
-
- if (!editor) {
- return false;
- }
-
- if (!editor.hasEditorFocus() && !editor.hasWebviewFocus()) {
- const codeEditorService = accessor.get(ICodeEditorService);
- // check if the active pane contains the active text editor
- const textEditor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
- if (editor.hasModel() && textEditor && textEditor.hasModel() && notebookContainsTextModel(editor.textModel.uri, textEditor.getModel())) {
- // the active text editor is in notebook editor
- } else {
- return false;
- }
- }
-
- const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
- controller.show();
- return true;
-});
-
-StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => {
- const editorService = accessor.get(IEditorService);
- const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
-
- if (!editor) {
- return false;
- }
-
- const controller = editor.getContribution<NotebookFindWidget>(NotebookFindWidget.id);
- if (controller) {
- controller.replace();
- return true;
- }
-
- return false;
-});
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts
index d0c6379a54b..68d9d0f8dcc 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/apiActions.ts
@@ -7,7 +7,7 @@ import * as glob from 'vs/base/common/glob';
import { URI, UriComponents } from 'vs/base/common/uri';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { isDocumentExcludePattern, TransientCellMetadata, TransientDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelService, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
CommandsRegistry.registerCommand('_resolveNotebookContentProvider', (accessor): {
@@ -66,13 +66,13 @@ CommandsRegistry.registerCommand('_resolveNotebookKernels', async (accessor, arg
const uri = URI.revive(args.uri as UriComponents);
const kernels = notebookKernelService.getMatchingKernel({ uri, viewType: args.viewType });
- return kernels.all.map(provider => ({
+ return kernels.all.filter(kernel => kernel.type === NotebookKernelType.Resolved).map((provider) => ({
id: provider.id,
label: provider.label,
kind: provider.kind,
description: provider.description,
detail: provider.detail,
isPreferred: false, // todo@jrieken,@rebornix
- preloads: provider.preloadUris,
+ preloads: (provider as IResolvedNotebookKernel).preloadUris,
}));
});
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts
index 588675f6403..8d253828d2e 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts
@@ -21,12 +21,14 @@ import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/
import { changeCellToKind, runDeleteAction } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
import { CellToolbarOrder, CELL_TITLE_CELL_GROUP_ID, CELL_TITLE_OUTPUT_GROUP_ID, executeNotebookCondition, INotebookActionContext, INotebookCellActionContext, NotebookAction, NotebookCellAction, NOTEBOOK_EDITOR_WIDGET_ACTION_WEIGHT } from 'vs/workbench/contrib/notebook/browser/controller/coreActions';
import { NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_LIST_FOCUSED, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
-import { CellEditState, CHANGE_CELL_LANGUAGE, QUIT_EDIT_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
+import { CellEditState, CHANGE_CELL_LANGUAGE, DETECT_CELL_LANGUAGE, QUIT_EDIT_CELL_COMMAND_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
import { CellEditType, CellKind, ICellEditOperation, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { ILanguageDetectionService } from 'vs/workbench/services/languageDetection/common/languageDetectionWorkerService';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
+import { INotificationService } from 'vs/platform/notification/common/notification';
+import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs';
const EDIT_CELL_COMMAND_ID = 'notebook.cell.edit';
@@ -437,23 +439,7 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction<ICellR
}
private async setLanguage(context: IChangeCellContext, languageId: string) {
- if (languageId === 'markdown' && context.cell?.language !== 'markdown') {
- const idx = context.notebookEditor.getCellIndex(context.cell);
- await changeCellToKind(CellKind.Markup, { cell: context.cell, notebookEditor: context.notebookEditor, ui: true }, 'markdown', Mimes.markdown);
- const newCell = context.notebookEditor.cellAt(idx);
-
- if (newCell) {
- context.notebookEditor.focusNotebookCell(newCell, 'editor');
- }
- } else if (languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markup) {
- await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor, ui: true }, languageId);
- } else {
- const index = context.notebookEditor.textModel.cells.indexOf(context.cell.model);
- context.notebookEditor.textModel.applyEdits(
- [{ editType: CellEditType.CellLanguage, index, language: languageId }],
- true, undefined, () => undefined, undefined, true
- );
- }
+ await setCellToLanguage(languageId, context);
}
/**
@@ -478,3 +464,50 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction<ICellR
return fakeResource;
}
});
+
+registerAction2(class DetectCellLanguageAction extends NotebookCellAction {
+ constructor() {
+ super({
+ id: DETECT_CELL_LANGUAGE,
+ title: localize('detectLanguage', 'Accept Detected Language for Cell'),
+ f1: true,
+ precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_EDITABLE),
+ keybinding: { primary: KeyCode.KeyD | KeyMod.Alt | KeyMod.Shift, weight: KeybindingWeight.WorkbenchContrib }
+ });
+ }
+
+ async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
+ const languageDetectionService = accessor.get(ILanguageDetectionService);
+ const notificationService = accessor.get(INotificationService);
+ const kernelService = accessor.get(INotebookKernelService);
+ const kernel = kernelService.getSelectedOrSuggestedKernel(context.notebookEditor.textModel);
+ const providerLanguages = [...kernel?.supportedLanguages ?? []];
+ providerLanguages.push('markdown');
+ const detection = await languageDetectionService.detectLanguage(context.cell.uri, providerLanguages);
+ if (detection) {
+ setCellToLanguage(detection, context);
+ } else {
+ notificationService.warn(localize('noDetection', "Unable to detect cell language"));
+ }
+ }
+});
+
+async function setCellToLanguage(languageId: string, context: IChangeCellContext) {
+ if (languageId === 'markdown' && context.cell?.language !== 'markdown') {
+ const idx = context.notebookEditor.getCellIndex(context.cell);
+ await changeCellToKind(CellKind.Markup, { cell: context.cell, notebookEditor: context.notebookEditor, ui: true }, 'markdown', Mimes.markdown);
+ const newCell = context.notebookEditor.cellAt(idx);
+
+ if (newCell) {
+ context.notebookEditor.focusNotebookCell(newCell, 'editor');
+ }
+ } else if (languageId !== 'markdown' && context.cell?.cellKind === CellKind.Markup) {
+ await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor, ui: true }, languageId);
+ } else {
+ const index = context.notebookEditor.textModel.cells.indexOf(context.cell.model);
+ context.notebookEditor.textModel.applyEdits(
+ [{ editType: CellEditType.CellLanguage, index, language: languageId }],
+ true, undefined, () => undefined, undefined, true
+ );
+ }
+}
diff --git a/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts
index 27ce6ca5434..4f6a3e489c5 100644
--- a/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts
+++ b/src/vs/workbench/contrib/notebook/browser/controller/layoutActions.ts
@@ -173,15 +173,6 @@ registerAction2(class ToggleBreadcrumbFromEditorTitle extends Action2 {
}
});
-MenuRegistry.appendMenuItem(MenuId.NotebookToolbar, {
- command: {
- id: 'breadcrumbs.toggle',
- title: { value: localize('cmd.toggle', "Toggle Breadcrumbs"), original: 'Toggle Breadcrumbs' },
- },
- group: 'notebookLayout',
- order: 2
-});
-
registerAction2(class SaveMimeTypeDisplayOrder extends Action2 {
constructor() {
super({
diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css
index a660892ff1f..e4220b57b14 100644
--- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css
+++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css
@@ -429,7 +429,7 @@
outline: none !important;
}
-.monaco-workbench .notebookOverlay.notebook-editor-editable > .cell-list-container > .monaco-list > .monaco-scrollable-element > .scrollbar.visible {
+.monaco-workbench .notebookOverlay.notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .scrollbar.visible {
z-index: var(--z-index-notebook-scrollbar);
cursor: default;
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
index 2b793c40961..466fd1bf565 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts
@@ -70,7 +70,7 @@ import 'vs/workbench/contrib/notebook/browser/controller/foldingController';
// Editor Contribution
import 'vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard';
-import 'vs/workbench/contrib/notebook/browser/contrib/find/findController';
+import 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFind';
import 'vs/workbench/contrib/notebook/browser/contrib/format/formatting';
import 'vs/workbench/contrib/notebook/browser/contrib/gettingStarted/notebookGettingStarted';
import 'vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions';
@@ -892,5 +892,22 @@ configurationRegistry.registerConfiguration({
enum: ['always', 'never', 'fromEditor'],
default: 'fromEditor'
},
+ [NotebookSetting.outputLineHeight]: {
+ markdownDescription: nls.localize('notebook.outputLineHeight', "Line height of the output text for notebook cells.\n - Values between 0 and 8 will be used as a multiplier with the font size.\n - Values greater than or equal to 8 will be used as effective values."),
+ type: 'number',
+ default: 22,
+ tags: ['notebookLayout']
+ },
+ [NotebookSetting.outputFontSize]: {
+ markdownDescription: nls.localize('notebook.outputFontSize', "Font size for the output text for notebook cells. When set to 0 `#editor.fontSize#` is used."),
+ type: 'number',
+ default: 0,
+ tags: ['notebookLayout']
+ },
+ [NotebookSetting.outputFontFamily]: {
+ markdownDescription: nls.localize('notebook.outputFontFamily', "The font family for the output text for notebook cells. When set to empty, the `#editor.fontFamily#` is used."),
+ type: 'string',
+ tags: ['notebookLayout']
+ },
}
});
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
index 7153bcfe26c..77a50b8c655 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts
@@ -11,7 +11,7 @@ import { IEditorContributionDescription } from 'vs/editor/browser/editorExtensio
import * as editorCommon from 'vs/editor/common/editorCommon';
import { FontInfo } from 'vs/editor/common/config/fontInfo';
import { IPosition } from 'vs/editor/common/core/position';
-import { Range } from 'vs/editor/common/core/range';
+import { IRange, Range } from 'vs/editor/common/core/range';
import { FindMatch, IModelDeltaDecoration, IReadonlyTextBuffer, ITextModel, TrackedRangeStickiness } from 'vs/editor/common/model';
import { MenuId } from 'vs/platform/actions/common/actions';
import { ITextEditorOptions, ITextResourceEditorInput } from 'vs/platform/editor/common/editor';
@@ -31,6 +31,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
//#region Shared commands
export const EXPAND_CELL_INPUT_COMMAND_ID = 'notebook.cell.expandCellInput';
export const EXECUTE_CELL_COMMAND_ID = 'notebook.cell.execute';
+export const DETECT_CELL_LANGUAGE = 'notebook.cell.detectLanguage';
export const CHANGE_CELL_LANGUAGE = 'notebook.cell.changeLanguage';
export const QUIT_EDIT_CELL_COMMAND_ID = 'notebook.cell.quitEdit';
export const EXPAND_CELL_OUTPUT_COMMAND_ID = 'notebook.cell.expandCellOutput';
@@ -280,6 +281,7 @@ export interface INotebookEditorOptions extends ITextEditorOptions {
readonly cellSelections?: ICellRange[];
readonly isReadOnly?: boolean;
readonly viewState?: INotebookEditorViewState;
+ readonly indexedCellOptions?: { index: number; selection?: IRange };
}
export type INotebookEditorContributionCtor = IConstructorSignature<INotebookEditorContribution, [INotebookEditor]>;
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
index 623686523fa..58edfc13e6b 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts
@@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction, toAction } from 'vs/base/common/actions';
import { CancellationToken } from 'vs/base/common/cancellation';
-import { IErrorWithActions } from 'vs/base/common/errorMessage';
+import { createErrorWithActions } from 'vs/base/common/errorMessage';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import { extname, isEqual } from 'vs/base/common/resources';
@@ -289,8 +289,7 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
}
}
} catch (e) {
- const error: Error & IErrorWithActions = e instanceof Error ? e : new Error(e.message);
- error.actions = [
+ const error = createErrorWithActions(e instanceof Error ? e : new Error(e.message), [
toAction({
id: 'workbench.notebook.action.openInTextEditor', label: localize('notebookOpenInTextEditor', "Open in Text Editor"), run: async () => {
const activeEditorPane = this._editorService.activeEditorPane;
@@ -317,7 +316,7 @@ export class NotebookEditor extends EditorPane implements IEditorPaneWithSelecti
return;
}
})
- ];
+ ]);
throw error;
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
index aa1bcc7853f..20ea78a5058 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts
@@ -101,7 +101,6 @@ export class BaseCellEditorOptions extends Disposable implements IBaseCellEditor
},
renderLineHighlightOnlyWhenFocus: true,
overviewRulerLanes: 0,
- selectOnLineNumbers: false,
lineNumbers: 'off',
lineDecorationsWidth: 0,
folding: true,
@@ -397,7 +396,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._updateForNotebookConfiguration();
}
- if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.markupFontSize || e.insertToolbarAlignment) {
+ if (e.fontFamily) {
+ this._generateFontInfo();
+ }
+
+ if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.markupFontSize || e.fontFamily || e.outputFontFamily || e.insertToolbarAlignment || e.outputLineHeight) {
this._styleElement?.remove();
this._createLayoutStyles();
this._webview?.updateOptions({
@@ -1216,8 +1219,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this.viewModel.updateOptions({ isReadOnly: this._readOnly });
// reveal cell if editor options tell to do so
- if (options?.cellOptions) {
- const cellOptions = options.cellOptions;
+ const cellOptions = options?.cellOptions ?? this._parseIndexedCellOptions(options);
+ if (cellOptions) {
const cell = this.viewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString());
if (cell) {
this.focusElement(cell);
@@ -1270,6 +1273,24 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._onDidChangeOptions.fire();
}
+ private _parseIndexedCellOptions(options: INotebookEditorOptions | undefined) {
+ if (options?.indexedCellOptions) {
+ // convert index based selections
+ const cell = this.cellAt(options.indexedCellOptions.index);
+ if (cell) {
+ return {
+ resource: cell.uri,
+ options: {
+ selection: options.indexedCellOptions.selection,
+ preserveFocus: false
+ }
+ };
+ }
+ }
+
+ return undefined;
+ }
+
private _detachModel() {
this._localStore.clear();
dispose(this._localCellStateListeners);
@@ -1802,6 +1823,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
const focusRange = this.viewModel.getFocus();
const element = this.viewModel.cellAt(focusRange.start);
+ // The notebook editor doesn't have focus yet
+ if (!this.hasEditorFocus()) {
+ this.focusContainer();
+ }
+
if (element && element.focusMode === CellFocusMode.Editor) {
element.updateEditState(CellEditState.Editing, 'editorWidget.focus');
element.focusMode = CellFocusMode.Editor;
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts
index 000c7b3b72c..2d4fe4cebe0 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts
@@ -4,6 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
+import { CancellationTokenSource } from 'vs/base/common/cancellation';
+import { IDisposable } from 'vs/base/common/lifecycle';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
@@ -12,10 +14,11 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode
import { CellKind, INotebookTextModel, NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
-import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
-export class NotebookExecutionService implements INotebookExecutionService {
+export class NotebookExecutionService implements INotebookExecutionService, IDisposable {
declare _serviceBrand: undefined;
+ private _activeProxyKernelExecutionToken: CancellationTokenSource | undefined;
constructor(
@ICommandService private readonly _commandService: ICommandService,
@@ -45,6 +48,29 @@ export class NotebookExecutionService implements INotebookExecutionService {
return;
}
+ if (kernel.type === NotebookKernelType.Proxy) {
+ this._activeProxyKernelExecutionToken?.dispose(true);
+ const tokenSource = this._activeProxyKernelExecutionToken = new CancellationTokenSource();
+ const resolved = await kernel.resolveKernel(notebook.uri);
+ const kernels = this._notebookKernelService.getMatchingKernel(notebook);
+ const newlyMatchedKernel = kernels.all.find(k => k.id === resolved);
+
+ if (!newlyMatchedKernel) {
+ return;
+ }
+
+ kernel = newlyMatchedKernel;
+ if (tokenSource.token.isCancellationRequested) {
+ // execution was cancelled but we still need to update the active kernel
+ this._notebookKernelService.selectKernelForNotebook(kernel, notebook);
+ return;
+ }
+ }
+
+ if (kernel.type === NotebookKernelType.Proxy) {
+ return;
+ }
+
const executeCells: NotebookCellTextModel[] = [];
for (const cell of cellsArr) {
const cellExe = this._notebookExecutionStateService.getCellExecution(cell.uri);
@@ -75,11 +101,20 @@ export class NotebookExecutionService implements INotebookExecutionService {
this._logService.debug(`NotebookExecutionService#cancelNotebookCellHandles ${JSON.stringify(cellsArr)}`);
const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(notebook);
if (kernel) {
- await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr);
+ if (kernel.type === NotebookKernelType.Proxy) {
+ this._activeProxyKernelExecutionToken?.dispose(true);
+ } else {
+ await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr);
+ }
+
}
}
async cancelNotebookCells(notebook: INotebookTextModel, cells: Iterable<NotebookCellTextModel>): Promise<void> {
this.cancelNotebookCellHandles(notebook, Array.from(cells, cell => cell.handle));
}
+
+ dispose() {
+ this._activeProxyKernelExecutionToken?.dispose(true);
+ }
}
diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts
index 1f2e2e72032..3a14f27d0ff 100644
--- a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts
+++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts
@@ -196,7 +196,16 @@ export class NotebookKernelService extends Disposable implements INotebookKernel
getSelectedOrSuggestedKernel(notebook: INotebookTextModel): INotebookKernel | undefined {
const info = this.getMatchingKernel(notebook);
- return info.selected ?? (info.all.length === 1 ? info.all[0] : undefined);
+ if (info.selected) {
+ return info.selected;
+ }
+
+ const preferred = info.all.filter(kernel => this._kernels.get(kernel.id)?.notebookPriorities.get(notebook.uri) === 2 /* vscode.NotebookControllerPriority.Preferred */);
+ if (preferred.length === 1) {
+ return preferred[0];
+ }
+
+ return info.all.length === 1 ? info.all[0] : undefined;
}
// default kernel for notebookType
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts
index e1e2a982be5..364939e3456 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellContextKeys.ts
@@ -5,15 +5,15 @@
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
-import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
+import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
+import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel';
import { NotebookCellExecutionState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookCellExecutionStateContext, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_EDITOR_FOCUSED, NOTEBOOK_CELL_EXECUTING, NOTEBOOK_CELL_EXECUTION_STATE, NOTEBOOK_CELL_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS, NOTEBOOK_CELL_INPUT_COLLAPSED, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_OUTPUT_COLLAPSED, NOTEBOOK_CELL_RESOURCE, NOTEBOOK_CELL_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
-import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
-import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
-import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export class CellContextKeyPart extends CellPart {
private cellContextKeyManager: CellContextKeyManager;
@@ -44,6 +44,7 @@ export class CellContextKeyManager extends Disposable {
private cellContentCollapsed!: IContextKey<boolean>;
private cellOutputCollapsed!: IContextKey<boolean>;
private cellLineNumbers!: IContextKey<'on' | 'off' | 'inherit'>;
+ private cellResource!: IContextKey<string>;
private markdownEditMode!: IContextKey<boolean>;
@@ -69,6 +70,7 @@ export class CellContextKeyManager extends Disposable {
this.cellContentCollapsed = NOTEBOOK_CELL_INPUT_COLLAPSED.bindTo(this._contextKeyService);
this.cellOutputCollapsed = NOTEBOOK_CELL_OUTPUT_COLLAPSED.bindTo(this._contextKeyService);
this.cellLineNumbers = NOTEBOOK_CELL_LINE_NUMBERS.bindTo(this._contextKeyService);
+ this.cellResource = NOTEBOOK_CELL_RESOURCE.bindTo(this._contextKeyService);
if (element) {
this.updateForElement(element);
@@ -112,6 +114,7 @@ export class CellContextKeyManager extends Disposable {
this.updateForOutputs();
this.cellLineNumbers.set(this.element!.lineNumbers);
+ this.cellResource.set(this.element!.uri.toString());
});
}
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts
index 8c0b8a99748..86e0a69074a 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDnd.ts
@@ -78,7 +78,7 @@ export class CellDragAndDropController extends Disposable {
this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_START, this.onGlobalDragStart.bind(this), true));
this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_END, this.onGlobalDragEnd.bind(this), true));
- const addCellDragListener = (eventType: string, handler: (e: CellDragEvent) => void) => {
+ const addCellDragListener = (eventType: string, handler: (e: CellDragEvent) => void, useCapture = false) => {
this._register(DOM.addDisposableListener(
notebookEditor.getDomNode(),
eventType,
@@ -87,14 +87,21 @@ export class CellDragAndDropController extends Disposable {
if (cellDragEvent) {
handler(cellDragEvent);
}
- }));
+ }, useCapture));
};
addCellDragListener(DOM.EventType.DRAG_OVER, event => {
+ if (!this.currentDraggedCell) {
+ return;
+ }
event.browserEvent.preventDefault();
+ event.browserEvent.stopImmediatePropagation();
this.onCellDragover(event);
- });
+ }, true);
addCellDragListener(DOM.EventType.DROP, event => {
+ if (!this.currentDraggedCell) {
+ return;
+ }
event.browserEvent.preventDefault();
this.onCellDrop(event);
});
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts
index 46388b581b4..43c5852753e 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellDragRenderer.ts
@@ -65,7 +65,7 @@ class EditorTextRenderer {
let result = '';
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
- const lineTokens = model.getLineTokens(lineNumber);
+ const lineTokens = model.tokenization.getLineTokens(lineNumber);
const lineContent = lineTokens.getLineContent();
const startOffset = (lineNumber === startLineNumber ? startColumn - 1 : 0);
const endOffset = (lineNumber === endLineNumber ? endColumn - 1 : lineContent.length);
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts
index d4745c02a43..469e7cbef3d 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts
@@ -9,6 +9,7 @@ import { ICellViewModel, INotebookEditorDelegate } from 'vs/workbench/contrib/no
import { CellViewModelStateChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookViewEvents';
import { CellPart } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
import { NotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
+import { NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
export class CellExecutionPart extends CellPart {
private kernelDisposables = this._register(new DisposableStore());
@@ -41,7 +42,7 @@ export class CellExecutionPart extends CellPart {
}
private updateExecutionOrder(internalMetadata: NotebookCellInternalMetadata): void {
- if (this._notebookEditor.activeKernel?.implementsExecutionOrder) {
+ if (this._notebookEditor.activeKernel?.type === NotebookKernelType.Resolved && this._notebookEditor.activeKernel?.implementsExecutionOrder) {
const executionOrderLabel = typeof internalMetadata.executionOrder === 'number' ?
`[${internalMetadata.executionOrder}]` :
'[ ]';
@@ -62,7 +63,8 @@ export class CellExecutionPart extends CellPart {
DOM.hide(this._executionOrderLabel);
} else {
DOM.show(this._executionOrderLabel);
- this._executionOrderLabel.style.top = `${element.layoutInfo.editorHeight}px`;
+ const top = element.layoutInfo.editorHeight - 22 + element.layoutInfo.statusBarHeight;
+ this._executionOrderLabel.style.top = `${top}px`;
}
}
}
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts
index 3f2df96e305..6cd5d2c242d 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/codeCell.ts
@@ -316,8 +316,17 @@ export class CodeCell extends Disposable {
}));
}
+ private shouldUpdateDOMFocus() {
+ // The DOM focus needs to be adjusted:
+ // when a cell editor should be focused
+ // the document active element is inside the notebook editor or the document body (cell editor being disposed previously)
+ return this.notebookEditor.getActiveCell() === this.viewCell
+ && this.viewCell.focusMode === CellFocusMode.Editor
+ && (this.notebookEditor.hasEditorFocus() || document.activeElement === document.body);
+ }
+
private updateEditorForFocusModeChange() {
- if (this.viewCell.focusMode === CellFocusMode.Editor && this.notebookEditor.getActiveCell() === this.viewCell) {
+ if (this.shouldUpdateDOMFocus()) {
this.templateData.editor?.focus();
}
@@ -479,7 +488,7 @@ export class CodeCell extends Disposable {
this._isDisposed = true;
// move focus back to the cell list otherwise the focus goes to body
- if (this.notebookEditor.getActiveCell() === this.viewCell && this.viewCell.focusMode === CellFocusMode.Editor) {
+ if (this.shouldUpdateDOMFocus()) {
this.notebookEditor.focusContainer();
}
diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts
index bf119feb15c..82e710ed494 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts
@@ -221,7 +221,7 @@ export class StatefulMarkdownCell extends Disposable {
override dispose() {
// move focus back to the cell list otherwise the focus goes to body
- if (this.notebookEditor.getActiveCell() === this.viewCell && this.viewCell.focusMode === CellFocusMode.Editor) {
+ if (this.notebookEditor.getActiveCell() === this.viewCell && this.viewCell.focusMode === CellFocusMode.Editor && (this.notebookEditor.hasEditorFocus() || document.activeElement === document.body)) {
this.notebookEditor.focusContainer();
}
@@ -327,6 +327,7 @@ export class StatefulMarkdownCell extends Disposable {
width: width,
height: editorHeight
},
+ enableDropIntoEditor: true,
// overflowWidgetsDomNode: this.notebookEditor.getOverflowContainerDomNode()
}, {
contributions: this.notebookEditor.creationOptions.cellEditorContributions
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
index 7bda661ed4e..a7145c9ffc9 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts
@@ -37,10 +37,11 @@ import { preloadsScriptStr, RendererMetadata } from 'vs/workbench/contrib/notebo
import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping';
import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel';
import { CellUri, INotebookRendererInfo, NotebookSetting, RendererMessagingSpec } from 'vs/workbench/contrib/notebook/common/notebookCommon';
-import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernel, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { IScopedRendererMessaging } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IWebviewElement, IWebviewService, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview';
+import { WebviewWindowDragMonitor } from 'vs/workbench/contrib/webview/browser/webviewWindowDragMonitor';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { FromWebviewMessage, IAckOutputHeight, IClickedDataUrlMessage, ICodeBlockHighlightRequest, IContentWidgetTopRequest, IControllerPreload, ICreationContent, ICreationRequestMessage, IFindMatch, IMarkupCellInitialization, ToWebviewMessage } from './webviewMessages';
@@ -88,8 +89,11 @@ interface BacklayerWebviewOptions {
readonly runGutter: number;
readonly dragAndDropEnabled: boolean;
readonly fontSize: number;
+ readonly outputFontSize: number;
readonly fontFamily: string;
+ readonly outputFontFamily: string;
readonly markupFontSize: number;
+ readonly outputLineHeight: number;
}
export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
@@ -204,8 +208,9 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
'notebook-output-node-left-padding': `${this.options.outputNodeLeftPadding}px`,
'notebook-markdown-min-height': `${this.options.previewNodePadding * 2}px`,
'notebook-markup-font-size': typeof this.options.markupFontSize === 'number' && this.options.markupFontSize > 0 ? `${this.options.markupFontSize}px` : `calc(${this.options.fontSize}px * 1.2)`,
- 'notebook-cell-output-font-size': `${this.options.fontSize}px`,
- 'notebook-cell-output-font-family': this.options.fontFamily,
+ 'notebook-cell-output-font-size': `${this.options.outputFontSize || this.options.fontSize}px`,
+ 'notebook-cell-output-line-height': `${this.options.outputLineHeight}px`,
+ 'notebook-cell-output-font-family': this.options.outputFontFamily || this.options.fontFamily,
'notebook-cell-markup-empty-content': nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit."),
'notebook-cell-renderer-not-found-error': nls.localize({
key: 'notebook.error.rendererNotFound',
@@ -523,6 +528,8 @@ var requirejs = (function() {
this.webview.mountTo(this.element);
this._register(this.webview);
+ this._register(new WebviewWindowDragMonitor(() => this.webview));
+
this._register(this.webview.onDidClickLink(link => {
if (this._disposed) {
return;
@@ -897,7 +904,7 @@ var requirejs = (function() {
}
this._preloadsCache.clear();
- if (this._currentKernel) {
+ if (this._currentKernel?.type === NotebookKernelType.Resolved) {
this._updatePreloadsFromKernel(this._currentKernel);
}
@@ -1394,14 +1401,14 @@ var requirejs = (function() {
const previousKernel = this._currentKernel;
this._currentKernel = kernel;
- if (previousKernel && previousKernel.preloadUris.length > 0) {
+ if (previousKernel?.type === NotebookKernelType.Resolved && previousKernel.preloadUris.length > 0) {
this.webview?.reload(); // preloads will be restored after reload
- } else if (kernel) {
+ } else if (kernel?.type === NotebookKernelType.Resolved) {
this._updatePreloadsFromKernel(kernel);
}
}
- private _updatePreloadsFromKernel(kernel: INotebookKernel) {
+ private _updatePreloadsFromKernel(kernel: IResolvedNotebookKernel) {
const resources: IControllerPreload[] = [];
for (const preload of kernel.preloadUris) {
const uri = this.environmentService.isExtensionDevelopment && (preload.scheme === 'http' || preload.scheme === 'https')
@@ -1427,7 +1434,7 @@ var requirejs = (function() {
const mixedResourceRoots = [
...(this.localResourceRootsCache || []),
- ...(this._currentKernel ? [this._currentKernel.localResourceRoot] : []),
+ ...(this._currentKernel?.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []),
];
this.webview.localResourcesRoot = mixedResourceRoots;
diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts
index 02beef093cf..2bcf55c8531 100644
--- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts
+++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts
@@ -168,7 +168,7 @@ export class MarkupCellRenderer extends AbstractCellRenderer implements IListRen
templateDisposables.add(scopedInstaService.createInstance(BetweenCellToolbar, this.notebookEditor, titleToolbarContainer, bottomCellContainer)),
templateDisposables.add(scopedInstaService.createInstance(CellEditorStatusBar, this.notebookEditor, container, editorPart, undefined)),
templateDisposables.add(new CellFocusIndicator(this.notebookEditor, titleToolbar, focusIndicatorTop, focusIndicatorLeft, focusIndicatorRight, focusIndicatorBottom)),
- templateDisposables.add(scopedInstaService.createInstance(FoldedCellHint, this.notebookEditor, DOM.append(container, $('.notebook-folded-hint')))),
+ templateDisposables.add(new FoldedCellHint(this.notebookEditor, DOM.append(container, $('.notebook-folded-hint')))),
templateDisposables.add(new CellDecorations(rootContainer, decorationContainer)),
templateDisposables.add(scopedInstaService.createInstance(CellComments, this.notebookEditor, cellCommentPartContainer)),
templateDisposables.add(new CollapsedCellInput(this.notebookEditor, cellInputCollapsedContainer)),
@@ -274,6 +274,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
width: 0,
height: 0
},
+ enableDropIntoEditor: true,
}, {
contributions: this.notebookEditor.creationOptions.cellEditorContributions
});
diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts
index 8b7c306af28..11b51e17e2f 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel.ts
@@ -156,8 +156,6 @@ export abstract class BaseCellViewModel extends Disposable {
this._onDidChangeState.fire({ outputCollapsedChanged: true });
}
- private _textEditorRestore: any;
-
constructor(
readonly viewType: string,
readonly model: NotebookCellTextModel,
@@ -236,9 +234,7 @@ export abstract class BaseCellViewModel extends Disposable {
this._textEditor = editor;
if (this._editorViewStates) {
- this._textEditorRestore = setTimeout(() => {
- this._restoreViewState(this._editorViewStates);
- });
+ this._restoreViewState(this._editorViewStates);
}
if (this._editorTransientState) {
@@ -264,7 +260,6 @@ export abstract class BaseCellViewModel extends Disposable {
}
detachTextEditor() {
- clearTimeout(this._textEditorRestore);
this.saveViewState();
this.saveTransientState();
// decorations need to be cleared first as editors can be resued.
@@ -589,7 +584,6 @@ export abstract class BaseCellViewModel extends Disposable {
super.dispose();
dispose(this._editorListeners);
- clearTimeout(this._textEditorRestore);
// Only remove the undo redo stack if we map this cell uri to itself
// If we are not in perCell mode, it will map to the full NotebookDocument and
diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts
index a90477db542..b1cf70a4946 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorWidgetContextKeys.ts
@@ -8,7 +8,7 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
import { ICellViewModel, INotebookEditorDelegate, KERNEL_EXTENSIONS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NOTEBOOK_CELL_TOOLBAR_LOCATION, NOTEBOOK_HAS_OUTPUTS, NOTEBOOK_HAS_RUNNING_CELL, NOTEBOOK_INTERRUPTIBLE_KERNEL, NOTEBOOK_KERNEL, NOTEBOOK_KERNEL_COUNT, NOTEBOOK_KERNEL_SELECTED, NOTEBOOK_MISSING_KERNEL_EXTENSION, NOTEBOOK_USE_CONSOLIDATED_OUTPUT_BUTTON, NOTEBOOK_VIEW_TYPE } from 'vs/workbench/contrib/notebook/common/notebookContextKeys';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
-import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
export class NotebookEditorContextKeys {
@@ -148,7 +148,7 @@ export class NotebookEditorContextKeys {
const { selected, all } = this._notebookKernelService.getMatchingKernel(this._editor.textModel);
this._notebookKernelCount.set(all.length);
- this._interruptibleKernel.set(selected?.implementsInterrupt ?? false);
+ this._interruptibleKernel.set((selected?.type === NotebookKernelType.Resolved && selected.implementsInterrupt) ?? false);
this._notebookKernelSelected.set(Boolean(selected));
this._notebookKernel.set(selected?.id ?? '');
}
diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts
index dc9a494193e..e5814ce98ec 100644
--- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts
+++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts
@@ -6,10 +6,11 @@
import 'vs/css!./notebookKernelActionViewItem';
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { Action, IAction } from 'vs/base/common/actions';
+import { DisposableStore } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
-import { INotebookKernelMatchResult, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelMatchResult, INotebookKernelService, NotebookKernelType, ProxyKernelState } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { Event } from 'vs/base/common/event';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
@@ -17,6 +18,7 @@ import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookB
export class NotebooKernelActionViewItem extends ActionViewItem {
private _kernelLabel?: HTMLAnchorElement;
+ private _kernelDisposable: DisposableStore;
constructor(
actualAction: IAction,
@@ -31,6 +33,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem {
this._register(_editor.onDidChangeModel(this._update, this));
this._register(_notebookKernelService.onDidChangeNotebookAffinity(this._update, this));
this._register(_notebookKernelService.onDidChangeSelectedNotebooks(this._update, this));
+ this._kernelDisposable = this._register(new DisposableStore());
}
override render(container: HTMLElement): void {
@@ -63,9 +66,9 @@ export class NotebooKernelActionViewItem extends ActionViewItem {
}
private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void {
-
+ this._kernelDisposable.clear();
this._action.enabled = true;
- const selectedOrSuggested = info.selected ?? (info.all.length === 1 && info.suggestions.length === 1 ? info.suggestions[0] : undefined);
+ const selectedOrSuggested = info.selected ?? ((info.suggestions.length === 1 && info.suggestions[0].type === NotebookKernelType.Resolved) ? info.suggestions[0] : undefined);
if (selectedOrSuggested) {
// selected or suggested kernel
this._action.label = selectedOrSuggested.label;
@@ -74,6 +77,23 @@ export class NotebooKernelActionViewItem extends ActionViewItem {
// special UI for selected kernel?
}
+ if (selectedOrSuggested.type === NotebookKernelType.Proxy) {
+ if (selectedOrSuggested.connectionState === ProxyKernelState.Initializing) {
+ this._action.label = localize('initializing', "Initializing...");
+ } else {
+ this._action.label = selectedOrSuggested.label;
+ }
+
+ this._kernelDisposable.add(selectedOrSuggested.onDidChange(e => {
+ if (e.connectionState) {
+ if (selectedOrSuggested.connectionState === ProxyKernelState.Initializing) {
+ this._action.label = localize('initializing', "Initializing...");
+ } else {
+ this._action.label = selectedOrSuggested.label;
+ }
+ }
+ }));
+ }
} else {
// many kernels or no kernels
this._action.label = localize('select', "Select Kernel");
diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
index bc1f504dc36..28ff3f4f885 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts
@@ -25,8 +25,7 @@ import { IEditorModel } from 'vs/platform/editor/common/editor';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo';
-import { IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
-import { EditorInput } from 'vs/workbench/common/editor/editorInput';
+import { IRevertOptions, ISaveOptions, IUntypedEditorInput } from 'vs/workbench/common/editor';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
import { IWorkingCopyBackupMeta, IWorkingCopySaveEvent } from 'vs/workbench/services/workingCopy/common/workingCopy';
@@ -792,7 +791,7 @@ export interface INotebookEditorModel extends IEditorModel {
hasAssociatedFilePath(): boolean;
load(options?: INotebookLoadOptions): Promise<IResolvedNotebookEditorModel>;
save(options?: ISaveOptions): Promise<boolean>;
- saveAs(target: URI): Promise<EditorInput | undefined>;
+ saveAs(target: URI): Promise<IUntypedEditorInput | undefined>;
revert(options?: IRevertOptions): Promise<void>;
}
@@ -925,7 +924,10 @@ export const NotebookSetting = {
textOutputLineLimit: 'notebook.output.textLineLimit',
globalToolbarShowLabel: 'notebook.globalToolbarShowLabel',
markupFontSize: 'notebook.markup.fontSize',
- interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode'
+ interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode',
+ outputLineHeight: 'notebook.outputLineHeight',
+ outputFontSize: 'notebook.outputFontSize',
+ outputFontFamily: 'notebook.outputFontFamily'
} as const;
export const enum CellStatusbarAlignment {
diff --git a/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts b/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts
index fd2279cba63..689f9ca995e 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookContextKeys.ts
@@ -38,6 +38,8 @@ export const NOTEBOOK_CELL_EXECUTING = new RawContextKey<boolean>('notebookCellE
export const NOTEBOOK_CELL_HAS_OUTPUTS = new RawContextKey<boolean>('notebookCellHasOutputs', false);
export const NOTEBOOK_CELL_INPUT_COLLAPSED = new RawContextKey<boolean>('notebookCellInputIsCollapsed', false);
export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey<boolean>('notebookCellOutputIsCollapsed', false);
+export const NOTEBOOK_CELL_RESOURCE = new RawContextKey<string>('notebookCellResource', '');
+
// Kernels
export const NOTEBOOK_KERNEL = new RawContextKey<string>('notebookKernel', undefined);
export const NOTEBOOK_KERNEL_COUNT = new RawContextKey<number>('notebookKernelCount', 0);
diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
index cffd2b0362d..b8cbd4985d0 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts
@@ -102,6 +102,10 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
}
}
+ if (!(capabilities & EditorInputCapabilities.Readonly)) {
+ capabilities |= EditorInputCapabilities.CanDropIntoEditor;
+ }
+
return capabilities;
}
@@ -120,7 +124,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
return this._editorModelReference.object.isDirty();
}
- override async save(group: GroupIdentifier, options?: ISaveOptions): Promise<EditorInput | undefined> {
+ override async save(group: GroupIdentifier, options?: ISaveOptions): Promise<EditorInput | IUntypedEditorInput | undefined> {
if (this._editorModelReference) {
if (this.hasCapability(EditorInputCapabilities.Untitled)) {
@@ -135,7 +139,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput {
return undefined;
}
- override async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise<EditorInput | undefined> {
+ override async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise<IUntypedEditorInput | undefined> {
if (!this._editorModelReference) {
return undefined;
}
diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
index 8938cff2e80..7cd345036a7 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts
@@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
-import { IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
-import { EditorInput } from 'vs/workbench/common/editor/editorInput';
+import { IRevertOptions, ISaveOptions, IUntypedEditorInput } from 'vs/workbench/common/editor';
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
import { Emitter, Event } from 'vs/base/common/event';
import { ICellDto2, INotebookEditorModel, INotebookLoadOptions, IResolvedNotebookEditorModel, NotebookCellsChangeType, NotebookData, NotebookDocumentBackupData } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@@ -28,8 +27,6 @@ import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/commo
import { StoredFileWorkingCopyState, IStoredFileWorkingCopy, IStoredFileWorkingCopyModel, IStoredFileWorkingCopyModelContentChangedEvent, IStoredFileWorkingCopyModelFactory, IStoredFileWorkingCopySaveEvent } from 'vs/workbench/services/workingCopy/common/storedFileWorkingCopy';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { CancellationError } from 'vs/base/common/errors';
-import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
-import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { filter } from 'vs/base/common/objects';
import { IFileWorkingCopyManager } from 'vs/workbench/services/workingCopy/common/fileWorkingCopyManager';
import { IUntitledFileWorkingCopy, IUntitledFileWorkingCopyModel, IUntitledFileWorkingCopyModelContentChangedEvent, IUntitledFileWorkingCopyModelFactory } from 'vs/workbench/services/workingCopy/common/untitledFileWorkingCopy';
@@ -59,7 +56,6 @@ export class ComplexNotebookEditorModel extends EditorModel implements INotebook
readonly resource: URI,
readonly viewType: string,
private readonly _contentProvider: INotebookContentProvider,
- @IInstantiationService private readonly _instantiationService: IInstantiationService,
@INotebookService private readonly _notebookService: INotebookService,
@IWorkingCopyService private readonly _workingCopyService: IWorkingCopyService,
@IWorkingCopyBackupService private readonly _workingCopyBackupService: IWorkingCopyBackupService,
@@ -393,7 +389,7 @@ export class ComplexNotebookEditorModel extends EditorModel implements INotebook
});
}
- async saveAs(targetResource: URI): Promise<EditorInput | undefined> {
+ async saveAs(targetResource: URI): Promise<IUntypedEditorInput | undefined> {
if (!this.isResolved()) {
return undefined;
@@ -419,7 +415,7 @@ export class ComplexNotebookEditorModel extends EditorModel implements INotebook
}
this.setDirty(false);
this._onDidSave.fire({});
- return this._instantiationService.createInstance(NotebookEditorInput, targetResource, this.viewType, {});
+ return { resource: targetResource };
}
private async _resolveStats(resource: URI) {
@@ -462,7 +458,6 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE
private readonly _hasAssociatedFilePath: boolean,
readonly viewType: string,
private readonly _workingCopyManager: IFileWorkingCopyManager<NotebookFileWorkingCopyModel, NotebookFileWorkingCopyModel>,
- @IInstantiationService private readonly _instantiationService: IInstantiationService,
@IFileService private readonly _fileService: IFileService
) {
super();
@@ -547,14 +542,14 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE
return this;
}
- async saveAs(target: URI): Promise<EditorInput | undefined> {
+ async saveAs(target: URI): Promise<IUntypedEditorInput | undefined> {
const newWorkingCopy = await this._workingCopyManager.saveAs(this.resource, target);
if (!newWorkingCopy) {
return undefined;
}
// this is a little hacky because we leave the new working copy alone. BUT
// the newly created editor input will pick it up and claim ownership of it.
- return this._instantiationService.createInstance(NotebookEditorInput, newWorkingCopy.resource, this.viewType, {});
+ return { resource: newWorkingCopy.resource };
}
private static _isStoredFileWorkingCopy(candidate?: IStoredFileWorkingCopy<NotebookFileWorkingCopyModel> | IUntitledFileWorkingCopy<NotebookFileWorkingCopyModel>): candidate is IStoredFileWorkingCopy<NotebookFileWorkingCopyModel> {
diff --git a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts
index 6610fe7177d..4f5304600b0 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts
@@ -31,8 +31,13 @@ export interface INotebookKernelChangeEvent {
hasExecutionOrder?: true;
}
-export interface INotebookKernel {
+export const enum NotebookKernelType {
+ Resolved,
+ Proxy = 1
+}
+export interface IResolvedNotebookKernel {
+ readonly type: NotebookKernelType.Resolved;
readonly id: string;
readonly viewType: string;
readonly onDidChange: Event<Readonly<INotebookKernelChangeEvent>>;
@@ -54,6 +59,34 @@ export interface INotebookKernel {
cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise<void>;
}
+export const enum ProxyKernelState {
+ Disconnected = 1,
+ Connected = 2,
+ Initializing = 3
+}
+
+export interface INotebookProxyKernelChangeEvent extends INotebookKernelChangeEvent {
+ connectionState?: true;
+}
+
+export interface INotebookProxyKernel {
+ readonly type: NotebookKernelType.Proxy;
+ readonly id: string;
+ readonly viewType: string;
+ readonly extension: ExtensionIdentifier;
+ readonly preloadProvides: string[];
+ readonly onDidChange: Event<Readonly<INotebookProxyKernelChangeEvent>>;
+ label: string;
+ description?: string;
+ detail?: string;
+ kind?: string;
+ supportedLanguages: string[];
+ connectionState: ProxyKernelState;
+ resolveKernel(uri: URI): Promise<string | null>;
+}
+
+export type INotebookKernel = IResolvedNotebookKernel | INotebookProxyKernel;
+
export interface INotebookTextModelLike { uri: URI; viewType: string }
export const INotebookKernelService = createDecorator<INotebookKernelService>('INotebookKernelService');
diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts
index 9564a563def..426871f84fa 100644
--- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts
+++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts
@@ -62,6 +62,9 @@ export interface NotebookLayoutConfiguration {
showFoldingControls: 'always' | 'mouseover';
dragAndDropEnabled: boolean;
fontSize: number;
+ outputFontSize: number;
+ outputFontFamily: string;
+ outputLineHeight: number;
markupFontSize: number;
focusIndicatorLeftMargin: number;
editorOptionsCustomizations: any | undefined;
@@ -84,9 +87,13 @@ export interface NotebookOptionsChangeEvent {
readonly consolidatedRunButton?: boolean;
readonly dragAndDropEnabled?: boolean;
readonly fontSize?: boolean;
+ readonly outputFontSize?: boolean;
readonly markupFontSize?: boolean;
+ readonly fontFamily?: boolean;
+ readonly outputFontFamily?: boolean;
readonly editorOptionsCustomizations?: boolean;
readonly interactiveWindowCollapseCodeCells?: boolean;
+ readonly outputLineHeight?: boolean;
}
const defaultConfigConstants = Object.freeze({
@@ -134,9 +141,12 @@ export class NotebookOptions extends Disposable {
const showFoldingControls = this._computeShowFoldingControlsOption();
// const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(compactView, insertToolbarPosition, insertToolbarAlignment);
const fontSize = this.configurationService.getValue<number>('editor.fontSize');
+ const outputFontSize = this.configurationService.getValue<number>(NotebookSetting.outputFontSize);
+ const outputFontFamily = this.configurationService.getValue<string>(NotebookSetting.outputFontFamily);
const markupFontSize = this.configurationService.getValue<number>(NotebookSetting.markupFontSize);
const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations);
const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells);
+ const outputLineHeight = this._computeOutputLineHeight();
this._layoutConfiguration = {
...(compactView ? compactConfigConstants : defaultConfigConstants),
@@ -166,6 +176,9 @@ export class NotebookOptions extends Disposable {
insertToolbarAlignment,
showFoldingControls,
fontSize,
+ outputFontSize,
+ outputFontFamily,
+ outputLineHeight,
markupFontSize,
editorOptionsCustomizations,
focusIndicatorGap: 3,
@@ -185,6 +198,29 @@ export class NotebookOptions extends Disposable {
}));
}
+ private _computeOutputLineHeight(): number {
+ const minimumLineHeight = 8;
+ let lineHeight = this.configurationService.getValue<number>(NotebookSetting.outputLineHeight);
+
+ if (lineHeight < minimumLineHeight) {
+ // Values too small to be line heights in pixels are in ems.
+ let fontSize = this.configurationService.getValue<number>(NotebookSetting.outputFontSize);
+ if (fontSize === 0) {
+ fontSize = this.configurationService.getValue<number>('editor.fontSize');
+ }
+
+ lineHeight = lineHeight * fontSize;
+ }
+
+ // Enforce integer, minimum constraints
+ lineHeight = Math.round(lineHeight);
+ if (lineHeight < minimumLineHeight) {
+ lineHeight = minimumLineHeight;
+ }
+
+ return lineHeight;
+ }
+
private _updateConfiguration(e: IConfigurationChangeEvent) {
const cellStatusBarVisibility = e.affectsConfiguration(NotebookSetting.showCellStatusBar);
const cellToolbarLocation = e.affectsConfiguration(NotebookSetting.cellToolbarLocation);
@@ -199,9 +235,13 @@ export class NotebookOptions extends Disposable {
const showFoldingControls = e.affectsConfiguration(NotebookSetting.showFoldingControls);
const dragAndDropEnabled = e.affectsConfiguration(NotebookSetting.dragAndDropEnabled);
const fontSize = e.affectsConfiguration('editor.fontSize');
+ const outputFontSize = e.affectsConfiguration(NotebookSetting.outputFontSize);
const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize);
+ const fontFamily = e.affectsConfiguration('editor.fontFamily');
+ const outputFontFamily = e.affectsConfiguration(NotebookSetting.outputFontFamily);
const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations);
const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells);
+ const outputLineHeight = e.affectsConfiguration(NotebookSetting.outputLineHeight);
if (
!cellStatusBarVisibility
@@ -217,9 +257,13 @@ export class NotebookOptions extends Disposable {
&& !showFoldingControls
&& !dragAndDropEnabled
&& !fontSize
+ && !outputFontSize
&& !markupFontSize
+ && !fontFamily
+ && !outputFontFamily
&& !editorOptionsCustomizations
- && !interactiveWindowCollapseCodeCells) {
+ && !interactiveWindowCollapseCodeCells
+ && !outputLineHeight) {
return;
}
@@ -281,10 +325,18 @@ export class NotebookOptions extends Disposable {
configuration.fontSize = this.configurationService.getValue<number>('editor.fontSize');
}
+ if (outputFontSize) {
+ configuration.outputFontSize = this.configurationService.getValue<number>(NotebookSetting.outputFontSize) ?? configuration.fontSize;
+ }
+
if (markupFontSize) {
configuration.markupFontSize = this.configurationService.getValue<number>(NotebookSetting.markupFontSize);
}
+ if (outputFontFamily) {
+ configuration.outputFontFamily = this.configurationService.getValue<string>(NotebookSetting.outputFontFamily);
+ }
+
if (editorOptionsCustomizations) {
configuration.editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations);
}
@@ -293,6 +345,10 @@ export class NotebookOptions extends Disposable {
configuration.interactiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells);
}
+ if (outputLineHeight || fontSize || outputFontSize) {
+ configuration.outputLineHeight = this._computeOutputLineHeight();
+ }
+
this._layoutConfiguration = Object.freeze(configuration);
// trigger event
@@ -310,9 +366,13 @@ export class NotebookOptions extends Disposable {
consolidatedRunButton,
dragAndDropEnabled,
fontSize,
+ outputFontSize,
markupFontSize,
+ fontFamily,
+ outputFontFamily,
editorOptionsCustomizations,
- interactiveWindowCollapseCodeCells
+ interactiveWindowCollapseCodeCells,
+ outputLineHeight
});
}
@@ -502,7 +562,10 @@ export class NotebookOptions extends Disposable {
runGutter: this._layoutConfiguration.cellRunGutter,
dragAndDropEnabled: this._layoutConfiguration.dragAndDropEnabled,
fontSize: this._layoutConfiguration.fontSize,
+ outputFontSize: this._layoutConfiguration.outputFontSize,
+ outputFontFamily: this._layoutConfiguration.outputFontFamily,
markupFontSize: this._layoutConfiguration.markupFontSize,
+ outputLineHeight: this._layoutConfiguration.outputLineHeight,
};
}
@@ -517,7 +580,10 @@ export class NotebookOptions extends Disposable {
runGutter: 0,
dragAndDropEnabled: false,
fontSize: this._layoutConfiguration.fontSize,
+ outputFontSize: this._layoutConfiguration.outputFontSize,
+ outputFontFamily: this._layoutConfiguration.outputFontFamily,
markupFontSize: this._layoutConfiguration.markupFontSize,
+ outputLineHeight: this._layoutConfiguration.outputLineHeight,
};
}
diff --git a/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts b/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts
index b9822f87393..6b1282d9afb 100644
--- a/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts
+++ b/src/vs/workbench/contrib/notebook/test/browser/contrib/find.test.ts
@@ -68,11 +68,11 @@ suite('Notebook Find', () => {
await found;
assert.strictEqual(model.findMatches.length, 2);
assert.strictEqual(model.currentMatch, -1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 0);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 0);
assert.strictEqual(editor.textModel.length, 3);
@@ -115,11 +115,11 @@ suite('Notebook Find', () => {
// find matches is not necessarily find results
assert.strictEqual(model.findMatches.length, 4);
assert.strictEqual(model.currentMatch, -1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 0);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 2);
const found2 = new Promise<boolean>(resolve => state.onFindReplaceStateChange(e => {
@@ -132,13 +132,13 @@ suite('Notebook Find', () => {
assert.strictEqual(model.findMatches.length, 3);
assert.strictEqual(model.currentMatch, 2);
- model.find(true);
+ model.find({ previous: true });
assert.strictEqual(model.currentMatch, 1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 2);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 3);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 0);
});
});
@@ -166,7 +166,7 @@ suite('Notebook Find', () => {
// find matches is not necessarily find results
assert.strictEqual(model.findMatches.length, 4);
assert.strictEqual(model.currentMatch, -1);
- model.find(true);
+ model.find({ previous: true });
assert.strictEqual(model.currentMatch, 4);
const found2 = new Promise<boolean>(resolve => state.onFindReplaceStateChange(e => {
@@ -178,9 +178,9 @@ suite('Notebook Find', () => {
await found2;
assert.strictEqual(model.findMatches.length, 3);
assert.strictEqual(model.currentMatch, 0);
- model.find(true);
+ model.find({ previous: true });
assert.strictEqual(model.currentMatch, 3);
- model.find(true);
+ model.find({ previous: true });
assert.strictEqual(model.currentMatch, 2);
});
});
@@ -208,9 +208,9 @@ suite('Notebook Find', () => {
// find matches is not necessarily find results
assert.strictEqual(model.findMatches.length, 4);
assert.strictEqual(model.currentMatch, -1);
- model.find(false);
- model.find(false);
- model.find(false);
+ model.find({ previous: false });
+ model.find({ previous: false });
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 2);
const found2 = new Promise<boolean>(resolve => state.onFindReplaceStateChange(e => {
if (e.matchesCount) { resolve(true); }
@@ -244,11 +244,11 @@ suite('Notebook Find', () => {
await found;
assert.strictEqual(model.findMatches.length, 2);
assert.strictEqual(model.currentMatch, -1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 0);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 1);
- model.find(false);
+ model.find({ previous: false });
assert.strictEqual(model.currentMatch, 0);
assert.strictEqual(editor.textModel.length, 3);
diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts
index d71a25076b3..124729d29b4 100644
--- a/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts
+++ b/src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts
@@ -10,7 +10,6 @@ import { isEqual } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { IFileService } from 'vs/platform/files/common/files';
-import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ILabelService } from 'vs/platform/label/common/label';
import { NullLogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -187,7 +186,6 @@ suite('NotebookFileWorkingCopyModel', function () {
suite('ComplexNotebookEditorModel', function () {
- const instaService = new InstantiationService();
const notebokService = new class extends mock<INotebookService>() { };
const backupService = new class extends mock<IWorkingCopyBackupService>() { };
const notificationService = new class extends mock<INotificationService>() { };
@@ -214,8 +212,8 @@ suite('ComplexNotebookEditorModel', function () {
}
};
- new ComplexNotebookEditorModel(r1, 'fff', notebookDataProvider, instaService, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService);
- new ComplexNotebookEditorModel(r2, 'fff', notebookDataProvider, instaService, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService);
+ new ComplexNotebookEditorModel(r1, 'fff', notebookDataProvider, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService);
+ new ComplexNotebookEditorModel(r2, 'fff', notebookDataProvider, notebokService, workingCopyService, backupService, fileService, notificationService, new NullLogService(), untitledTextEditorService, labelService);
assert.strictEqual(copies.length, 2);
assert.strictEqual(!isEqual(copies[0].resource, copies[1].resource), true);
diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts
index 6f65268830f..8d3bff7a83a 100644
--- a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts
+++ b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionService.test.ts
@@ -20,7 +20,7 @@ import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellKind, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
-import { INotebookKernel, INotebookKernelService, ISelectedNotebooksChangeEvent } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelService, IResolvedNotebookKernel, ISelectedNotebooksChangeEvent, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor';
@@ -166,7 +166,8 @@ suite('NotebookExecutionService', () => {
});
});
-class TestNotebookKernel implements INotebookKernel {
+class TestNotebookKernel implements IResolvedNotebookKernel {
+ type: NotebookKernelType.Resolved = NotebookKernelType.Resolved;
id: string = 'test';
label: string = '';
viewType = '*';
diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts
index 887a4a05443..e5b7f84b8bf 100644
--- a/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts
+++ b/src/vs/workbench/contrib/notebook/test/browser/notebookExecutionStateService.test.ts
@@ -21,7 +21,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no
import { CellEditType, CellKind, CellUri, IOutputDto, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService';
import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService';
-import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelService, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor';
@@ -170,7 +170,8 @@ suite('NotebookExecutionStateService', () => {
});
});
-class TestNotebookKernel implements INotebookKernel {
+class TestNotebookKernel implements IResolvedNotebookKernel {
+ type: NotebookKernelType.Resolved = NotebookKernelType.Resolved;
id: string = 'test';
label: string = '';
viewType = '*';
diff --git a/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts b/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts
index b1ebabc1db2..62d6afecb8b 100644
--- a/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts
+++ b/src/vs/workbench/contrib/notebook/test/browser/notebookKernelService.test.ts
@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { setupInstantiationService, withTestNotebook as _withTestNotebook } from 'vs/workbench/contrib/notebook/test/browser/testNotebookEditor';
import { Emitter, Event } from 'vs/base/common/event';
-import { INotebookKernel, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
+import { INotebookKernelService, IResolvedNotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
import { NotebookKernelService } from 'vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { mock } from 'vs/base/test/common/mock';
@@ -159,7 +159,8 @@ suite('NotebookKernelService', () => {
});
});
-class TestNotebookKernel implements INotebookKernel {
+class TestNotebookKernel implements IResolvedNotebookKernel {
+ type: NotebookKernelType.Resolved = NotebookKernelType.Resolved;
id: string = Math.random() + 'kernel';
label: string = 'test-label';
viewType = '*';