Merge branch 'notebook/dev' into main

This commit is contained in:
Johannes Rieken 2021-05-31 19:43:49 +02:00
commit 0a1046ada4
No known key found for this signature in database
GPG key ID: 96634B5AF12F8798
28 changed files with 1427 additions and 1244 deletions

View file

@ -1,196 +1,101 @@
# Query: todo@API
# Flags: WordMatch OpenEditors
# Including: */vscode.proposed.d.ts
# Including: */vscode.d.ts
# ContextLines: 1
56 results - 1 file
29 results - 1 file
src/vs/vscode.proposed.d.ts:
1098 */
1099: // todo@API should this be called `notebookType` or `notebookKind`
1100 readonly viewType: string;
src/vs/vscode.d.ts:
11374 /** @deprecated */
11375: // todo@API remove
11376 readonly viewType: string;
1159
1160: // todo@API jsdoc
1161 export class NotebookCellMetadata {
11440
11441: // todo@API jsdoc
11442 export class NotebookCellMetadata {
1165 */
1166: // todo@API decouple from metadata? extract as dedicated field or inside an options object and leave metadata purely for extensions?
1167 readonly inputCollapsed?: boolean;
11446 */
11447: // todo@API decouple from metadata? extract as dedicated field or inside an options object and leave metadata purely for extensions?
11448 readonly inputCollapsed?: boolean;
1171 */
1172: // todo@API decouple from metadata? extract as dedicated field or inside an options object and leave metadata purely for extensions?
1173 readonly outputCollapsed?: boolean;
11452 */
11453: // todo@API decouple from metadata? extract as dedicated field or inside an options object and leave metadata purely for extensions?
11454 readonly outputCollapsed?: boolean;
1215 */
1216: // todo@API use duration instead of start/end?
1217 readonly startTime?: number;
11496 */
11497: // todo@API use duration instead of start/end?
11498 readonly startTime?: number;
1224
1225: // todo@API jsdoc
1226: // todo@API remove this and use simple {}?
1227 export class NotebookDocumentMetadata {
11505
11506: // todo@API jsdoc
11507: // todo@API remove this and use simple {}?
11508 export class NotebookDocumentMetadata {
1290 */
1291: // todo@API document which mime types are supported out of the box and
1292 // which are considered secure
11644
11645: //todo@API remove in favour of NotebookCellOutput#metadata
11646 metadata?: { [key: string]: any };
1365
1366: //todo@API remove in favour of NotebookCellOutput#metadata
1367 metadata?: { [key: string]: any };
11662 */
11663: //todo@API - add sugar function to add more outputs
11664 export class NotebookCellOutput {
1383 */
1384: //todo@API - add sugar function to add more outputs
1385 export class NotebookCellOutput {
11689 */
11690: //todo@API have this OR NotebookCellOutputItem#metadata but not both? Preference for this.
11691 metadata?: { [key: string]: any };
1407
1408: //todo@API have this OR NotebookCellOutputItem#metadata but not both? Preference for this.
1409 metadata?: { [key: string]: any };
11753 * @param languageId The language identifier of the source value.
11754: * @param outputs //TODO@API remove from ctor?
11755: * @param metadata //TODO@API remove from ctor?
11756: * @param executionSummary //TODO@API remove from ctor?
11757 */
1471 * @param languageId The language identifier of the source value.
1472: * @param outputs //TODO@API remove from ctor?
1473: * @param metadata //TODO@API remove from ctor?
1474: * @param executionSummary //TODO@API remove from ctor?
1475 */
11840 */
11841: // todo@API ...NotebookDocument... or just ...Notebook... just like...Cell... above
11842 transientDocumentMetadata?: { [K in keyof NotebookDocumentMetadata]?: boolean };
1558 */
1559: // todo@API ...NotebookDocument... or just ...Notebook... just like...Cell... above
1560 transientDocumentMetadata?: { [K in keyof NotebookDocumentMetadata]?: boolean };
11847 */
11848: //todo@API inline?
11849 export interface NotebookExecuteHandler {
1617
1618: // todo@api jsdoc
1619: // todo@api Inline unless we can come up with more (future) properties
1620 export interface NotebookCellExecuteStartContext {
11895
11896: // todo@api remove
11897 /** @deprecated */
1627
1628: // todo@api jsdoc
1629: // todo@api Inline unless we can come up with more (future) properties
1630 export interface NotebookCellExecuteEndContext {
11942
11943: // todo@API remove
11944 /** @deprecated */
1634 */
1635: // todo@api undefined === false, so by default cells execution fails?
1636 success?: boolean;
12003
12004: // todo@api jsdoc
12005: // todo@api Inline unless we can come up with more (future) properties
12006 export interface NotebookCellExecuteStartContext {
1672
1673: // todo@API inline context object?
1674 start(context?: NotebookCellExecuteStartContext): void;
1675
1676: // todo@API inline context object?
1677 end(result?: NotebookCellExecuteEndContext): void;
12013
12014: // todo@api jsdoc
12015: // todo@api Inline unless we can come up with more (future) properties
12016 export interface NotebookCellExecuteEndContext {
1751 */
1752: // todo@api rename to notebookType?
1753 readonly viewType: string;
12058
12059: // todo@API inline context object?
12060 start(context?: NotebookCellExecuteStartContext): void;
12061
12062: // todo@API inline context object?
12063 end(result?: NotebookCellExecuteEndContext): void;
1790 */
1791: // todo@API rename to supportsExecutionOrder, usesExecutionOrder
1792 hasExecutionOrder?: boolean;
12145 */
12146: //todo@API only have Command?
12147 command?: string | Command;
1849
1850: // todo@API allow add, not remove
1851 readonly rendererScripts: NotebookRendererScript[];
12166 */
12167: // todo@API jsdoc for args
12168: // todo@API should ctors only have the args for required properties?
12169 constructor(text: string, alignment: NotebookCellStatusBarAlignment, command?: string | Command, tooltip?: string, priority?: number, accessibilityInformation?: AccessibilityInformation);
1870
1871: //todo@API validate this works
1872 asWebviewUri(localResource: Uri): Uri;
12185 */
12186: //todo@API jsdoc for return-type
12187: //todo@API should this return an item instead of an array?
12188 provideCellStatusBarItems(cell: NotebookCell, token: CancellationToken): ProviderResult<NotebookCellStatusBarItem[]>;
1899 */
1900: // todo@api remove? use cell.notebook instead?
1901 readonly document: NotebookDocument;
1910 */
1911: // todo@API rename to state?
1912 readonly executionState: NotebookCellExecutionState;
1930
1931: // todo@api jsdoc
1932 export class NotebookCellStatusBarItem {
1942
1943: // todo@api jsdoc
1944 export interface NotebookCellStatusBarItemProvider {
1952 */
1953: // todo@API rename to ...NotebookCell...
1954 provideCellStatusBarItems(cell: NotebookCell, token: CancellationToken): ProviderResult<NotebookCellStatusBarItem[]>;
1965 */
1966: // todo@api rename to notebooks?
1967: // todo@api what should be in this namespace? should notebookDocuments and friends be in the workspace namespace?
1968 export namespace notebook {
2035 * @param handler
2036: * @param rendererScripts todo@API should renderer scripts come later?
2037 */
2042 */
2043: // todo@API this is an event that is fired for a property that cells don't have and that makes me wonder
2044 // how a correct consumer work, e.g the consumer could have been late and missed an event?
2046
2047: // todo@api jsdoc
2048 export function registerNotebookCellStatusBarItemProvider(notebookType: string, provider: NotebookCellStatusBarItemProvider): Disposable;
2118 readonly start: number;
2119: // todo@API end? Use NotebookCellRange instead?
2120 readonly deletedCount: number;
2121: // todo@API removedCells, deletedCells?
2122 readonly deletedItems: NotebookCell[];
2123: // todo@API addedCells, insertedCells, newCells?
2124 readonly items: NotebookCell[];
2183
2184: // todo@API add onDidChangeNotebookCellOutputs
2185 export const onDidChangeCellOutputs: Event<NotebookCellOutputsChangeEvent>;
2186
2187: // todo@API add onDidChangeNotebookCellMetadata
2188 export const onDidChangeCellMetadata: Event<NotebookCellMetadataChangeEvent>;
2206
2207: // todo@API add NotebookEdit-type which handles all these cases?
2208 // export class NotebookEdit {
2223 export interface WorkspaceEdit {
2224: // todo@API add NotebookEdit-type which handles all these cases?
2225 replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void;
2285 */
2286: // todo@API really needed? we didn't find a user here
2287 export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument;
2339
2340: // todo@API use openNotebookDOCUMENT to align with openCustomDocument etc?
2341: // todo@API rename to NotebookDocumentContentProvider
2342 export interface NotebookContentProvider {
2352
2353: // todo@API use NotebookData instead
2354 saveNotebook(document: NotebookDocument, token: CancellationToken): Thenable<void>;
2355
2356: // todo@API use NotebookData instead
2357 saveNotebookAs(targetResource: Uri, document: NotebookDocument, token: CancellationToken): Thenable<void>;
2358
2359: // todo@API use NotebookData instead
2360 backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, token: CancellationToken): Thenable<NotebookDocumentBackup>;
2364
2365: // TODO@api use NotebookDocumentFilter instead of just notebookType:string?
2366: // TODO@API options duplicates the more powerful variant on NotebookContentProvider
2367 export function registerNotebookContentProvider(notebookType: string, provider: NotebookContentProvider, options?: NotebookDocumentContentOptions): Disposable;
2647
2648: // todo@API Split between Inlay- and OverlayHints (InlayHint are for a position, OverlayHints for a non-empty range)
2649: // todo@API add "mini-markdown" for links and styles
2650 // (done) remove description
2699
2700: // todo@API make range first argument
2701 constructor(text: string, position: Position, kind?: InlayHintKind);
3564
3565: // TODO@API must be a class
3566 export interface OpenEditorInfo {
3574
3575: // todo@API proper event type
3576 export const onDidChangeOpenEditors: Event<void>;
12199 */
12200: // todo@api what should be in this namespace? should notebookDocuments and friends be in the workspace namespace?
12201 export namespace notebooks {

View file

@ -859,12 +859,12 @@ suite('Notebook API tests', function () {
const p = new Promise<void>(r => resolve = r);
const listener = vscode.notebook.onDidChangeNotebookCellExecutionState(e => {
if (eventCount === 0) {
assert.strictEqual(e.executionState, vscode.NotebookCellExecutionState.Pending, 'should be set to Pending');
assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Pending, 'should be set to Pending');
} else if (eventCount === 1) {
assert.strictEqual(e.executionState, vscode.NotebookCellExecutionState.Executing, 'should be set to Executing');
assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Executing, 'should be set to Executing');
assert.strictEqual(cell.outputs.length, 0, 'no outputs yet: ' + JSON.stringify(cell.outputs[0]));
} else if (eventCount === 2) {
assert.strictEqual(e.executionState, vscode.NotebookCellExecutionState.Idle, 'should be set to Idle');
assert.strictEqual(e.state, vscode.NotebookCellExecutionState.Idle, 'should be set to Idle');
assert.strictEqual(cell.outputs.length, 1, 'should have an output');
resolve();
}

992
src/vs/vscode.d.ts vendored

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,7 @@ abstract class MainThreadKernel implements INotebookKernel {
constructor(data: INotebookKernelDto2, private _modeService: IModeService) {
this.id = data.id;
this.viewType = data.viewType;
this.viewType = data.notebookType;
this.extension = data.extensionId;
this.implementsInterrupt = data.supportsInterrupt ?? false;
@ -52,7 +52,7 @@ abstract class MainThreadKernel implements INotebookKernel {
this.description = data.description;
this.detail = data.detail;
this.supportedLanguages = isNonEmptyArray(data.supportedLanguages) ? data.supportedLanguages : _modeService.getRegisteredModes();
this.implementsExecutionOrder = data.hasExecutionOrder ?? false;
this.implementsExecutionOrder = data.supportsExecutionOrder ?? false;
this.localResourceRoot = URI.revive(data.extensionLocation);
this.preloads = data.preloads?.map(u => ({ uri: URI.revive(u.uri), provides: u.provides })) ?? [];
}
@ -77,8 +77,8 @@ abstract class MainThreadKernel implements INotebookKernel {
this.supportedLanguages = isNonEmptyArray(data.supportedLanguages) ? data.supportedLanguages : this._modeService.getRegisteredModes();
event.supportedLanguages = true;
}
if (data.hasExecutionOrder !== undefined) {
this.implementsExecutionOrder = data.hasExecutionOrder;
if (data.supportsExecutionOrder !== undefined) {
this.implementsExecutionOrder = data.supportsExecutionOrder;
event.hasExecutionOrder = true;
}
this._onDidChange.fire(event);

View file

@ -1054,48 +1054,45 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
};
// namespace: notebook
const notebook: typeof vscode.notebook = {
async openNotebookDocument(uriOrOptions?: URI | string, content?: vscode.NotebookData) {
checkProposedApiEnabled(extension);
const notebooks: typeof vscode.notebooks = {
get notebookDocuments(): vscode.NotebookDocument[] {
return extHostNotebook.notebookDocuments.map(d => d.apiNotebook);
},
async openNotebookDocument(uriOrType?: URI | string, content?: vscode.NotebookData) {
let uri: URI;
if (URI.isUri(uriOrOptions)) {
uri = uriOrOptions;
await extHostNotebook.openNotebookDocument(uriOrOptions);
} else if (typeof uriOrOptions === 'string') {
uri = URI.revive(await extHostNotebook.createNotebookDocument({ viewType: uriOrOptions, content }));
if (URI.isUri(uriOrType)) {
uri = uriOrType;
await extHostNotebook.openNotebookDocument(uriOrType);
} else if (typeof uriOrType === 'string') {
uri = URI.revive(await extHostNotebook.createNotebookDocument({ viewType: uriOrType, content }));
} else {
throw new Error('Invalid arguments');
}
return extHostNotebook.getNotebookDocument(uri).apiNotebook;
},
get onDidOpenNotebookDocument(): Event<vscode.NotebookDocument> {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidOpenNotebookDocument;
},
get onDidCloseNotebookDocument(): Event<vscode.NotebookDocument> {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidCloseNotebookDocument;
},
registerNotebookSerializer(viewType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) {
return extHostNotebook.registerNotebookSerializer(extension, viewType, serializer, options, extension.enableProposedApi ? registration : undefined);
},
createNotebookController(id: string, notebookType: string, label: string, handler?: vscode.NotebookExecuteHandler, rendererScripts?: vscode.NotebookRendererScript[]) {
return extHostNotebookKernels.createNotebookController(extension, id, notebookType, label, handler, extension.enableProposedApi ? rendererScripts : undefined);
},
registerNotebookCellStatusBarItemProvider: (notebookType: string, provider: vscode.NotebookCellStatusBarItemProvider) => {
return extHostNotebook.registerNotebookCellStatusBarItemProvider(extension, notebookType, provider);
},
get onDidSaveNotebookDocument(): Event<vscode.NotebookDocument> {
checkProposedApiEnabled(extension);
return extHostNotebook.onDidSaveNotebookDocument;
},
get notebookDocuments(): vscode.NotebookDocument[] {
checkProposedApiEnabled(extension);
return extHostNotebook.notebookDocuments.map(d => d.apiNotebook);
},
registerNotebookSerializer(viewType: string, serializer: vscode.NotebookSerializer, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookSerializer(extension, viewType, serializer, options, extension.enableProposedApi ? registration : undefined);
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider, options?: vscode.NotebookDocumentContentOptions, registration?: vscode.NotebookRegistrationData) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider, options, extension.enableProposedApi ? registration : undefined);
},
registerNotebookCellStatusBarItemProvider: (notebookType: string, provider: vscode.NotebookCellStatusBarItemProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookCellStatusBarItemProvider(extension, notebookType, provider);
},
createNotebookEditorDecorationType(options: vscode.NotebookDecorationRenderOptions): vscode.NotebookEditorDecorationType {
checkProposedApiEnabled(extension);
return extHostNotebook.createNotebookEditorDecorationType(options);
@ -1128,10 +1125,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return new ExtHostNotebookConcatDocument(extHostNotebook, extHostDocuments, notebook, selector);
},
createNotebookController(id, viewType, label, executeHandler, preloads) {
checkProposedApiEnabled(extension);
return extHostNotebookKernels.createNotebookController(extension, id, viewType, label, executeHandler, preloads);
}
};
return <typeof vscode>{
@ -1144,7 +1137,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
env,
extensions,
languages,
notebook,
notebooks,
notebook: notebooks, //todo@jrieken remove after grace
scm,
tasks,
test,

View file

@ -907,7 +907,7 @@ export interface MainThreadNotebookDocumentsShape extends IDisposable {
export interface INotebookKernelDto2 {
id: string;
viewType: string;
notebookType: string;
extensionId: ExtensionIdentifier;
extensionLocation: UriComponents;
label: string;
@ -915,7 +915,7 @@ export interface INotebookKernelDto2 {
description?: string;
supportedLanguages?: string[];
supportsInterrupt?: boolean;
hasExecutionOrder?: boolean;
supportsExecutionOrder?: boolean;
preloads?: { uri: UriComponents; provides: string[] }[];
}

View file

@ -144,7 +144,7 @@ export class ExtHostNotebookDocument {
private readonly _textDocumentsAndEditors: ExtHostDocumentsAndEditors,
private readonly _textDocuments: ExtHostDocuments,
private readonly _emitter: INotebookEventEmitter,
private readonly _viewType: string,
private readonly _notebookType: string,
private _metadata: extHostTypes.NotebookDocumentMetadata,
readonly uri: URI,
) { }
@ -159,7 +159,8 @@ export class ExtHostNotebookDocument {
this._notebook = {
get uri() { return that.uri; },
get version() { return that._versionId; },
get viewType() { return that._viewType; },
get viewType() { return that._notebookType; },
get notebookType() { return that._notebookType; },
get isDirty() { return that._isDirty; },
get isUntitled() { return that.uri.scheme === Schemas.untitled; },
get isClosed() { return that._disposed; },
@ -356,7 +357,7 @@ export class ExtHostNotebookDocument {
if (originalInternalMetadata.runState !== newInternalMetadata.runState) {
const executionState = newInternalMetadata.runState ?? extHostTypes.NotebookCellExecutionState.Idle;
this._emitter.emitCellExecutionStateChange(deepFreeze({ document: this.apiNotebook, cell: cell.apiCell, executionState }));
this._emitter.emitCellExecutionStateChange(deepFreeze({ document: this.apiNotebook, cell: cell.apiCell, state: executionState }));
}
}

View file

@ -21,6 +21,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { asArray } from 'vs/base/common/arrays';
import { ILogService } from 'vs/platform/log/common/log';
import { NotebookCellOutput } from 'vs/workbench/api/common/extHostTypes';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
interface IKernelData {
extensionId: ExtensionIdentifier,
@ -71,7 +72,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
const data: INotebookKernelDto2 = {
id: `${extension.identifier.value}/${id}`,
viewType,
notebookType: viewType,
extensionId: extension.identifier,
extensionLocation: extension.extensionLocation,
label: label || extension.identifier.value,
@ -110,7 +111,8 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
const controller: vscode.NotebookController = {
get id() { return id; },
get viewType() { return data.viewType; },
get viewType() { return data.notebookType; },
get notebookType() { return data.notebookType; },
onDidChangeNotebookAssociation: onDidChangeSelection.event,
get label() {
return data.label;
@ -141,10 +143,17 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
_update();
},
get hasExecutionOrder() {
return data.hasExecutionOrder ?? false;
return data.supportsExecutionOrder ?? false;
},
set hasExecutionOrder(value) {
data.hasExecutionOrder = value;
data.supportsExecutionOrder = value;
_update();
},
get supportsExecutionOrder() {
return data.supportsExecutionOrder ?? false;
},
set supportsExecutionOrder(value) {
data.supportsExecutionOrder = value;
_update();
},
get rendererScripts() {
@ -185,18 +194,20 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
this._proxy.$removeKernel(handle);
}
},
// --- ipc
onDidReceiveMessage: onDidReceiveMessage.event,
postMessage(message, editor) {
return that._proxy.$postMessage(handle, editor && that._extHostNotebook.getIdByEditor(editor), message);
},
asWebviewUri(uri: URI) {
return asWebviewUri(uri, that._initData.remote);
},
// --- priority
updateNotebookAffinity(notebook, priority) {
that._proxy.$updateNotebookPriority(handle, notebook.uri, priority);
}
},
// --- ipc
onDidReceiveMessage: onDidReceiveMessage.event,
postMessage(message, editor) {
checkProposedApiEnabled(extension);
return that._proxy.$postMessage(handle, editor && that._extHostNotebook.getIdByEditor(editor), message);
},
asWebviewUri(uri: URI) {
checkProposedApiEnabled(extension);
return asWebviewUri(uri, that._initData.remote);
},
};
this._kernelData.set(handle, {

View file

@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Registry } from 'vs/platform/registry/common/platform';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { Memento } from 'vs/workbench/common/memento';
import { HAS_OPENED_NOTEBOOK } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
const hasOpenedNotebookKey = 'hasOpenedNotebook';
/**
* Sets a context key when a notebook has ever been opened by the user
*/
export class NotebookGettingStarted extends Disposable implements IWorkbenchContribution {
constructor(
@IEditorService _editorService: IEditorService,
@IStorageService _storageService: IStorageService,
@IContextKeyService _contextKeyService: IContextKeyService,
@ICommandService _commandService: ICommandService,
@IConfigurationService _configurationService: IConfigurationService,
) {
super();
const hasOpenedNotebook = HAS_OPENED_NOTEBOOK.bindTo(_contextKeyService);
const memento = new Memento('notebookGettingStarted', _storageService);
const storedValue = memento.getMemento(StorageScope.GLOBAL, StorageTarget.USER);
if (storedValue[hasOpenedNotebookKey]) {
hasOpenedNotebook.set(true);
} else {
const listener = this._register(_editorService.onDidActiveEditorChange(() => {
if (_editorService.activeEditor?.typeId === NotebookEditorInput.ID) {
hasOpenedNotebook.set(true);
storedValue[hasOpenedNotebookKey] = true;
memento.saveMemento();
listener.dispose();
if (_configurationService.getValue('notebook.experimental.openGettingStarted')) {
_commandService.executeCommand('workbench.action.openWalkthrough', { category: 'Setup', step: 'notebookProfile' }, true);
}
}
}));
}
}
}
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(NotebookGettingStarted, LifecyclePhase.Restored);

View file

@ -8,7 +8,7 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { INotebookActionContext, NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import { CellToolbarLocKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellToolbarLocation } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const TOGGLE_CELL_TOOLBAR_POSITION = 'notebook.toggleCellToolbarPosition';
@ -33,9 +33,9 @@ export class ToggleCellToolbarPositionAction extends Action2 {
// from toolbar
const viewType = editor.viewModel.viewType;
const configurationService = accessor.get(IConfigurationService);
const toolbarPosition = configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocKey);
const toolbarPosition = configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocation);
const newConfig = this.togglePosition(viewType, toolbarPosition);
await configurationService.updateValue(CellToolbarLocKey, newConfig);
await configurationService.updateValue(CellToolbarLocation, newConfig);
}
}

View file

@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { localize } from 'vs/nls';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CellToolbarLocation, CompactView, FocusIndicator, GlobalToolbar, InsertToolbarPosition, ShowCellStatusBarAfterExecuteKey, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
export enum NotebookProfileType {
default = 'default',
jupyter = 'jupyter',
colab = 'colab'
}
const profiles = {
[NotebookProfileType.default]: {
[FocusIndicator]: 'border',
[InsertToolbarPosition]: 'both',
[GlobalToolbar]: false,
[CellToolbarLocation]: { default: 'right' },
[CompactView]: true,
[ShowCellStatusBarKey]: true,
[ShowCellStatusBarAfterExecuteKey]: false,
},
[NotebookProfileType.jupyter]: {
[FocusIndicator]: 'gutter',
[InsertToolbarPosition]: 'notebookToolbar',
[GlobalToolbar]: true,
[CellToolbarLocation]: { default: 'left' },
[CompactView]: true,
[ShowCellStatusBarKey]: true,
},
[NotebookProfileType.colab]: {
[FocusIndicator]: 'border',
[InsertToolbarPosition]: 'betweenCells',
[GlobalToolbar]: false,
[CellToolbarLocation]: { default: 'right' },
[CompactView]: false,
[ShowCellStatusBarKey]: false,
}
};
async function applyProfile(accessor: ServicesAccessor, profile: Record<string, any>): Promise<void> {
const configService = accessor.get(IConfigurationService);
const promises = [];
for (let settingKey in profile) {
promises.push(configService.updateValue(settingKey, profile[settingKey]));
}
await Promise.all(promises);
}
export interface ISetProfileArgs {
profile: NotebookProfileType;
}
registerAction2(class extends Action2 {
constructor() {
super({
id: 'notebook.setProfile',
title: localize('setProfileTitle', "Set Profile")
});
}
async run(accessor: ServicesAccessor, args: unknown): Promise<void> {
if (!isSetProfileArgs(args)) {
return;
}
return applyProfile(accessor, profiles[args.profile]);
}
});
function isSetProfileArgs(args: unknown): args is ISetProfileArgs {
const setProfileArgs = args as ISetProfileArgs;
return setProfileArgs.profile === NotebookProfileType.colab ||
setProfileArgs.profile === NotebookProfileType.default ||
setProfileArgs.profile === NotebookProfileType.jupyter;
}

View file

@ -9,6 +9,8 @@ import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/exte
import { NotebookEditorPriority, NotebookRendererEntrypoint } from 'vs/workbench/contrib/notebook/common/notebookCommon';
namespace NotebookEditorContribution {
export const type = 'type';
/** @deprecated use type */
export const viewType = 'viewType';
export const displayName = 'displayName';
export const selector = 'selector';
@ -16,6 +18,8 @@ namespace NotebookEditorContribution {
}
export interface INotebookEditorContribution {
readonly [NotebookEditorContribution.type]: string;
/** @deprecated use type */
readonly [NotebookEditorContribution.viewType]: string;
readonly [NotebookEditorContribution.displayName]: string;
readonly [NotebookEditorContribution.selector]?: readonly { filenamePattern?: string; excludeFileNamePattern?: string; }[];
@ -23,6 +27,7 @@ export interface INotebookEditorContribution {
}
namespace NotebookRendererContribution {
/** @deprecated use type */
export const viewType = 'viewType';
export const id = 'id';
export const displayName = 'displayName';
@ -35,6 +40,7 @@ namespace NotebookRendererContribution {
export interface INotebookRendererContribution {
readonly [NotebookRendererContribution.id]?: string;
/** @deprecated use type */
readonly [NotebookRendererContribution.viewType]?: string;
readonly [NotebookRendererContribution.displayName]: string;
readonly [NotebookRendererContribution.mimeTypes]?: readonly string[];
@ -47,17 +53,22 @@ export interface INotebookRendererContribution {
const notebookProviderContribution: IJSONSchema = {
description: nls.localize('contributes.notebook.provider', 'Contributes notebook document provider.'),
type: 'array',
defaultSnippets: [{ body: [{ viewType: '', displayName: '', 'selector': [{ 'filenamePattern': '' }] }] }],
defaultSnippets: [{ body: [{ type: '', displayName: '', 'selector': [{ 'filenamePattern': '' }] }] }],
items: {
type: 'object',
required: [
NotebookEditorContribution.viewType,
NotebookEditorContribution.type,
NotebookEditorContribution.displayName,
NotebookEditorContribution.selector,
],
properties: {
[NotebookEditorContribution.type]: {
type: 'string',
description: nls.localize('contributes.notebook.provider.viewType', 'Unique identifier of the notebook.'),
},
[NotebookEditorContribution.viewType]: {
type: 'string',
deprecationMessage: nls.localize('contributes.notebook.provider.viewType.deprecated', 'Rename `viewType` to `id`.'),
description: nls.localize('contributes.notebook.provider.viewType', 'Unique identifier of the notebook.'),
},
[NotebookEditorContribution.displayName]: {

View file

@ -30,7 +30,7 @@ import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEd
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { NotebookService } from 'vs/workbench/contrib/notebook/browser/notebookServiceImpl';
import { CellKind, CellToolbarLocKey, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled, ShowCellStatusBarAfterExecuteKey, NotebookCellEditorOptionsCustomizations, ConsolidatedRunButton } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellKind, CellToolbarLocation, CellToolbarVisibility, CellUri, DisplayOrderKey, UndoRedoPerCell, ExperimentalUseMarkdownRenderer, getCellUndoRedoComparisonKey, IResolvedNotebookEditorModel, NotebookDocumentBackupData, NotebookTextDiffEditorPreview, NotebookWorkingCopyTypeIdentifier, ShowCellStatusBarKey, CompactView, FocusIndicator, InsertToolbarPosition, GlobalToolbar, ConsolidatedOutputButton, ShowFoldingControls, DragAndDropEnabled, ShowCellStatusBarAfterExecuteKey, NotebookCellEditorOptionsCustomizations, ConsolidatedRunButton } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
@ -66,10 +66,12 @@ import 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
import 'vs/workbench/contrib/notebook/browser/contrib/find/findController';
import 'vs/workbench/contrib/notebook/browser/contrib/fold/folding';
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';
import 'vs/workbench/contrib/notebook/browser/contrib/marker/markerProvider';
import 'vs/workbench/contrib/notebook/browser/contrib/navigation/arrow';
import 'vs/workbench/contrib/notebook/browser/contrib/outline/notebookOutline';
import 'vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile';
import 'vs/workbench/contrib/notebook/browser/contrib/statusBar/statusBarProviders';
import 'vs/workbench/contrib/notebook/browser/contrib/statusBar/contributedStatusBarItemController';
import 'vs/workbench/contrib/notebook/browser/contrib/statusBar/executionStatusBarItemController';
@ -602,7 +604,7 @@ configurationRegistry.registerConfiguration({
},
default: []
},
[CellToolbarLocKey]: {
[CellToolbarLocation]: {
description: nls.localize('notebook.cellToolbarLocation.description', "Where the cell toolbar should be shown, or whether it should be hidden."),
type: 'object',
additionalProperties: {
@ -622,7 +624,7 @@ configurationRegistry.registerConfiguration({
tags: ['notebookLayout']
},
[ShowCellStatusBarAfterExecuteKey]: {
description: nls.localize('notebook.showCellStatusbarAfterExecute.description', "Whether the cell status bar should be shown after the cell has been executed."),
description: nls.localize('notebook.showCellStatusbarAfterExecute.description', "Whether the cell status bar should be shown after the cell has been executed. Only has an effect if notebook.showCellStatusBar is false."),
type: 'boolean',
default: false,
tags: ['notebookLayout']

View file

@ -37,6 +37,7 @@ export const NOTEBOOK_EDITOR_ID = 'workbench.editor.notebook';
export const NOTEBOOK_DIFF_EDITOR_ID = 'workbench.editor.notebookTextDiffEditor';
//#region Context Keys
export const HAS_OPENED_NOTEBOOK = new RawContextKey<boolean>('userHasOpenedNotebook', false);
export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('notebookFindWidgetFocused', false);
// Is Notebook

View file

@ -96,7 +96,7 @@ export class NotebookProviderInfoStore extends Disposable {
for (const notebookContribution of extension.value) {
this.add(new NotebookProviderInfo({
extension: extension.description.identifier,
id: notebookContribution.viewType,
id: notebookContribution.type || notebookContribution.viewType,
displayName: notebookContribution.displayName,
selectors: notebookContribution.selector || [],
priority: this._convertPriority(notebookContribution.priority),

View file

@ -905,7 +905,7 @@ export interface INotebookCellStatusBarItemList {
}
export const DisplayOrderKey = 'notebook.displayOrder';
export const CellToolbarLocKey = 'notebook.cellToolbarLocation';
export const CellToolbarLocation = 'notebook.cellToolbarLocation';
export const CellToolbarVisibility = 'notebook.cellToolbarVisibility';
export const ShowCellStatusBarKey = 'notebook.showCellStatusBar';
export const ShowCellStatusBarAfterExecuteKey = 'notebook.showCellStatusBarAfterExecute';
@ -922,6 +922,7 @@ export const ShowFoldingControls = 'notebook.showFoldingControls';
export const DragAndDropEnabled = 'notebook.dragAndDropEnabled';
export const NotebookCellEditorOptionsCustomizations = 'notebook.editorOptionsCustomizations';
export const ConsolidatedRunButton = 'notebook.consolidatedRunButton';
export const OpenGettingStarted = 'notebook.experimental.openGettingStarted';
export const enum CellStatusbarAlignment {
Left = 1,

View file

@ -6,7 +6,7 @@
import { Emitter } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IConfigurationChangeEvent, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CellToolbarLocKey, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, ConsolidatedRunButton, DragAndDropEnabled, ExperimentalInsertToolbarAlignment, FocusIndicator, GlobalToolbar, InsertToolbarPosition, NotebookCellEditorOptionsCustomizations, ShowCellStatusBarAfterExecuteKey, ShowCellStatusBarKey, ShowFoldingControls } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellToolbarLocation, CellToolbarVisibility, CompactView, ConsolidatedOutputButton, ConsolidatedRunButton, DragAndDropEnabled, ExperimentalInsertToolbarAlignment, FocusIndicator, GlobalToolbar, InsertToolbarPosition, NotebookCellEditorOptionsCustomizations, ShowCellStatusBarAfterExecuteKey, ShowCellStatusBarKey, ShowFoldingControls } from 'vs/workbench/contrib/notebook/common/notebookCommon';
const SCROLLABLE_ELEMENT_PADDING_TOP = 18;
@ -114,7 +114,7 @@ export class NotebookOptions {
const consolidatedOutputButton = this.configurationService.getValue<boolean | undefined>(ConsolidatedOutputButton) ?? true;
const consolidatedRunButton = this.configurationService.getValue<boolean | undefined>(ConsolidatedRunButton) ?? false;
const dragAndDropEnabled = this.configurationService.getValue<boolean | undefined>(DragAndDropEnabled) ?? true;
const cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocKey) ?? { 'default': 'right' };
const cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocation) ?? { 'default': 'right' };
const cellToolbarInteraction = this.configurationService.getValue<string>(CellToolbarVisibility);
const compactView = this.configurationService.getValue<boolean | undefined>(CompactView) ?? true;
const focusIndicator = this._computeFocusIndicatorOption();
@ -173,7 +173,7 @@ export class NotebookOptions {
private _updateConfiguration(e: IConfigurationChangeEvent) {
const cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey);
const cellStatusBarAfterExecuteVisibility = e.affectsConfiguration(ShowCellStatusBarAfterExecuteKey);
const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey);
const cellToolbarLocation = e.affectsConfiguration(CellToolbarLocation);
const cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility);
const compactView = e.affectsConfiguration(CompactView);
const focusIndicator = e.affectsConfiguration(FocusIndicator);
@ -217,7 +217,7 @@ export class NotebookOptions {
}
if (cellToolbarLocation) {
configuration.cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocKey) ?? { 'default': 'right' };
configuration.cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocation) ?? { 'default': 'right' };
}
if (cellToolbarInteraction) {

View file

@ -497,7 +497,9 @@ export class GettingStartedPage extends EditorPane {
const rawHTML = await this.renderMarkdown(media.path, media.base);
webview.html = rawHTML;
const serializedContextKeyExprs = rawHTML.match(/checked-on=\"([^'][^"]*)\"/g)?.map(attr => attr.slice('checked-on="'.length, -1).replace(/&#39;/g, '\''));
const serializedContextKeyExprs = rawHTML.match(/checked-on=\"([^'][^"]*)\"/g)?.map(attr => attr.slice('checked-on="'.length, -1)
.replace(/&#39;/g, '\'')
.replace(/&amp;/g, '&'));
const postTrueKeysMessage = () => {
const enabledContextKeys = serializedContextKeyExprs?.filter(expr => this.contextService.contextMatchesRules(ContextKeyExpr.deserialize(expr)));

View file

@ -261,7 +261,16 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
hc: 'hc/openFolder.png',
}
}
}
},
{
id: 'notebookProfile',
title: localize('gettingStarted.notebookProfile.title', "Customize the look of your notebooks"),
description: localize('gettingStarted.notebookProfile.description', "Get notebooks to feel just the way you prefer"),
when: 'userHasOpenedNotebook',
media: {
type: 'markdown', path: 'notebookProfile'
}
},
]
}
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

View file

@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { escape } from 'vs/base/common/strings';
import { localize } from 'vs/nls';
const profileArg = (profile: string) => encodeURIComponent(JSON.stringify({ profile }));
const imageSize = 400;
export default () => `
&nbsp;
<checklist>
<checkbox on-checked="command:notebook.setProfile?${profileArg('default')}" checked-on="config.notebook.cellFocusIndicator == 'border' && config.notebook.insertToolbarPosition == 'both' && config.notebook.globalToolbar == false && config.notebook.compactView == true && config.notebook.showCellStatusBar == true">
<img width="${imageSize}" src="./notebookThemes/default.png"/>
${escape(localize('default', "Default"))}
</checkbox>
<checkbox on-checked="command:notebook.setProfile?${profileArg('jupyter')}" checked-on="config.notebook.cellFocusIndicator == 'gutter' && config.notebook.insertToolbarPosition == 'notebookToolbar' && config.notebook.globalToolbar == true && config.notebook.compactView == true && config.notebook.showCellStatusBar == true">
<img width="${imageSize}" src="./notebookThemes/jupyter.png"/>
${escape(localize('jupyter', "Jupyter"))}
</checkbox>
<checkbox on-checked="command:notebook.setProfile?${profileArg('colab')}" checked-on="config.notebook.cellFocusIndicator == 'border' && config.notebook.insertToolbarPosition == 'betweenCells' && config.notebook.globalToolbar == false && config.notebook.compactView == false && config.notebook.showCellStatusBar == false">
<img width="${imageSize}" src="./notebookThemes/colab.png"/>
${escape(localize('colab', "Colab"))}
</checkbox>
</checklist>
`;

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -138,7 +138,7 @@ suite('NotebookKernel', function () {
assert.strictEqual(first.id, 'nullExtensionDescription/foo');
assert.strictEqual(ExtensionIdentifier.equals(first.extensionId, nullExtensionDescription.identifier), true);
assert.strictEqual(first.label, 'Foo');
assert.strictEqual(first.viewType, '*');
assert.strictEqual(first.notebookType, '*');
kernel.dispose();
await rpcProtocol.sync();