From 6e1e0b1d899b2d262265e8faeadee98c562cfe7b Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Fri, 1 Apr 2022 17:35:06 +0200 Subject: Moves tokenization logic from text model to its own text model part. --- .../contrib/notebook/browser/view/cellParts/cellDragRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') 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); -- cgit v1.2.3 From 12f64a68ba92805f9f316eb57d64aa92203adad9 Mon Sep 17 00:00:00 2001 From: rebornix Date: Sun, 3 Apr 2022 11:02:07 -0700 Subject: faster CellFolding ctor. --- .../workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') 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..39026ca2aca 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)), -- cgit v1.2.3 From 9405808b23f254e1ce619a6cdc75635a94cb8d45 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 6 Apr 2022 10:39:47 -0700 Subject: Use SELECT_KERNEL_ID other than string literal --- .../notebook/browser/contrib/editorStatusBar/editorStatusBar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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..83b35ce916d 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -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, @@ -381,7 +381,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 +399,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { command: SELECT_KERNEL_ID, backgroundColor: { id: 'statusBarItem.prominentBackground' } }, - '_notebook.selectKernel', + SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, 10 )); -- cgit v1.2.3 From ad78a1cdfec4a96fa550355dbc9b189dd9ea4c65 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 7 Apr 2022 12:18:41 -0800 Subject: Enable drop into editor for notebooks (#146966) Fixes #146961 This makes two changes: - For drag over, make sure the cellDnd sees the event before the editor widget does (using `useCapture`). This lets us avoid showing the drop into indicator when dragging notebook cells - For drag_over and drop events, don't do anything if a cell is not being dragged. This lets us drop other things into code cells --- .../contrib/notebook/browser/view/cellParts/cellDnd.ts | 13 ++++++++++--- .../contrib/notebook/browser/view/cellParts/markdownCell.ts | 1 + .../contrib/notebook/browser/view/renderers/cellRenderer.ts | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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/markdownCell.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts index bf119feb15c..b7652ba37ca 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/markdownCell.ts @@ -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/cellRenderer.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts index 39026ca2aca..2bcf55c8531 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts @@ -274,6 +274,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende width: 0, height: 0 }, + enableDropIntoEditor: true, }, { contributions: this.notebookEditor.creationOptions.cellEditorContributions }); -- cgit v1.2.3 From 897ab9567cc31477e5955a7f4b34750b6faacbaf Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Fri, 8 Apr 2022 09:13:06 +0200 Subject: editors - reload error placeholder when file is coming back --- src/vs/workbench/contrib/notebook/browser/notebookEditor.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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; } -- cgit v1.2.3 From 860221a1933842f41afc19c304ed3c1a04da0671 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 11 Apr 2022 08:05:40 -0700 Subject: two kernel types --- .../contrib/editorStatusBar/editorStatusBar.ts | 5 +++ .../notebook/browser/controller/apiActions.ts | 6 ++-- .../notebook/browser/notebookEditorWidget.ts | 10 +++++- .../browser/notebookExecutionServiceImpl.ts | 24 +++++++++++++- .../notebook/browser/notebookKernelServiceImpl.ts | 28 +++++++++++++++- .../browser/view/cellParts/cellExecution.ts | 3 +- .../notebook/browser/view/cellParts/cellOutput.ts | 9 +++--- .../browser/view/renderers/backLayerWebView.ts | 12 +++---- .../viewParts/notebookEditorWidgetContextKeys.ts | 4 +-- .../viewParts/notebookKernelActionViewItem.ts | 27 ++++++++++++++-- .../notebook/common/notebookKernelService.ts | 37 ++++++++++++++++++++-- .../test/browser/notebookExecutionService.test.ts | 5 +-- .../browser/notebookExecutionStateService.test.ts | 5 +-- .../test/browser/notebookKernelService.test.ts | 5 +-- 14 files changed, 150 insertions(+), 30 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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 83b35ce916d..c93c6b17ba2 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -197,6 +197,11 @@ registerAction2(class extends Action2 { quickPickItems.push(...suggestions.map(toQuickPick)); } + quickPickItems.push({ + id: 'install', + label: nls.localize('installKernels', "Install kernels from the marketplace"), + }); + // Next display all of the kernels grouped by categories or extensions. // If we don't have a kind, always display those at the bottom. const picks = all.filter(item => !suggestions.includes(item)).map(toQuickPick); 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/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index aa1bcc7853f..bafa9981455 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -76,7 +76,7 @@ import { CellKind, INotebookSearchOptions, SelectionStateType } from 'vs/workben import { NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; 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'; import { NotebookOptions, OutputInnerContainerTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; @@ -2108,6 +2108,14 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD return; } const { selected } = this.notebookKernelService.getMatchingKernel(this.textModel); + if (!selected) { + return; + } + + if (selected.type === NotebookKernelType.Proxy) { + return; + } + if (!this._webview?.isResolved()) { await this._resolveWebview(); } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts index 000c7b3b72c..b8877a553a2 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts @@ -12,7 +12,7 @@ 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 { declare _serviceBrand: undefined; @@ -45,6 +45,23 @@ export class NotebookExecutionService implements INotebookExecutionService { return; } + if (kernel.type === NotebookKernelType.Proxy) { + // we should actually resolve the kernel + const resolved = await kernel.resolveKernel(notebook.uri); + let kernels = this._notebookKernelService.getMatchingKernel(notebook); + const newlyMatchedKernel = kernels.all.find(k => k.id === resolved); + + if (!newlyMatchedKernel) { + return; + } + + kernel = newlyMatchedKernel; + } + + if (kernel.type === NotebookKernelType.Proxy) { + return; + } + const executeCells: NotebookCellTextModel[] = []; for (const cell of cellsArr) { const cellExe = this._notebookExecutionStateService.getCellExecution(cell.uri); @@ -75,6 +92,11 @@ export class NotebookExecutionService implements INotebookExecutionService { this._logService.debug(`NotebookExecutionService#cancelNotebookCellHandles ${JSON.stringify(cellsArr)}`); const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(notebook); if (kernel) { + if (kernel.type === NotebookKernelType.Proxy) { + // we should handle cancelling proxy kernel too + return; + } + await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr); } } diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts index 1f2e2e72032..09e75953d84 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts @@ -6,7 +6,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { INotebookTextModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike, INotebookProxyKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { LRUCache, ResourceMap } from 'vs/base/common/map'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { URI } from 'vs/base/common/uri'; @@ -164,6 +164,32 @@ export class NotebookKernelService extends Disposable implements INotebookKernel }); } + registerProxyKernel(kernel: INotebookProxyKernel): IDisposable { + if (this._kernels.has(kernel.id)) { + throw new Error(`NOTEBOOK CONTROLLER with id '${kernel.id}' already exists`); + } + + this._kernels.set(kernel.id, new KernelInfo(kernel)); + this._onDidAddKernel.fire(kernel); + + // auto associate the new kernel to existing notebooks it was + // associated to in the past. + for (const notebook of this._notebookService.getNotebookTextModels()) { + this._tryAutoBindNotebook(notebook, kernel); + } + + return toDisposable(() => { + if (this._kernels.delete(kernel.id)) { + this._onDidRemoveKernel.fire(kernel); + } + for (const [key, candidate] of Array.from(this._notebookBindings)) { + if (candidate === kernel.id) { + this._onDidChangeNotebookKernelBinding.fire({ notebook: NotebookTextModelLikeId.obj(key).uri, oldKernel: kernel.id, newKernel: undefined }); + } + } + }); + } + getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult { // all applicable kernels 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..eb6e260ec10 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}]` : '[ ]'; diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts index 7306836ac30..7ed12d9bb09 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts @@ -31,7 +31,7 @@ import { CodeCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/vi import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellUri, IOrderedMimeType, NotebookCellOutputsSplice, RENDERER_NOT_AVAILABLE } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; @@ -127,7 +127,8 @@ export class CellOutputElement extends Disposable { this.notebookEditor.hasModel() && this.innerContainer && this.renderResult && - this.renderResult.type === RenderOutputType.Extension + this.renderResult.type === RenderOutputType.Extension && + this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved ) { // Output rendered by extension renderer got an update const [mimeTypes, pick] = this.output.resolveMimeTypes(this.notebookEditor.textModel, this.notebookEditor.activeKernel?.preloadProvides); @@ -191,7 +192,7 @@ export class CellOutputElement extends Disposable { const notebookTextModel = this.notebookEditor.textModel; - const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.preloadProvides); + const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved ? this.notebookEditor.activeKernel?.preloadProvides : undefined); if (!mimeTypes.find(mimeType => mimeType.isTrusted) || mimeTypes.length === 0) { this.viewCell.updateOutputHeight(index, 0, 'CellOutputElement#noMimeType'); @@ -299,7 +300,7 @@ export class CellOutputElement extends Disposable { } private async _pickActiveMimeTypeRenderer(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, viewModel: ICellOutputViewModel) { - const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.preloadProvides); + const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.type === NotebookKernelType.Resolved ? kernel?.preloadProvides : undefined); const items: IMimeTypeRenderer[] = []; const unsupportedItems: IMimeTypeRenderer[] = []; 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..669bcb2a519 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -37,7 +37,7 @@ 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'; @@ -897,7 +897,7 @@ var requirejs = (function() { } this._preloadsCache.clear(); - if (this._currentKernel) { + if (this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(this._currentKernel); } @@ -1394,14 +1394,14 @@ var requirejs = (function() { const previousKernel = this._currentKernel; this._currentKernel = kernel; - if (previousKernel && previousKernel.preloadUris.length > 0) { + if (previousKernel && 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 +1427,7 @@ var requirejs = (function() { const mixedResourceRoots = [ ...(this.localResourceRootsCache || []), - ...(this._currentKernel ? [this._currentKernel.localResourceRoot] : []), + ...(this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []), ]; this.webview.localResourcesRoot = mixedResourceRoots; 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..41e1ec74773 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -9,14 +9,16 @@ import { Action, IAction } from 'vs/base/common/actions'; 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, 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'; +import { DisposableStore } from 'vs/base/common/lifecycle'; 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.all.length === 1 && info.suggestions.length === 1 && !('resolveKernel' in info.suggestions[0])) ? info.suggestions[0] : undefined); if (selectedOrSuggested) { // selected or suggested kernel this._action.label = selectedOrSuggested.label; @@ -74,6 +77,24 @@ export class NotebooKernelActionViewItem extends ActionViewItem { // special UI for selected kernel? } + if ('resolveKernel' in selectedOrSuggested) { + 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/notebookKernelService.ts b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts index 6610fe7177d..19ee2cf2b66 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>; @@ -54,6 +59,33 @@ export interface INotebookKernel { cancelNotebookCellExecution(uri: URI, cellHandles: number[]): Promise; } +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 onDidChange: Event>; + label: string; + description?: string; + detail?: string; + kind?: string; + supportedLanguages: string[]; + connectionState: ProxyKernelState; + resolveKernel(uri: URI): Promise; +} + +export type INotebookKernel = IResolvedNotebookKernel | INotebookProxyKernel; + export interface INotebookTextModelLike { uri: URI; viewType: string } export const INotebookKernelService = createDecorator('INotebookKernelService'); @@ -66,7 +98,8 @@ export interface INotebookKernelService { readonly onDidChangeSelectedNotebooks: Event; readonly onDidChangeNotebookAffinity: Event; - registerKernel(kernel: INotebookKernel): IDisposable; + registerKernel(kernel: IResolvedNotebookKernel): IDisposable; + registerProxyKernel(proxyKernel: INotebookProxyKernel): IDisposable; getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult; 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 = '*'; -- cgit v1.2.3 From a4e3e86c5955b42fa0168c943f52d433b263ba56 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 11 Apr 2022 13:59:40 -0700 Subject: Revert "delay editor restore." This reverts commit 960e1bd963aeee2b6d5cfa7c5750e32b1728ef34. --- .../contrib/notebook/browser/viewModel/baseCellViewModel.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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 -- cgit v1.2.3 From eda166b7fa6377d2bd2fd2c33e5a844ea1b7bddd Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 13 Apr 2022 12:00:09 +0530 Subject: Move output service to workbench/services --- .../contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') 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'; -- cgit v1.2.3 From 9a87fe7eaf2bcf29de4f5ec7c02044c410c95c0f Mon Sep 17 00:00:00 2001 From: aamunger Date: Mon, 11 Apr 2022 12:44:15 -0700 Subject: added setting for notebook output line height --- .../contrib/notebook/browser/notebook.contribution.ts | 6 ++++++ .../contrib/notebook/browser/notebookEditorWidget.ts | 2 +- .../browser/view/renderers/backLayerWebView.ts | 2 ++ .../contrib/notebook/common/notebookCommon.ts | 3 ++- .../contrib/notebook/common/notebookOptions.ts | 18 ++++++++++++++++-- 5 files changed, 27 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 2b793c40961..f1c5936099e 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -892,5 +892,11 @@ configurationRegistry.registerConfiguration({ enum: ['always', 'never', 'fromEditor'], default: 'fromEditor' }, + [NotebookSetting.outputLineHeight]: { + markdownDescription: nls.localize('notebook.outputLineHeight', "line height of the output text"), + type: 'number', + default: 22, + tags: ['notebookLayout'] + }, } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index aa1bcc7853f..3cc81adc47a 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,7 @@ 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.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ 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..4917457e7dc 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -81,6 +81,7 @@ export interface INotebookDelegateForWebview { interface BacklayerWebviewOptions { readonly outputNodePadding: number; readonly outputNodeLeftPadding: number; + readonly outputLineHeight: number; readonly previewNodePadding: number; readonly markdownLeftMargin: number; readonly leftMargin: number; @@ -205,6 +206,7 @@ export class BackLayerWebView extends Disposable { '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-line-height': `${this.options.outputLineHeight}px`, 'notebook-cell-output-font-family': 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({ diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index b93c8a7449f..4a2b3f9e405 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -913,7 +913,8 @@ export const NotebookSetting = { textOutputLineLimit: 'notebook.output.textLineLimit', globalToolbarShowLabel: 'notebook.globalToolbarShowLabel', markupFontSize: 'notebook.markup.fontSize', - interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode' + interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode', + outputLineHeight: 'notebook.outputLineHeight' } as const; export const enum CellStatusbarAlignment { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 9564a563def..91d23a63e48 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -62,6 +62,7 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; + outputLineHeight: number; markupFontSize: number; focusIndicatorLeftMargin: number; editorOptionsCustomizations: any | undefined; @@ -87,6 +88,7 @@ export interface NotebookOptionsChangeEvent { readonly markupFontSize?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; + readonly outputLineHeight?: boolean; } const defaultConfigConstants = Object.freeze({ @@ -137,6 +139,7 @@ export class NotebookOptions extends Disposable { const markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); + const outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); this._layoutConfiguration = { ...(compactView ? compactConfigConstants : defaultConfigConstants), @@ -166,6 +169,7 @@ export class NotebookOptions extends Disposable { insertToolbarAlignment, showFoldingControls, fontSize, + outputLineHeight, markupFontSize, editorOptionsCustomizations, focusIndicatorGap: 3, @@ -202,6 +206,7 @@ export class NotebookOptions extends Disposable { const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); + const outputLineHeight = e.affectsConfiguration(NotebookSetting.outputLineHeight); if ( !cellStatusBarVisibility @@ -219,7 +224,8 @@ export class NotebookOptions extends Disposable { && !fontSize && !markupFontSize && !editorOptionsCustomizations - && !interactiveWindowCollapseCodeCells) { + && !interactiveWindowCollapseCodeCells + && !outputLineHeight) { return; } @@ -293,8 +299,13 @@ export class NotebookOptions extends Disposable { configuration.interactiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); } + if (outputLineHeight) { + configuration.outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + } + this._layoutConfiguration = Object.freeze(configuration); + // add new configuration to the event? // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, @@ -312,7 +323,8 @@ export class NotebookOptions extends Disposable { fontSize, markupFontSize, editorOptionsCustomizations, - interactiveWindowCollapseCodeCells + interactiveWindowCollapseCodeCells, + outputLineHeight }); } @@ -503,6 +515,7 @@ export class NotebookOptions extends Disposable { dragAndDropEnabled: this._layoutConfiguration.dragAndDropEnabled, fontSize: this._layoutConfiguration.fontSize, markupFontSize: this._layoutConfiguration.markupFontSize, + outputLineHeight: this._layoutConfiguration.outputLineHeight, }; } @@ -518,6 +531,7 @@ export class NotebookOptions extends Disposable { dragAndDropEnabled: false, fontSize: this._layoutConfiguration.fontSize, markupFontSize: this._layoutConfiguration.markupFontSize, + outputLineHeight: this._layoutConfiguration.outputLineHeight, }; } -- cgit v1.2.3 From 51ab78f535d8537e031e1ae77cac678ae22b0249 Mon Sep 17 00:00:00 2001 From: aamunger Date: Tue, 12 Apr 2022 08:32:14 -0700 Subject: added setting to override notebook output font family and size --- .../notebook/browser/notebook.contribution.ts | 13 +++++++++- .../notebook/browser/notebookEditorWidget.ts | 2 +- .../browser/view/renderers/backLayerWebView.ts | 8 +++--- .../contrib/notebook/common/notebookCommon.ts | 4 ++- .../contrib/notebook/common/notebookOptions.ts | 30 ++++++++++++++++++++++ 5 files changed, 51 insertions(+), 6 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index f1c5936099e..17c7255ad50 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -893,10 +893,21 @@ configurationRegistry.registerConfiguration({ default: 'fromEditor' }, [NotebookSetting.outputLineHeight]: { - markdownDescription: nls.localize('notebook.outputLineHeight', "line height of the output text"), + markdownDescription: nls.localize('notebook.outputLineHeight', "Line height of the output text"), type: 'number', default: 22, tags: ['notebookLayout'] }, + [NotebookSetting.outputFontSize]: { + markdownDescription: nls.localize('notebook.outputFontSize', "Font size for plain text outputs. 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 plain text output of notebook cells. When set to empty, the `#editor.fontFamily#` is used."), + type: 'string', + tags: ['notebookLayout'] + }, } }); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 3cc81adc47a..15e56226ccd 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,7 @@ 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 || e.outputLineHeight) { + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.fontFamily || e.outputFontFamily || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ 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 4917457e7dc..d5ad9679436 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -81,7 +81,6 @@ export interface INotebookDelegateForWebview { interface BacklayerWebviewOptions { readonly outputNodePadding: number; readonly outputNodeLeftPadding: number; - readonly outputLineHeight: number; readonly previewNodePadding: number; readonly markdownLeftMargin: number; readonly leftMargin: number; @@ -89,8 +88,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 extends Disposable { @@ -205,9 +207,9 @@ export class BackLayerWebView 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-size': `${this.options.outputFontSize || this.options.fontSize}px`, 'notebook-cell-output-line-height': `${this.options.outputLineHeight}px`, - 'notebook-cell-output-font-family': this.options.fontFamily, + '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', diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 4a2b3f9e405..121ac0689da 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -914,7 +914,9 @@ export const NotebookSetting = { globalToolbarShowLabel: 'notebook.globalToolbarShowLabel', markupFontSize: 'notebook.markup.fontSize', interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode', - outputLineHeight: 'notebook.outputLineHeight' + outputLineHeight: 'notebook.outputLineHeight', + outputFontSize: 'notebook.outputFontSize', + outputFontFamily: 'notebook.fontFamily' } as const; export const enum CellStatusbarAlignment { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 91d23a63e48..b7c9b89a926 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -62,6 +62,8 @@ export interface NotebookLayoutConfiguration { showFoldingControls: 'always' | 'mouseover'; dragAndDropEnabled: boolean; fontSize: number; + outputFontSize: number; + outputFontFamily: string; outputLineHeight: number; markupFontSize: number; focusIndicatorLeftMargin: number; @@ -85,6 +87,9 @@ export interface NotebookOptionsChangeEvent { readonly consolidatedRunButton?: boolean; readonly dragAndDropEnabled?: boolean; readonly fontSize?: boolean; + readonly outputFontSize?: boolean; + readonly fontFamily?: boolean; + readonly outputFontFamily?: boolean; readonly markupFontSize?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; @@ -136,6 +141,8 @@ export class NotebookOptions extends Disposable { const showFoldingControls = this._computeShowFoldingControlsOption(); // const { bottomToolbarGap, bottomToolbarHeight } = this._computeBottomToolbarDimensions(compactView, insertToolbarPosition, insertToolbarAlignment); const fontSize = this.configurationService.getValue('editor.fontSize'); + const outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); + const outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); const markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); @@ -169,6 +176,8 @@ export class NotebookOptions extends Disposable { insertToolbarAlignment, showFoldingControls, fontSize, + outputFontSize, + outputFontFamily, outputLineHeight, markupFontSize, editorOptionsCustomizations, @@ -203,11 +212,15 @@ 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 fontFamily = e.affectsConfiguration('editor.fontFamily'); + const outputFontFamily = e.affectsConfiguration(NotebookSetting.outputFontFamily); const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); const outputLineHeight = e.affectsConfiguration(NotebookSetting.outputLineHeight); + if ( !cellStatusBarVisibility && !cellToolbarLocation @@ -222,6 +235,9 @@ export class NotebookOptions extends Disposable { && !showFoldingControls && !dragAndDropEnabled && !fontSize + && !outputFontSize + && !fontFamily + && !outputFontFamily && !markupFontSize && !editorOptionsCustomizations && !interactiveWindowCollapseCodeCells @@ -287,6 +303,14 @@ export class NotebookOptions extends Disposable { configuration.fontSize = this.configurationService.getValue('editor.fontSize'); } + if (outputFontSize) { + configuration.outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); + } + + if (outputFontFamily) { + configuration.outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); + } + if (markupFontSize) { configuration.markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); } @@ -321,6 +345,8 @@ export class NotebookOptions extends Disposable { consolidatedRunButton, dragAndDropEnabled, fontSize, + outputFontSize, + outputFontFamily, markupFontSize, editorOptionsCustomizations, interactiveWindowCollapseCodeCells, @@ -514,6 +540,8 @@ 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, }; @@ -530,6 +558,8 @@ 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, }; -- cgit v1.2.3 From fe38a7b3bd41d5f7fe0e29579308f625d68ea170 Mon Sep 17 00:00:00 2001 From: aamunger Date: Tue, 12 Apr 2022 12:46:09 -0700 Subject: line height as ratio when < 8 --- .../notebook/browser/notebook.contribution.ts | 6 ++-- .../notebook/browser/notebookEditorWidget.ts | 2 +- .../contrib/notebook/common/notebookCommon.ts | 2 +- .../contrib/notebook/common/notebookOptions.ts | 42 ++++++++++++++-------- 4 files changed, 32 insertions(+), 20 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index 17c7255ad50..b96059530d4 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts @@ -893,19 +893,19 @@ configurationRegistry.registerConfiguration({ default: 'fromEditor' }, [NotebookSetting.outputLineHeight]: { - markdownDescription: nls.localize('notebook.outputLineHeight', "Line height of the output text"), + 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 plain text outputs. When set to 0 `#editor.fontSize#` is used."), + 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 plain text output of notebook cells. When set to empty, the `#editor.fontFamily#` is used."), + 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/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 15e56226ccd..93bcb157f61 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.fontFamily || e.outputFontFamily || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { + if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { this._styleElement?.remove(); this._createLayoutStyles(); this._webview?.updateOptions({ diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 121ac0689da..5f70d558da1 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -916,7 +916,7 @@ export const NotebookSetting = { interactiveWindowCollapseCodeCells: 'interactiveWindow.collapseCellInputCode', outputLineHeight: 'notebook.outputLineHeight', outputFontSize: 'notebook.outputFontSize', - outputFontFamily: 'notebook.fontFamily' + outputFontFamily: 'notebook.outputFontFamily' } as const; export const enum CellStatusbarAlignment { diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index b7c9b89a926..2964a52df79 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -88,8 +88,6 @@ export interface NotebookOptionsChangeEvent { readonly dragAndDropEnabled?: boolean; readonly fontSize?: boolean; readonly outputFontSize?: boolean; - readonly fontFamily?: boolean; - readonly outputFontFamily?: boolean; readonly markupFontSize?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; @@ -146,7 +144,7 @@ export class NotebookOptions extends Disposable { const markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); const editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells: InteractiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); - const outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + const outputLineHeight = this._computeOutputLineHeight(); this._layoutConfiguration = { ...(compactView ? compactConfigConstants : defaultConfigConstants), @@ -198,6 +196,29 @@ export class NotebookOptions extends Disposable { })); } + private _computeOutputLineHeight(): number { + const minimumLineHeight = 8; + let lineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + + if (lineHeight < minimumLineHeight) { + // Values too small to be line heights in pixels are in ems. + let fontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); + if (fontSize === 0) { + fontSize = this.configurationService.getValue('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); @@ -213,8 +234,6 @@ export class NotebookOptions extends Disposable { const dragAndDropEnabled = e.affectsConfiguration(NotebookSetting.dragAndDropEnabled); const fontSize = e.affectsConfiguration('editor.fontSize'); const outputFontSize = e.affectsConfiguration(NotebookSetting.outputFontSize); - const fontFamily = e.affectsConfiguration('editor.fontFamily'); - const outputFontFamily = e.affectsConfiguration(NotebookSetting.outputFontFamily); const markupFontSize = e.affectsConfiguration(NotebookSetting.markupFontSize); const editorOptionsCustomizations = e.affectsConfiguration(NotebookSetting.cellEditorOptionsCustomizations); const interactiveWindowCollapseCodeCells = e.affectsConfiguration(NotebookSetting.interactiveWindowCollapseCodeCells); @@ -236,8 +255,6 @@ export class NotebookOptions extends Disposable { && !dragAndDropEnabled && !fontSize && !outputFontSize - && !fontFamily - && !outputFontFamily && !markupFontSize && !editorOptionsCustomizations && !interactiveWindowCollapseCodeCells @@ -304,11 +321,7 @@ export class NotebookOptions extends Disposable { } if (outputFontSize) { - configuration.outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize); - } - - if (outputFontFamily) { - configuration.outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); + configuration.outputFontSize = this.configurationService.getValue(NotebookSetting.outputFontSize) ?? configuration.fontSize; } if (markupFontSize) { @@ -323,8 +336,8 @@ export class NotebookOptions extends Disposable { configuration.interactiveWindowCollapseCodeCells = this.configurationService.getValue(NotebookSetting.interactiveWindowCollapseCodeCells); } - if (outputLineHeight) { - configuration.outputLineHeight = this.configurationService.getValue(NotebookSetting.outputLineHeight); + if (outputLineHeight || fontSize || outputFontSize) { + configuration.outputLineHeight = this._computeOutputLineHeight(); } this._layoutConfiguration = Object.freeze(configuration); @@ -346,7 +359,6 @@ export class NotebookOptions extends Disposable { dragAndDropEnabled, fontSize, outputFontSize, - outputFontFamily, markupFontSize, editorOptionsCustomizations, interactiveWindowCollapseCodeCells, -- cgit v1.2.3 From 4e697d42086b7535f90deecce642d4bc7fd8b0e7 Mon Sep 17 00:00:00 2001 From: aamunger Date: Wed, 13 Apr 2022 10:51:23 -0700 Subject: update output style when font family changes --- .../contrib/notebook/browser/notebookEditorWidget.ts | 6 +++++- .../workbench/contrib/notebook/common/notebookOptions.ts | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 93bcb157f61..40712d1eaa3 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -397,7 +397,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD this._updateForNotebookConfiguration(); } - if (e.compactView || e.focusIndicator || e.insertToolbarPosition || e.cellToolbarLocation || e.dragAndDropEnabled || e.fontSize || e.outputFontSize || e.markupFontSize || e.insertToolbarAlignment || e.outputLineHeight) { + 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({ diff --git a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts index 2964a52df79..426871f84fa 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookOptions.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookOptions.ts @@ -89,6 +89,8 @@ export interface NotebookOptionsChangeEvent { readonly fontSize?: boolean; readonly outputFontSize?: boolean; readonly markupFontSize?: boolean; + readonly fontFamily?: boolean; + readonly outputFontFamily?: boolean; readonly editorOptionsCustomizations?: boolean; readonly interactiveWindowCollapseCodeCells?: boolean; readonly outputLineHeight?: boolean; @@ -235,11 +237,12 @@ export class NotebookOptions extends Disposable { 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 && !cellToolbarLocation @@ -256,6 +259,8 @@ export class NotebookOptions extends Disposable { && !fontSize && !outputFontSize && !markupFontSize + && !fontFamily + && !outputFontFamily && !editorOptionsCustomizations && !interactiveWindowCollapseCodeCells && !outputLineHeight) { @@ -328,6 +333,10 @@ export class NotebookOptions extends Disposable { configuration.markupFontSize = this.configurationService.getValue(NotebookSetting.markupFontSize); } + if (outputFontFamily) { + configuration.outputFontFamily = this.configurationService.getValue(NotebookSetting.outputFontFamily); + } + if (editorOptionsCustomizations) { configuration.editorOptionsCustomizations = this.configurationService.getValue(NotebookSetting.cellEditorOptionsCustomizations); } @@ -342,7 +351,6 @@ export class NotebookOptions extends Disposable { this._layoutConfiguration = Object.freeze(configuration); - // add new configuration to the event? // trigger event this._onDidChangeOptions.fire({ cellStatusBarVisibility, @@ -360,6 +368,8 @@ export class NotebookOptions extends Disposable { fontSize, outputFontSize, markupFontSize, + fontFamily, + outputFontFamily, editorOptionsCustomizations, interactiveWindowCollapseCodeCells, outputLineHeight -- cgit v1.2.3 From ce80e8b243df25a530ea10d39970c110e935fa5f Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 13 Apr 2022 14:02:15 -0700 Subject: Fix drag from explorer into notebook --- .../contrib/notebook/browser/view/renderers/backLayerWebView.ts | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/vs/workbench/contrib/notebook') 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 d5ad9679436..f5b40f97620 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -41,6 +41,7 @@ import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKe 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'; @@ -527,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; -- cgit v1.2.3 From b84d1d9d18176572b4eb9f76368bb8204878df08 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 14 Apr 2022 10:48:33 -0700 Subject: Fixing capabilities for drop into - Copy logic into notebook and file editor since they override `capabilities` from `AbstractResourceEditorInput` - Remove unneeded override --- src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index cffd2b0362d..6e28efdd088 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; } -- cgit v1.2.3 From f20a0f2a10769b0c3eb5da43ba75c12ab44d0d43 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 11:10:48 -0700 Subject: extract exthost/mainthread proxy kernels. --- .../notebook/browser/notebookKernelServiceImpl.ts | 28 +--------------------- .../notebook/browser/view/cellParts/cellOutput.ts | 9 ++++--- .../notebook/common/notebookKernelService.ts | 4 ++-- 3 files changed, 7 insertions(+), 34 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts index 09e75953d84..1f2e2e72032 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookKernelServiceImpl.ts @@ -6,7 +6,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { INotebookTextModel } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike, INotebookProxyKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel, ISelectedNotebooksChangeEvent, INotebookKernelMatchResult, INotebookKernelService, INotebookTextModelLike } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { LRUCache, ResourceMap } from 'vs/base/common/map'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { URI } from 'vs/base/common/uri'; @@ -164,32 +164,6 @@ export class NotebookKernelService extends Disposable implements INotebookKernel }); } - registerProxyKernel(kernel: INotebookProxyKernel): IDisposable { - if (this._kernels.has(kernel.id)) { - throw new Error(`NOTEBOOK CONTROLLER with id '${kernel.id}' already exists`); - } - - this._kernels.set(kernel.id, new KernelInfo(kernel)); - this._onDidAddKernel.fire(kernel); - - // auto associate the new kernel to existing notebooks it was - // associated to in the past. - for (const notebook of this._notebookService.getNotebookTextModels()) { - this._tryAutoBindNotebook(notebook, kernel); - } - - return toDisposable(() => { - if (this._kernels.delete(kernel.id)) { - this._onDidRemoveKernel.fire(kernel); - } - for (const [key, candidate] of Array.from(this._notebookBindings)) { - if (candidate === kernel.id) { - this._onDidChangeNotebookKernelBinding.fire({ notebook: NotebookTextModelLikeId.obj(key).uri, oldKernel: kernel.id, newKernel: undefined }); - } - } - }); - } - getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult { // all applicable kernels diff --git a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts index 7ed12d9bb09..7306836ac30 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellOutput.ts @@ -31,7 +31,7 @@ import { CodeCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/vi import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { CellUri, IOrderedMimeType, NotebookCellOutputsSplice, RENDERER_NOT_AVAILABLE } from 'vs/workbench/contrib/notebook/common/notebookCommon'; -import { INotebookKernel, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; @@ -127,8 +127,7 @@ export class CellOutputElement extends Disposable { this.notebookEditor.hasModel() && this.innerContainer && this.renderResult && - this.renderResult.type === RenderOutputType.Extension && - this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved + this.renderResult.type === RenderOutputType.Extension ) { // Output rendered by extension renderer got an update const [mimeTypes, pick] = this.output.resolveMimeTypes(this.notebookEditor.textModel, this.notebookEditor.activeKernel?.preloadProvides); @@ -192,7 +191,7 @@ export class CellOutputElement extends Disposable { const notebookTextModel = this.notebookEditor.textModel; - const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.type === NotebookKernelType.Resolved ? this.notebookEditor.activeKernel?.preloadProvides : undefined); + const [mimeTypes, pick] = this.output.resolveMimeTypes(notebookTextModel, this.notebookEditor.activeKernel?.preloadProvides); if (!mimeTypes.find(mimeType => mimeType.isTrusted) || mimeTypes.length === 0) { this.viewCell.updateOutputHeight(index, 0, 'CellOutputElement#noMimeType'); @@ -300,7 +299,7 @@ export class CellOutputElement extends Disposable { } private async _pickActiveMimeTypeRenderer(outputItemDiv: HTMLElement, notebookTextModel: NotebookTextModel, kernel: INotebookKernel | undefined, viewModel: ICellOutputViewModel) { - const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.type === NotebookKernelType.Resolved ? kernel?.preloadProvides : undefined); + const [mimeTypes, currIndex] = viewModel.resolveMimeTypes(notebookTextModel, kernel?.preloadProvides); const items: IMimeTypeRenderer[] = []; const unsupportedItems: IMimeTypeRenderer[] = []; diff --git a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts index 19ee2cf2b66..4f5304600b0 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookKernelService.ts @@ -74,6 +74,7 @@ export interface INotebookProxyKernel { readonly id: string; readonly viewType: string; readonly extension: ExtensionIdentifier; + readonly preloadProvides: string[]; readonly onDidChange: Event>; label: string; description?: string; @@ -98,8 +99,7 @@ export interface INotebookKernelService { readonly onDidChangeSelectedNotebooks: Event; readonly onDidChangeNotebookAffinity: Event; - registerKernel(kernel: IResolvedNotebookKernel): IDisposable; - registerProxyKernel(proxyKernel: INotebookProxyKernel): IDisposable; + registerKernel(kernel: INotebookKernel): IDisposable; getMatchingKernel(notebook: INotebookTextModelLike): INotebookKernelMatchResult; -- cgit v1.2.3 From 280050dba576740f0350245409d147aa2c84aa94 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 11:19:50 -0700 Subject: :lipstick: --- .../workbench/contrib/notebook/browser/notebookEditorWidget.ts | 10 +--------- .../notebook/browser/viewParts/notebookKernelActionViewItem.ts | 6 +++--- 2 files changed, 4 insertions(+), 12 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 96912b1f10c..40712d1eaa3 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -76,7 +76,7 @@ import { CellKind, INotebookSearchOptions, SelectionStateType } from 'vs/workben import { NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/common/notebookContextKeys'; import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/notebookExecutionService'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; -import { INotebookKernelService, NotebookKernelType } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; +import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService'; import { NotebookOptions, OutputInnerContainerTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions'; import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance'; import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange'; @@ -2112,14 +2112,6 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD return; } const { selected } = this.notebookKernelService.getMatchingKernel(this.textModel); - if (!selected) { - return; - } - - if (selected.type === NotebookKernelType.Proxy) { - return; - } - if (!this._webview?.isResolved()) { await this._resolveWebview(); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index 41e1ec74773..a4060aaa62e 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -6,14 +6,14 @@ 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, ProxyKernelState } 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'; -import { DisposableStore } from 'vs/base/common/lifecycle'; export class NotebooKernelActionViewItem extends ActionViewItem { @@ -77,7 +77,7 @@ export class NotebooKernelActionViewItem extends ActionViewItem { // special UI for selected kernel? } - if ('resolveKernel' in selectedOrSuggested) { + if (selectedOrSuggested.type === NotebookKernelType.Proxy) { if (selectedOrSuggested.connectionState === ProxyKernelState.Initializing) { this._action.label = localize('initializing', "Initializing..."); } else { -- cgit v1.2.3 From 3c9c0e36cd536805b8d376d1f1e09b6db0c53522 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 6 Apr 2022 10:39:47 -0700 Subject: Use SELECT_KERNEL_ID other than string literal --- .../notebook/browser/contrib/editorStatusBar/editorStatusBar.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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..83b35ce916d 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/editorStatusBar/editorStatusBar.ts @@ -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, @@ -381,7 +381,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 +399,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution { command: SELECT_KERNEL_ID, backgroundColor: { id: 'statusBarItem.prominentBackground' } }, - '_notebook.selectKernel', + SELECT_KERNEL_ID, StatusbarAlignment.RIGHT, 10 )); -- cgit v1.2.3 From 9fe5271dac26ed9ebdf6b2ae24016d8cfb8aa9fc Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 11:46:04 -0700 Subject: tweak install from marketplace entry on kernel quickpick. --- .../contrib/editorStatusBar/editorStatusBar.ts | 22 ++++++++++------------ .../browser/view/renderers/backLayerWebView.ts | 6 +++--- 2 files changed, 13 insertions(+), 15 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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 c93c6b17ba2..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'; @@ -182,12 +182,7 @@ registerAction2(class extends Action2 { return res; } const quickPickItems: QuickPickInput[] = []; - 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({ @@ -197,11 +192,6 @@ registerAction2(class extends Action2 { quickPickItems.push(...suggestions.map(toQuickPick)); } - quickPickItems.push({ - id: 'install', - label: nls.localize('installKernels', "Install kernels from the marketplace"), - }); - // Next display all of the kernels grouped by categories or extensions. // If we don't have a kind, always display those at the bottom. const picks = all.filter(item => !suggestions.includes(item)).map(toQuickPick); @@ -215,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 })) 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 f7a64b5b596..a7145c9ffc9 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -904,7 +904,7 @@ var requirejs = (function() { } this._preloadsCache.clear(); - if (this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved) { + if (this._currentKernel?.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(this._currentKernel); } @@ -1401,7 +1401,7 @@ var requirejs = (function() { const previousKernel = this._currentKernel; this._currentKernel = kernel; - if (previousKernel && previousKernel.type === NotebookKernelType.Resolved && 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?.type === NotebookKernelType.Resolved) { this._updatePreloadsFromKernel(kernel); @@ -1434,7 +1434,7 @@ var requirejs = (function() { const mixedResourceRoots = [ ...(this.localResourceRootsCache || []), - ...(this._currentKernel && this._currentKernel.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []), + ...(this._currentKernel?.type === NotebookKernelType.Resolved ? [this._currentKernel.localResourceRoot] : []), ]; this.webview.localResourcesRoot = mixedResourceRoots; -- cgit v1.2.3 From 7195f05a16a5e92147354c4ebfd040b1eb60d162 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 14 Apr 2022 12:05:38 -0700 Subject: allow notebook cancel execution with proxy kernel. --- .../browser/notebookExecutionServiceImpl.ts | 25 ++++++++++++++++------ .../viewParts/notebookKernelActionViewItem.ts | 3 +-- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookExecutionServiceImpl.ts index b8877a553a2..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'; @@ -14,8 +16,9 @@ import { INotebookExecutionService } from 'vs/workbench/contrib/notebook/common/ import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; 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, @@ -46,9 +49,10 @@ export class NotebookExecutionService implements INotebookExecutionService { } if (kernel.type === NotebookKernelType.Proxy) { - // we should actually resolve the kernel + this._activeProxyKernelExecutionToken?.dispose(true); + const tokenSource = this._activeProxyKernelExecutionToken = new CancellationTokenSource(); const resolved = await kernel.resolveKernel(notebook.uri); - let kernels = this._notebookKernelService.getMatchingKernel(notebook); + const kernels = this._notebookKernelService.getMatchingKernel(notebook); const newlyMatchedKernel = kernels.all.find(k => k.id === resolved); if (!newlyMatchedKernel) { @@ -56,6 +60,11 @@ export class NotebookExecutionService implements INotebookExecutionService { } 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) { @@ -93,15 +102,19 @@ export class NotebookExecutionService implements INotebookExecutionService { const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(notebook); if (kernel) { if (kernel.type === NotebookKernelType.Proxy) { - // we should handle cancelling proxy kernel too - return; + this._activeProxyKernelExecutionToken?.dispose(true); + } else { + await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr); } - await kernel.cancelNotebookCellExecution(notebook.uri, cellsArr); } } async cancelNotebookCells(notebook: INotebookTextModel, cells: Iterable): Promise { this.cancelNotebookCellHandles(notebook, Array.from(cells, cell => cell.handle)); } + + dispose() { + this._activeProxyKernelExecutionToken?.dispose(true); + } } diff --git a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index a4060aaa62e..ed9098ad49d 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -68,7 +68,7 @@ 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 && !('resolveKernel' in info.suggestions[0])) ? info.suggestions[0] : undefined); + const selectedOrSuggested = info.selected ?? ((info.all.length === 1 && 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; @@ -94,7 +94,6 @@ export class NotebooKernelActionViewItem extends ActionViewItem { } })); } - } else { // many kernels or no kernels this._action.label = localize('select', "Select Kernel"); -- cgit v1.2.3 From 07e2a4e3f2908a5cad417d57e6ce9b3831d6955e Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 18 Apr 2022 15:02:49 -0700 Subject: Fix exec order indicator position when statusbar hidden. Fix #147333 --- .../workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') 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 eb6e260ec10..469e7cbef3d 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/cellParts/cellExecution.ts @@ -63,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`; } } } -- cgit v1.2.3 From 08f9528d33e01abaa21ff558330a3c6d4d268185 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Tue, 19 Apr 2022 16:03:44 -0700 Subject: Add 'notebookCellResource' context key. Fix #146686 --- .../notebook/browser/view/cellParts/cellContextKeys.ts | 11 +++++++---- .../workbench/contrib/notebook/common/notebookContextKeys.ts | 2 ++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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; private cellOutputCollapsed!: IContextKey; private cellLineNumbers!: IContextKey<'on' | 'off' | 'inherit'>; + private cellResource!: IContextKey; private markdownEditMode!: IContextKey; @@ -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/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('notebookCellE export const NOTEBOOK_CELL_HAS_OUTPUTS = new RawContextKey('notebookCellHasOutputs', false); export const NOTEBOOK_CELL_INPUT_COLLAPSED = new RawContextKey('notebookCellInputIsCollapsed', false); export const NOTEBOOK_CELL_OUTPUT_COLLAPSED = new RawContextKey('notebookCellOutputIsCollapsed', false); +export const NOTEBOOK_CELL_RESOURCE = new RawContextKey('notebookCellResource', ''); + // Kernels export const NOTEBOOK_KERNEL = new RawContextKey('notebookKernel', undefined); export const NOTEBOOK_KERNEL_COUNT = new RawContextKey('notebookKernelCount', 0); -- cgit v1.2.3 From e0a3f8d33a46ca752d043be329a1543a98003613 Mon Sep 17 00:00:00 2001 From: aamunger Date: Wed, 20 Apr 2022 10:57:38 -0700 Subject: use css selector that includes IW scrollbar --- src/vs/workbench/contrib/notebook/browser/media/notebook.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') 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; } -- cgit v1.2.3 From bd95a8d4516d590256eefecfce465a2f10e8f5e5 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Wed, 20 Apr 2022 20:38:20 -0700 Subject: Implement language detection for notebook cells (#147537) * Implement language detection for notebook cells * Add lightbulb for normal text editors as well Clean up mapping of language id's in neural model Add config to opt out of language detection hints --- .../contrib/cellStatusBar/statusBarProviders.ts | 74 +++++++++++++++++++++- .../notebook/browser/controller/editActions.ts | 66 +++++++++++++------ .../contrib/notebook/browser/notebookBrowser.ts | 1 + 3 files changed, 122 insertions(+), 19 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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..3747a011ae7 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts @@ -3,18 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Delayer } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Disposable } from 'vs/base/common/lifecycle'; 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,72 @@ class CellStatusBarLanguagePickerProvider implements INotebookCellStatusBarItemP } } +class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarItemProvider { + + readonly viewType = '*'; + + private delayer = new Delayer(500); + + 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 { + return await this.delayer.trigger(async () => { + const doc = this._notebookService.getNotebookTextModel(uri); + const cell = doc?.cells[index]; + if (!cell || token.isCancellationRequested) { + 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); + + const kernel = this._notebookKernelService.getMatchingKernel(doc); + const items: INotebookCellStatusBarItem[] = []; + + if (kernel.selected) { + const availableLangs = []; + availableLangs.push(...kernel.selected.supportedLanguages, 'markdown'); + const detectedLanguageId = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); + + if (detectedLanguageId && currentLanguageId !== detectedLanguageId) { + const detectedName = this._languageService.getLanguageName(detectedLanguageId) || detectedLanguageId; + 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 +129,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/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index 588675f6403..27a1c5b7c21 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -21,12 +21,13 @@ 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'; const CLEAR_ALL_CELLS_OUTPUTS_COMMAND_ID = 'notebook.clearAllCellsOutputs'; const EDIT_CELL_COMMAND_ID = 'notebook.cell.edit'; @@ -437,23 +438,7 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction undefined, undefined, true - ); - } + await setCellToLanguage(languageId, context); } /** @@ -478,3 +463,48 @@ registerAction2(class ChangeCellLanguageAction extends NotebookCellAction { + const languageDetectionService = accessor.get(ILanguageDetectionService); + const notificationService = accessor.get(INotificationService); + const providerLanguages = [...context.notebookEditor.activeKernel?.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/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 7153bcfe26c..34c9a2afe21 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -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'; -- cgit v1.2.3 From e4d0a1ff061ca8bc23c4459d6b38318354ba517b Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 21 Apr 2022 15:30:33 -0700 Subject: Support indexed base cell options. --- .../contrib/notebook/browser/notebookBrowser.ts | 3 ++- .../notebook/browser/notebookEditorWidget.ts | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 34c9a2afe21..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'; @@ -281,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; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 40712d1eaa3..942f49772ca 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1220,8 +1220,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); @@ -1274,6 +1274,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); -- cgit v1.2.3 From 7135a30a635810e6745c33a97af2d3164d6f05bd Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 22 Apr 2022 16:20:39 -0700 Subject: Open the notebook editor find widget when opening a notebook from search results #95275 --- .../browser/contrib/find/findController.ts | 452 --------------------- .../notebook/browser/contrib/find/findModel.ts | 18 +- .../notebook/browser/contrib/find/notebookFind.ts | 135 ++++++ .../contrib/find/notebookFindReplaceWidget.ts | 6 +- .../browser/contrib/find/notebookFindWidget.ts | 353 ++++++++++++++++ .../notebook/browser/notebook.contribution.ts | 2 +- .../notebook/test/browser/contrib/find.test.ts | 38 +- 7 files changed, 524 insertions(+), 480 deletions(-) delete mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts create mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts create mode 100644 src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts deleted file mode 100644 index 662b1929a2e..00000000000 --- a/src/vs/workbench/contrib/notebook/browser/contrib/find/findController.ts +++ /dev/null @@ -1,452 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * 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 { alert as alertFn } from 'vs/base/browser/ui/aria/aria'; -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 { 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 { 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'; - -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 class NotebookFindWidget extends SimpleFindReplaceWidget implements INotebookEditorContribution { - static id: string = 'workbench.notebook.find'; - protected _findWidgetFocused: IContextKey; - private _showTimeout: number | null = null; - private _hideTimeout: number | null = null; - private _previousFocusElement?: HTMLElement; - private _findModel: FindModel; - - constructor( - private readonly _notebookEditor: INotebookEditor, - @IContextViewService contextViewService: IContextViewService, - @IContextKeyService contextKeyService: IContextKeyService, - @IThemeService themeService: IThemeService, - @IConfigurationService configurationService: IConfigurationService, - @IContextMenuService contextMenuService: IContextMenuService, - @IMenuService menuService: IMenuService, - @IInstantiationService instantiationService: IInstantiationService, - ) { - super(contextViewService, contextKeyService, themeService, configurationService, menuService, contextMenuService, instantiationService, new FindReplaceState()); - this._findModel = new FindModel(this._notebookEditor, this._state, this._configurationService); - - DOM.append(this._notebookEditor.getDomNode(), this.getDomNode()); - this._findWidgetFocused = KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED.bindTo(contextKeyService); - this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e))); - this.updateTheme(themeService.getColorTheme()); - this._register(themeService.onDidColorThemeChange(() => { - this.updateTheme(themeService.getColorTheme()); - })); - - this._register(this._state.onFindReplaceStateChange((e) => { - this.onInputChanged(); - - if (e.isSearching) { - if (this._state.isSearching) { - this._progressBar.infinite().show(PROGRESS_BAR_DELAY); - } else { - this._progressBar.stop().hide(); - } - } - - if (this._findModel.currentMatch >= 0) { - const currentMatch = this._findModel.getCurrentMatch(); - this._replaceBtn.setEnabled(currentMatch.isModelMatch); - } - - const matches = this._findModel.findMatches; - this._replaceAllBtn.setEnabled(matches.length > 0 && matches.find(match => match.modelMatchCount < match.matches.length) === undefined); - - if (e.filters) { - this._findInput.updateFilterState((this._state.filters?.markupPreview ?? false) || (this._state.filters?.codeOutput ?? false)); - } - })); - - this._register(DOM.addDisposableListener(this.getDomNode(), DOM.EventType.FOCUS, e => { - this._previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; - }, true)); - } - - - private _onFindInputKeyDown(e: IKeyboardEvent): void { - if (e.equals(KeyCode.Enter)) { - this._findModel.find(false); - e.preventDefault(); - return; - } else if (e.equals(KeyMod.Shift | KeyCode.Enter)) { - this.find(true); - e.preventDefault(); - return; - } - } - - protected onInputChanged(): boolean { - this._state.change({ searchString: this.inputValue }, false); - // this._findModel.research(); - const findMatches = this._findModel.findMatches; - if (findMatches && findMatches.length) { - return true; - } - - return false; - } - - protected find(previous: boolean): void { - this._findModel.find(previous); - } - - protected replaceOne() { - if (!this._notebookEditor.hasModel()) { - return; - } - - if (!this._findModel.findMatches.length) { - return; - } - - this._findModel.ensureFindMatches(); - - if (this._findModel.currentMatch < 0) { - this._findModel.find(false); - } - - const currentMatch = this._findModel.getCurrentMatch(); - const cell = currentMatch.cell; - if (currentMatch.isModelMatch) { - const match = currentMatch.match as FindMatch; - - this._progressBar.infinite().show(PROGRESS_BAR_DELAY); - - const replacePattern = this.replacePattern; - const replaceString = replacePattern.buildReplaceString(match.matches, this._state.preserveCase); - - const viewModel = this._notebookEditor._getViewModel(); - viewModel.replaceOne(cell, match.range, replaceString).then(() => { - this._progressBar.stop(); - }); - } else { - // this should not work - console.error('Replace does not work for output match'); - } - } - - protected replaceAll() { - if (!this._notebookEditor.hasModel()) { - return; - } - - this._progressBar.infinite().show(PROGRESS_BAR_DELAY); - - const replacePattern = this.replacePattern; - - const cellFindMatches = this._findModel.findMatches; - const replaceStrings: string[] = []; - cellFindMatches.forEach(cellFindMatch => { - const findMatches = cellFindMatch.matches; - findMatches.forEach((findMatch, index) => { - if (index < cellFindMatch.modelMatchCount) { - const match = findMatch as FindMatch; - const matches = match.matches; - replaceStrings.push(replacePattern.buildReplaceString(matches, this._state.preserveCase)); - } - }); - }); - - const viewModel = this._notebookEditor._getViewModel(); - viewModel.replaceAll(this._findModel.findMatches, replaceStrings).then(() => { - this._progressBar.stop(); - }); - } - - protected findFirst(): void { } - - protected onFocusTrackerFocus() { - this._findWidgetFocused.set(true); - } - - protected onFocusTrackerBlur() { - this._previousFocusElement = undefined; - this._findWidgetFocused.reset(); - } - - protected onReplaceInputFocusTrackerFocus(): void { - // throw new Error('Method not implemented.'); - } - protected onReplaceInputFocusTrackerBlur(): void { - // throw new Error('Method not implemented.'); - } - - protected onFindInputFocusTrackerFocus(): void { } - protected onFindInputFocusTrackerBlur(): void { } - - override show(initialInput?: string): void { - super.show(initialInput); - this._state.change({ searchString: initialInput ?? '', isRevealed: true }, false); - this._findInput.select(); - - if (this._showTimeout === null) { - if (this._hideTimeout !== null) { - window.clearTimeout(this._hideTimeout); - this._hideTimeout = null; - this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); - } - - this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); - this._showTimeout = window.setTimeout(() => { - this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); - this._showTimeout = null; - }, 200); - } else { - // no op - } - } - - replace(initialFindInput?: string, initialReplaceInput?: string) { - super.showWithReplace(initialFindInput, initialReplaceInput); - this._state.change({ searchString: initialFindInput ?? '', replaceString: initialReplaceInput ?? '', isRevealed: true }, false); - this._replaceInput.select(); - - if (this._showTimeout === null) { - if (this._hideTimeout !== null) { - window.clearTimeout(this._hideTimeout); - this._hideTimeout = null; - this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); - } - - this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); - this._showTimeout = window.setTimeout(() => { - this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); - this._showTimeout = null; - }, 200); - } else { - // no op - } - } - - override hide() { - super.hide(); - this._state.change({ isRevealed: false }, false); - this._findModel.clear(); - this._notebookEditor.findStop(); - this._progressBar.stop(); - - if (this._hideTimeout === null) { - if (this._showTimeout !== null) { - window.clearTimeout(this._showTimeout); - this._showTimeout = null; - this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); - } - this._notebookEditor.addClassName(FIND_HIDE_TRANSITION); - this._hideTimeout = window.setTimeout(() => { - this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); - }, 200); - } else { - // no op - } - - if (this._previousFocusElement && this._previousFocusElement.offsetParent) { - this._previousFocusElement.focus(); - this._previousFocusElement = undefined; - } - - if (this._notebookEditor.hasModel()) { - for (let i = 0; i < this._notebookEditor.getLength(); i++) { - const cell = this._notebookEditor.cellAt(i); - - if (cell.getEditState() === CellEditState.Editing && cell.editStateSource === 'find') { - cell.updateEditState(CellEditState.Preview, 'find'); - } - } - } - } - - override _updateMatchesCount(): void { - if (!this._findModel || !this._findModel.findMatches) { - return; - } - - this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px'; - this._matchesCount.title = ''; - - // remove previous content - if (this._matchesCount.firstChild) { - this._matchesCount.removeChild(this._matchesCount.firstChild); - } - - let label: string; - - if (this._state.matchesCount > 0) { - let matchesCount: string = String(this._state.matchesCount); - if (this._state.matchesCount >= MATCHES_LIMIT) { - matchesCount += '+'; - } - const matchesPosition: string = this._findModel.currentMatch < 0 ? '?' : String((this._findModel.currentMatch + 1)); - label = strings.format(NLS_MATCHES_LOCATION, matchesPosition, matchesCount); - } else { - label = NLS_NO_RESULTS; - } - - this._matchesCount.appendChild(document.createTextNode(label)); - - alertFn(this._getAriaLabel(label, this._state.currentMatch, this._state.searchString)); - MAX_MATCHES_COUNT_WIDTH = Math.max(MAX_MATCHES_COUNT_WIDTH, this._matchesCount.clientWidth); - } - - private _getAriaLabel(label: string, currentMatch: Range | null, searchString: string): string { - if (label === NLS_NO_RESULTS) { - return searchString === '' - ? localize('ariaSearchNoResultEmpty', "{0} found", label) - : localize('ariaSearchNoResult', "{0} found for '{1}'", label, searchString); - } - - // TODO@rebornix, aria for `cell ${index}, line {line}` - return localize('ariaSearchNoResultWithLineNumNoCurrentMatch', "{0} found for '{1}'", label, searchString); - } - override dispose() { - this._notebookEditor?.removeClassName(FIND_SHOW_TRANSITION); - this._notebookEditor?.removeClassName(FIND_HIDE_TRANSITION); - this._findModel.dispose(); - 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 { - const editorService = accessor.get(IEditorService); - const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); - - if (!editor) { - return; - } - - const controller = editor.getContribution(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 { - const editorService = accessor.get(IEditorService); - const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); - - if (!editor) { - return; - } - - const controller = editor.getContribution(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.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.id); - if (controller) { - controller.replace(); - return true; - } - - return false; -}); 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 { + const editorService = accessor.get(IEditorService); + const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); + + if (!editor) { + return; + } + + const controller = editor.getContribution(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 { + const editorService = accessor.get(IEditorService); + const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane); + + if (!editor) { + return; + } + + const controller = editor.getContribution(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.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.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/notebookFindWidget.ts b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts new file mode 100644 index 00000000000..c027d8137d4 --- /dev/null +++ b/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.ts @@ -0,0 +1,353 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +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 { 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 { FindReplaceState } from 'vs/editor/contrib/find/browser/findState'; +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 { SimpleFindReplaceWidget } from 'vs/workbench/contrib/notebook/browser/contrib/find/notebookFindReplaceWidget'; +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; + private _showTimeout: number | null = null; + private _hideTimeout: number | null = null; + private _previousFocusElement?: HTMLElement; + private _findModel: FindModel; + + constructor( + private readonly _notebookEditor: INotebookEditor, + @IContextViewService contextViewService: IContextViewService, + @IContextKeyService contextKeyService: IContextKeyService, + @IThemeService themeService: IThemeService, + @IConfigurationService configurationService: IConfigurationService, + @IContextMenuService contextMenuService: IContextMenuService, + @IMenuService menuService: IMenuService, + @IInstantiationService instantiationService: IInstantiationService, + ) { + super(contextViewService, contextKeyService, themeService, configurationService, menuService, contextMenuService, instantiationService, new FindReplaceState()); + this._findModel = new FindModel(this._notebookEditor, this._state, this._configurationService); + + DOM.append(this._notebookEditor.getDomNode(), this.getDomNode()); + this._findWidgetFocused = KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED.bindTo(contextKeyService); + this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e))); + this.updateTheme(themeService.getColorTheme()); + this._register(themeService.onDidColorThemeChange(() => { + this.updateTheme(themeService.getColorTheme()); + })); + + this._register(this._state.onFindReplaceStateChange((e) => { + this.onInputChanged(); + + if (e.isSearching) { + if (this._state.isSearching) { + this._progressBar.infinite().show(PROGRESS_BAR_DELAY); + } else { + this._progressBar.stop().hide(); + } + } + + if (this._findModel.currentMatch >= 0) { + const currentMatch = this._findModel.getCurrentMatch(); + this._replaceBtn.setEnabled(currentMatch.isModelMatch); + } + + const matches = this._findModel.findMatches; + this._replaceAllBtn.setEnabled(matches.length > 0 && matches.find(match => match.modelMatchCount < match.matches.length) === undefined); + + if (e.filters) { + this._findInput.updateFilterState((this._state.filters?.markupPreview ?? false) || (this._state.filters?.codeOutput ?? false)); + } + })); + + this._register(DOM.addDisposableListener(this.getDomNode(), DOM.EventType.FOCUS, e => { + this._previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; + }, true)); + } + + + private _onFindInputKeyDown(e: IKeyboardEvent): void { + if (e.equals(KeyCode.Enter)) { + this.find(false); + e.preventDefault(); + return; + } else if (e.equals(KeyMod.Shift | KeyCode.Enter)) { + this.find(true); + e.preventDefault(); + return; + } + } + + protected onInputChanged(): boolean { + this._state.change({ searchString: this.inputValue }, false); + // this._findModel.research(); + const findMatches = this._findModel.findMatches; + if (findMatches && findMatches.length) { + return true; + } + + return false; + } + + private findIndex(index: number): void { + this._findModel.find({ index }); + } + + protected find(previous: boolean): void { + this._findModel.find({ previous }); + } + + protected replaceOne() { + if (!this._notebookEditor.hasModel()) { + return; + } + + if (!this._findModel.findMatches.length) { + return; + } + + this._findModel.ensureFindMatches(); + + if (this._findModel.currentMatch < 0) { + this._findModel.find({ previous: false }); + } + + const currentMatch = this._findModel.getCurrentMatch(); + const cell = currentMatch.cell; + if (currentMatch.isModelMatch) { + const match = currentMatch.match as FindMatch; + + this._progressBar.infinite().show(PROGRESS_BAR_DELAY); + + const replacePattern = this.replacePattern; + const replaceString = replacePattern.buildReplaceString(match.matches, this._state.preserveCase); + + const viewModel = this._notebookEditor._getViewModel(); + viewModel.replaceOne(cell, match.range, replaceString).then(() => { + this._progressBar.stop(); + }); + } else { + // this should not work + console.error('Replace does not work for output match'); + } + } + + protected replaceAll() { + if (!this._notebookEditor.hasModel()) { + return; + } + + this._progressBar.infinite().show(PROGRESS_BAR_DELAY); + + const replacePattern = this.replacePattern; + + const cellFindMatches = this._findModel.findMatches; + const replaceStrings: string[] = []; + cellFindMatches.forEach(cellFindMatch => { + const findMatches = cellFindMatch.matches; + findMatches.forEach((findMatch, index) => { + if (index < cellFindMatch.modelMatchCount) { + const match = findMatch as FindMatch; + const matches = match.matches; + replaceStrings.push(replacePattern.buildReplaceString(matches, this._state.preserveCase)); + } + }); + }); + + const viewModel = this._notebookEditor._getViewModel(); + viewModel.replaceAll(this._findModel.findMatches, replaceStrings).then(() => { + this._progressBar.stop(); + }); + } + + protected findFirst(): void { } + + protected onFocusTrackerFocus() { + this._findWidgetFocused.set(true); + } + + protected onFocusTrackerBlur() { + this._previousFocusElement = undefined; + this._findWidgetFocused.reset(); + } + + protected onReplaceInputFocusTrackerFocus(): void { + // throw new Error('Method not implemented.'); + } + protected onReplaceInputFocusTrackerBlur(): void { + // throw new Error('Method not implemented.'); + } + + protected onFindInputFocusTrackerFocus(): void { } + protected onFindInputFocusTrackerBlur(): void { } + + override async show(initialInput?: string, options?: IShowNotebookFindWidgetOptions): Promise { + super.show(initialInput, options); + this._state.change({ searchString: initialInput ?? '', isRevealed: true }, false); + + 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) { + window.clearTimeout(this._hideTimeout); + this._hideTimeout = null; + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + } + + this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); + this._showTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + this._showTimeout = null; + }, 200); + } else { + // no op + } + } + + replace(initialFindInput?: string, initialReplaceInput?: string) { + super.showWithReplace(initialFindInput, initialReplaceInput); + this._state.change({ searchString: initialFindInput ?? '', replaceString: initialReplaceInput ?? '', isRevealed: true }, false); + this._replaceInput.select(); + + if (this._showTimeout === null) { + if (this._hideTimeout !== null) { + window.clearTimeout(this._hideTimeout); + this._hideTimeout = null; + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + } + + this._notebookEditor.addClassName(FIND_SHOW_TRANSITION); + this._showTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + this._showTimeout = null; + }, 200); + } else { + // no op + } + } + + override hide() { + super.hide(); + this._state.change({ isRevealed: false }, false); + this._findModel.clear(); + this._notebookEditor.findStop(); + this._progressBar.stop(); + + if (this._hideTimeout === null) { + if (this._showTimeout !== null) { + window.clearTimeout(this._showTimeout); + this._showTimeout = null; + this._notebookEditor.removeClassName(FIND_SHOW_TRANSITION); + } + this._notebookEditor.addClassName(FIND_HIDE_TRANSITION); + this._hideTimeout = window.setTimeout(() => { + this._notebookEditor.removeClassName(FIND_HIDE_TRANSITION); + }, 200); + } else { + // no op + } + + if (this._previousFocusElement && this._previousFocusElement.offsetParent) { + this._previousFocusElement.focus(); + this._previousFocusElement = undefined; + } + + if (this._notebookEditor.hasModel()) { + for (let i = 0; i < this._notebookEditor.getLength(); i++) { + const cell = this._notebookEditor.cellAt(i); + + if (cell.getEditState() === CellEditState.Editing && cell.editStateSource === 'find') { + cell.updateEditState(CellEditState.Preview, 'find'); + } + } + } + } + + override _updateMatchesCount(): void { + if (!this._findModel || !this._findModel.findMatches) { + return; + } + + this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px'; + this._matchesCount.title = ''; + + // remove previous content + if (this._matchesCount.firstChild) { + this._matchesCount.removeChild(this._matchesCount.firstChild); + } + + let label: string; + + if (this._state.matchesCount > 0) { + let matchesCount: string = String(this._state.matchesCount); + if (this._state.matchesCount >= MATCHES_LIMIT) { + matchesCount += '+'; + } + const matchesPosition: string = this._findModel.currentMatch < 0 ? '?' : String((this._findModel.currentMatch + 1)); + label = strings.format(NLS_MATCHES_LOCATION, matchesPosition, matchesCount); + } else { + label = NLS_NO_RESULTS; + } + + this._matchesCount.appendChild(document.createTextNode(label)); + + alertFn(this._getAriaLabel(label, this._state.currentMatch, this._state.searchString)); + MAX_MATCHES_COUNT_WIDTH = Math.max(MAX_MATCHES_COUNT_WIDTH, this._matchesCount.clientWidth); + } + + private _getAriaLabel(label: string, currentMatch: Range | null, searchString: string): string { + if (label === NLS_NO_RESULTS) { + return searchString === '' + ? localize('ariaSearchNoResultEmpty', "{0} found", label) + : localize('ariaSearchNoResult', "{0} found for '{1}'", label, searchString); + } + + // TODO@rebornix, aria for `cell ${index}, line {line}` + return localize('ariaSearchNoResultWithLineNumNoCurrentMatch', "{0} found for '{1}'", label, searchString); + } + override dispose() { + this._notebookEditor?.removeClassName(FIND_SHOW_TRANSITION); + this._notebookEditor?.removeClassName(FIND_HIDE_TRANSITION); + this._findModel.dispose(); + super.dispose(); + } +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts b/src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts index b96059530d4..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'; 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(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(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(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); -- cgit v1.2.3 From f07b19f5ac4ac4f5df5e67d72a82ccd834cefcae Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 10:24:53 -0700 Subject: Fix #148009 --- src/vs/workbench/contrib/notebook/browser/controller/editActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index 27a1c5b7c21..34cc0e18f85 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -471,7 +471,7 @@ registerAction2(class DetectCellLanguageAction extends NotebookCellAction { title: localize('detectLanguage', 'Accept Detected Language for Cell'), f1: true, precondition: ContextKeyExpr.and(NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_EDITABLE), - keybinding: { primary: KeyCode.KeyE | KeyMod.CtrlCmd, weight: KeybindingWeight.WorkbenchContrib } + keybinding: { primary: KeyCode.KeyD | KeyMod.Alt, weight: KeybindingWeight.WorkbenchContrib } }); } -- cgit v1.2.3 From bab5c223e4be43578b082492a12344b41551baac Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 25 Apr 2022 16:57:24 -0700 Subject: Use Alt+Shift+D ref #148009 --- src/vs/workbench/contrib/notebook/browser/controller/editActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index 34cc0e18f85..d684e721add 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -471,7 +471,7 @@ registerAction2(class DetectCellLanguageAction extends NotebookCellAction { 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, weight: KeybindingWeight.WorkbenchContrib } + keybinding: { primary: KeyCode.KeyD | KeyMod.Alt | KeyMod.Shift, weight: KeybindingWeight.WorkbenchContrib } }); } -- cgit v1.2.3 From e70161f75d08e0abc6226cbd4e324c239621d42c Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 14:36:45 -0700 Subject: Allow language guessing to work with suggested kernels in addition to selected --- .../notebook/browser/contrib/cellStatusBar/statusBarProviders.ts | 6 +++--- src/vs/workbench/contrib/notebook/browser/controller/editActions.ts | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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 3747a011ae7..3700db63aa5 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts @@ -88,12 +88,12 @@ class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarIt 'markdown' : (this._languageService.getLanguageIdByLanguageName(cell.language) || cell.language); - const kernel = this._notebookKernelService.getMatchingKernel(doc); + const kernel = this._notebookKernelService.getSelectedOrSuggestedKernel(doc); const items: INotebookCellStatusBarItem[] = []; - if (kernel.selected) { + if (kernel) { const availableLangs = []; - availableLangs.push(...kernel.selected.supportedLanguages, 'markdown'); + availableLangs.push(...kernel.supportedLanguages, 'markdown'); const detectedLanguageId = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); if (detectedLanguageId && currentLanguageId !== detectedLanguageId) { diff --git a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts index d684e721add..8d253828d2e 100644 --- a/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/controller/editActions.ts @@ -28,6 +28,7 @@ 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'; @@ -478,7 +479,9 @@ registerAction2(class DetectCellLanguageAction extends NotebookCellAction { async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise { const languageDetectionService = accessor.get(ILanguageDetectionService); const notificationService = accessor.get(INotificationService); - const providerLanguages = [...context.notebookEditor.activeKernel?.supportedLanguages ?? []]; + 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) { -- cgit v1.2.3 From ac3e081e0ecbee16961053cc2713489e70332650 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Tue, 26 Apr 2022 16:00:51 -0700 Subject: Improve debouncing logic to immediately react to language changes Fixes #148196 --- .../contrib/cellStatusBar/statusBarProviders.ts | 84 ++++++++++++---------- 1 file changed, 46 insertions(+), 38 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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 3700db63aa5..750af12fdf4 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/statusBarProviders.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Delayer } from 'vs/base/common/async'; 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'; @@ -59,7 +59,11 @@ class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarIt readonly viewType = '*'; - private delayer = new Delayer(500); + private cache = new ResourceMap<{ + lastUpdate: number; + lastCellLang: string; + lastGuess?: string; + }>(); constructor( @INotebookService private readonly _notebookService: INotebookService, @@ -71,53 +75,57 @@ class CellStatusBarLanguageDetectionProvider implements INotebookCellStatusBarIt ) { } async provideCellStatusBarItems(uri: URI, index: number, token: CancellationToken): Promise { - return await this.delayer.trigger(async () => { - const doc = this._notebookService.getNotebookTextModel(uri); - const cell = doc?.cells[index]; - if (!cell || token.isCancellationRequested) { - return; - } + 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 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); + 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); - const items: INotebookCellStatusBarItem[] = []; if (kernel) { const availableLangs = []; availableLangs.push(...kernel.supportedLanguages, 'markdown'); - const detectedLanguageId = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); - - if (detectedLanguageId && currentLanguageId !== detectedLanguageId) { - const detectedName = this._languageService.getLanguageName(detectedLanguageId) || detectedLanguageId; - 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 - }); - } + cached.lastGuess = await this._languageDetectionService.detectLanguage(cell.uri, availableLangs); } + } - return { items }; - }); + 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 }; } } -- cgit v1.2.3 From 8632e9c4096eab5773958b9fb3f45f92efba74a8 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 28 Apr 2022 16:04:03 -0700 Subject: fix #148258. --- .../contrib/notebook/browser/notebookEditorWidget.ts | 5 +++++ .../contrib/notebook/browser/view/cellParts/codeCell.ts | 13 +++++++++++-- .../contrib/notebook/browser/view/cellParts/markdownCell.ts | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 942f49772ca..5f76bc5718f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1824,6 +1824,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/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 b7652ba37ca..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(); } -- cgit v1.2.3 From b0a0e7ec37df52bf2dddbcb5b1892933ad707867 Mon Sep 17 00:00:00 2001 From: Johannes Date: Mon, 2 May 2022 15:51:11 +0200 Subject: debt - use Action2 instead of spread out calls to registries --- .../contrib/notebook/browser/controller/layoutActions.ts | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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({ -- cgit v1.2.3 From 2785ac4f7117d8cd3086ffd5ac13628963d712c7 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Mon, 2 May 2022 10:07:25 -0700 Subject: fix #147603. Enable selecting line on line number. (#148459) --- src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts | 1 - 1 file changed, 1 deletion(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 5f76bc5718f..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, -- cgit v1.2.3 From 57479a5f6be520ada8517ecbbca6a982b1f80ff3 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Mon, 2 May 2022 12:34:13 -0700 Subject: Always suggest the only preferred kernel. (#148576) --- .../contrib/notebook/browser/notebookKernelServiceImpl.ts | 11 ++++++++++- .../browser/viewParts/notebookKernelActionViewItem.ts | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') 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/viewParts/notebookKernelActionViewItem.ts b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts index ed9098ad49d..e5814ce98ec 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelActionViewItem.ts @@ -68,7 +68,7 @@ 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].type === NotebookKernelType.Resolved) ? 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; -- cgit v1.2.3 From 322ee9dc4119f48648b1951009db63eedfeb4495 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 3 May 2022 16:16:15 +0200 Subject: return untyped editor input from saveAs (#148614) --- .../workbench/contrib/notebook/common/notebookCommon.ts | 5 ++--- .../contrib/notebook/common/notebookEditorInput.ts | 4 ++-- .../contrib/notebook/common/notebookEditorModel.ts | 15 +++++---------- .../notebook/test/browser/notebookEditorModel.test.ts | 6 ++---- 4 files changed, 11 insertions(+), 19 deletions(-) (limited to 'src/vs/workbench/contrib/notebook') diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 5f70d558da1..40b6b6a2074 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'; @@ -780,7 +779,7 @@ export interface INotebookEditorModel extends IEditorModel { hasAssociatedFilePath(): boolean; load(options?: INotebookLoadOptions): Promise; save(options?: ISaveOptions): Promise; - saveAs(target: URI): Promise; + saveAs(target: URI): Promise; revert(options?: IRevertOptions): Promise; } diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts index 6e28efdd088..b8cbd4985d0 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorInput.ts @@ -124,7 +124,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return this._editorModelReference.object.isDirty(); } - override async save(group: GroupIdentifier, options?: ISaveOptions): Promise { + override async save(group: GroupIdentifier, options?: ISaveOptions): Promise { if (this._editorModelReference) { if (this.hasCapability(EditorInputCapabilities.Untitled)) { @@ -139,7 +139,7 @@ export class NotebookEditorInput extends AbstractResourceEditorInput { return undefined; } - override async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { + override async saveAs(group: GroupIdentifier, options?: ISaveOptions): Promise { 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 { + async saveAs(targetResource: URI): Promise { 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, - @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 { + async saveAs(target: URI): Promise { 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 | IUntitledFileWorkingCopy): candidate is IStoredFileWorkingCopy { 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() { }; const backupService = new class extends mock() { }; const notificationService = new class extends mock() { }; @@ -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); -- cgit v1.2.3