mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-08 07:44:33 +01:00
Merge remote-tracking branch 'origin/main' into tyriar/getprofilesexthost
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-js-debug repo:microsoft/vscode-remote-release repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-remotehub\n\n$MILESTONE=milestone:\"April 2021\""
|
||||
"value": "$REPOS=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-js-debug repo:microsoft/vscode-remote-release repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-remotehub\n\n$MILESTONE=milestone:\"May 2021\""
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
},
|
||||
"contributes": {
|
||||
"notebookMarkupRenderers": [
|
||||
"notebookOutputRenderer": [
|
||||
{
|
||||
"id": "markdownItRenderer",
|
||||
"displayName": "Markdown it renderer",
|
||||
|
||||
@@ -21,18 +21,28 @@
|
||||
}
|
||||
},
|
||||
"contributes": {
|
||||
"notebookMarkupRenderers": [
|
||||
"notebookOutputRenderer": [
|
||||
{
|
||||
"id": "markdownItRenderer-katex",
|
||||
"displayName": "Markdown it katex renderer",
|
||||
"entrypoint": "./notebook-out/katex.js",
|
||||
"dependsOn": "markdownItRenderer"
|
||||
"mimeTypes": [
|
||||
"text/markdown"
|
||||
],
|
||||
"dependencies": [
|
||||
"markdownItRenderer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "markdownItRenderer-emoji",
|
||||
"displayName": "Markdown it emoji renderer",
|
||||
"entrypoint": "./notebook-out/emoji.js",
|
||||
"dependsOn": "markdownItRenderer"
|
||||
"mimeTypes": [
|
||||
"text/markdown"
|
||||
],
|
||||
"dependencies": [
|
||||
"markdownItRenderer"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"notebookProvider": [
|
||||
"notebooks": [
|
||||
{
|
||||
"viewType": "notebookCoreTest",
|
||||
"displayName": "Notebook Core Test",
|
||||
|
||||
@@ -40,9 +40,7 @@ suite('Notebook Editor', function () {
|
||||
});
|
||||
|
||||
|
||||
test.skip('showNotebookDocment', async function () {
|
||||
|
||||
const count1 = vscode.notebook.notebookDocuments.length;
|
||||
test('showNotebookDocment', async function () {
|
||||
|
||||
const p = utils.asPromise(vscode.notebook.onDidOpenNotebookDocument);
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
@@ -53,9 +51,8 @@ suite('Notebook Editor', function () {
|
||||
const event = await p;
|
||||
assert.strictEqual(event.uri.toString(), uri.toString());
|
||||
|
||||
const count2 = vscode.notebook.notebookDocuments.length;
|
||||
assert.strictEqual(count1 + 1, count2);
|
||||
|
||||
const includes = vscode.notebook.notebookDocuments.includes(editor.document);
|
||||
assert.strictEqual(true, includes);
|
||||
});
|
||||
|
||||
test('notebook editor has viewColumn', async function () {
|
||||
|
||||
@@ -121,7 +121,7 @@ suite('Notebook API tests', function () {
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
outputs: [],
|
||||
metadata: new vscode.NotebookCellMetadata().with({ custom: { testCellMetadata: 123 } }),
|
||||
latestExecutionSummary: { startTime: 10, endTime: 20 }
|
||||
executionSummary: { startTime: 10, endTime: 20 }
|
||||
},
|
||||
{
|
||||
value: 'test2',
|
||||
@@ -133,7 +133,7 @@ suite('Notebook API tests', function () {
|
||||
],
|
||||
{ testOutputMetadata: true })
|
||||
],
|
||||
latestExecutionSummary: { executionOrder: 5, success: true },
|
||||
executionSummary: { executionOrder: 5, success: true },
|
||||
metadata: new vscode.NotebookCellMetadata().with({ custom: { testCellMetadata: 456 } })
|
||||
}
|
||||
]
|
||||
@@ -478,8 +478,8 @@ suite('Notebook API tests', function () {
|
||||
assert.strictEqual(secondCell!.outputs[0].outputs[0].mime, 'text/plain');
|
||||
assert.strictEqual(secondCell!.outputs[0].outputs[0].value, 'Hello World');
|
||||
assert.deepStrictEqual(secondCell!.outputs[0].outputs[0].metadata, { testOutputItemMetadata: true });
|
||||
assert.strictEqual(secondCell!.latestExecutionSummary?.executionOrder, 5);
|
||||
assert.strictEqual(secondCell!.latestExecutionSummary?.success, true);
|
||||
assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5);
|
||||
assert.strictEqual(secondCell!.executionSummary?.success, true);
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
|
||||
@@ -1205,30 +1205,30 @@ suite('Notebook API tests', function () {
|
||||
verifyOutputSyncKernel.controller.dispose();
|
||||
});
|
||||
|
||||
test('latestExecutionSummary', async () => {
|
||||
test('executionSummary', async () => {
|
||||
const resource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
const editor = vscode.window.activeNotebookEditor!;
|
||||
const cell = editor.document.cellAt(0);
|
||||
|
||||
assert.strictEqual(cell.latestExecutionSummary?.success, undefined);
|
||||
assert.strictEqual(cell.latestExecutionSummary?.executionOrder, undefined);
|
||||
assert.strictEqual(cell.executionSummary?.success, undefined);
|
||||
assert.strictEqual(cell.executionSummary?.executionOrder, undefined);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute');
|
||||
assert.ok(cell.latestExecutionSummary);
|
||||
assert.strictEqual(cell.latestExecutionSummary!.success, true);
|
||||
assert.strictEqual(typeof cell.latestExecutionSummary!.executionOrder, 'number');
|
||||
assert.ok(cell.executionSummary);
|
||||
assert.strictEqual(cell.executionSummary!.success, true);
|
||||
assert.strictEqual(typeof cell.executionSummary!.executionOrder, 'number');
|
||||
|
||||
});
|
||||
|
||||
test('initialize latestExecutionSummary', async () => {
|
||||
test('initialize executionSummary', async () => {
|
||||
|
||||
const document = await openRandomNotebookDocument();
|
||||
const cell = document.cellAt(0);
|
||||
|
||||
assert.strictEqual(cell.latestExecutionSummary?.success, undefined);
|
||||
assert.strictEqual(cell.latestExecutionSummary?.startTime, 10);
|
||||
assert.strictEqual(cell.latestExecutionSummary?.endTime, 20);
|
||||
assert.strictEqual(cell.executionSummary?.success, undefined);
|
||||
assert.strictEqual(cell.executionSummary?.startTime, 10);
|
||||
assert.strictEqual(cell.executionSummary?.endTime, 20);
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"icon": "$(debug)"
|
||||
}
|
||||
],
|
||||
"notebookProvider": [
|
||||
"notebooks": [
|
||||
{
|
||||
"viewType": "notebookSmokeTest",
|
||||
"displayName": "Notebook Smoke Test",
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.57.0",
|
||||
"distro": "5a7e0f9786abefbe5c166898c7cb71537b3d651e",
|
||||
"distro": "d4088d7fa3ad4446065d4cec45d90d02d04fe745",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
+40
-14
@@ -1179,28 +1179,44 @@ export function computeScreenAwareSize(cssPx: number): number {
|
||||
}
|
||||
|
||||
/**
|
||||
* Open safely a new window. This is the best way to do so, but you cannot tell
|
||||
* if the window was opened or if it was blocked by the brower's popup blocker.
|
||||
* If you want to tell if the browser blocked the new window, use `windowOpenNoOpenerWithSuccess`.
|
||||
*
|
||||
* See https://github.com/microsoft/monaco-editor/issues/601
|
||||
* To protect against malicious code in the linked site, particularly phishing attempts,
|
||||
* the window.opener should be set to null to prevent the linked site from having access
|
||||
* to change the location of the current page.
|
||||
* See https://mathiasbynens.github.io/rel-noopener/
|
||||
*/
|
||||
export function windowOpenNoOpener(url: string): boolean {
|
||||
if (browser.isElectron || browser.isEdgeLegacyWebView) {
|
||||
// In VSCode, window.open() always returns null...
|
||||
// The same is true for a WebView (see https://github.com/microsoft/monaco-editor/issues/628)
|
||||
// Also call directly window.open in sandboxed Electron (see https://github.com/microsoft/monaco-editor/issues/2220)
|
||||
window.open(url);
|
||||
export function windowOpenNoOpener(url: string): void {
|
||||
// By using 'noopener' in the `windowFeatures` argument, the newly created window will
|
||||
// not be able to use `window.opener` to reach back to the current page.
|
||||
// See https://stackoverflow.com/a/46958731
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener
|
||||
// However, this also doesn't allow us to realize if the browser blocked
|
||||
// the creation of the window.
|
||||
window.open(url, '_blank', 'noopener');
|
||||
}
|
||||
|
||||
/**
|
||||
* Open safely a new window. This technique is not appropiate in certain contexts,
|
||||
* like for example when the JS context is executing inside a sandboxed iframe.
|
||||
* If it is not necessary to know if the browser blocked the new window, use
|
||||
* `windowOpenNoOpener`.
|
||||
*
|
||||
* See https://github.com/microsoft/monaco-editor/issues/601
|
||||
* See https://github.com/microsoft/monaco-editor/issues/2474
|
||||
* See https://mathiasbynens.github.io/rel-noopener/
|
||||
*/
|
||||
export function windowOpenNoOpenerWithSuccess(url: string): boolean {
|
||||
const newTab = window.open();
|
||||
if (newTab) {
|
||||
(newTab as any).opener = null;
|
||||
newTab.location.href = url;
|
||||
return true;
|
||||
} else {
|
||||
let newTab = window.open();
|
||||
if (newTab) {
|
||||
(newTab as any).opener = null;
|
||||
newTab.location.href = url;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function animate(fn: () => void): IDisposable {
|
||||
@@ -1596,3 +1612,13 @@ export function getCookieValue(name: string): string | undefined {
|
||||
|
||||
return match ? match.pop() : undefined;
|
||||
}
|
||||
|
||||
export function addMatchMediaChangeListener(query: string, callback: () => void): void {
|
||||
const mediaQueryList = window.matchMedia(query);
|
||||
if (typeof mediaQueryList.addEventListener === 'function') {
|
||||
mediaQueryList.addEventListener('change', callback);
|
||||
} else {
|
||||
// Safari 13.x
|
||||
mediaQueryList.addListener(callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ declare const self: unknown;
|
||||
export const globals: any = (typeof self === 'object' ? self : typeof global === 'object' ? global : {});
|
||||
|
||||
let nodeProcess: INodeProcess | undefined = undefined;
|
||||
if (typeof globals.vscode !== 'undefined') {
|
||||
if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.process !== 'undefined') {
|
||||
// Native environment (sandboxed)
|
||||
nodeProcess = globals.vscode.process;
|
||||
} else if (typeof process !== 'undefined') {
|
||||
|
||||
@@ -9,7 +9,7 @@ let safeProcess: INodeProcess & { nextTick: (callback: (...args: any[]) => void)
|
||||
declare const process: INodeProcess;
|
||||
|
||||
// Native sandbox environment
|
||||
if (typeof globals.vscode !== 'undefined') {
|
||||
if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.process !== 'undefined') {
|
||||
const sandboxProcess: INodeProcess = globals.vscode.process;
|
||||
safeProcess = {
|
||||
get platform() { return sandboxProcess.platform; },
|
||||
|
||||
@@ -349,14 +349,16 @@ export abstract class EditorAction extends EditorCommand {
|
||||
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void>;
|
||||
}
|
||||
|
||||
export type EditorActionImplementation = (accessor: ServicesAccessor, editor: ICodeEditor, args: any) => boolean | Promise<void>;
|
||||
|
||||
export class MultiEditorAction extends EditorAction {
|
||||
|
||||
private readonly _implementations: [number, CommandImplementation][] = [];
|
||||
private readonly _implementations: [number, EditorActionImplementation][] = [];
|
||||
|
||||
/**
|
||||
* A higher priority gets to be looked at first
|
||||
*/
|
||||
public addImplementation(priority: number, implementation: CommandImplementation): IDisposable {
|
||||
public addImplementation(priority: number, implementation: EditorActionImplementation): IDisposable {
|
||||
this._implementations.push([priority, implementation]);
|
||||
this._implementations.sort((a, b) => b[0] - a[0]);
|
||||
return {
|
||||
@@ -373,7 +375,7 @@ export class MultiEditorAction extends EditorAction {
|
||||
|
||||
public run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
|
||||
for (const impl of this._implementations) {
|
||||
const result = impl[1](accessor, args);
|
||||
const result = impl[1](accessor, editor, args);
|
||||
if (result) {
|
||||
if (typeof result === 'boolean') {
|
||||
return;
|
||||
|
||||
@@ -226,7 +226,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
protected readonly _instantiationService: IInstantiationService;
|
||||
protected readonly _contextKeyService: IContextKeyService;
|
||||
private readonly _notificationService: INotificationService;
|
||||
private readonly _codeEditorService: ICodeEditorService;
|
||||
protected readonly _codeEditorService: ICodeEditorService;
|
||||
private readonly _commandService: ICommandService;
|
||||
private readonly _themeService: IThemeService;
|
||||
|
||||
@@ -1048,6 +1048,10 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
return;
|
||||
}
|
||||
|
||||
this._triggerCommand(handlerId, payload);
|
||||
}
|
||||
|
||||
protected _triggerCommand(handlerId: string, payload: any): void {
|
||||
this._commandService.executeCommand(handlerId, payload);
|
||||
}
|
||||
|
||||
|
||||
@@ -383,7 +383,7 @@ export interface IEditorOptions {
|
||||
*/
|
||||
suggest?: ISuggestOptions;
|
||||
/**
|
||||
* Smart select opptions;
|
||||
* Smart select options.
|
||||
*/
|
||||
smartSelect?: ISmartSelectOptions;
|
||||
/**
|
||||
@@ -638,6 +638,10 @@ export interface IEditorOptions {
|
||||
* Control the behavior and rendering of the inline hints.
|
||||
*/
|
||||
inlayHints?: IEditorInlayHintsOptions;
|
||||
/**
|
||||
* Control if the editor should use shadow DOM.
|
||||
*/
|
||||
useShadowDOM?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3845,6 +3849,7 @@ export const enum EditorOption {
|
||||
tabCompletion,
|
||||
tabIndex,
|
||||
unusualLineTerminators,
|
||||
useShadowDOM,
|
||||
useTabStops,
|
||||
wordSeparators,
|
||||
wordWrap,
|
||||
@@ -4460,6 +4465,9 @@ export const EditorOptions = {
|
||||
description: nls.localize('unusualLineTerminators', "Remove unusual line terminators that might cause problems.")
|
||||
}
|
||||
)),
|
||||
useShadowDOM: register(new EditorBooleanOption(
|
||||
EditorOption.useShadowDOM, 'useShadowDOM', true
|
||||
)),
|
||||
useTabStops: register(new EditorBooleanOption(
|
||||
EditorOption.useTabStops, 'useTabStops', true,
|
||||
{ description: nls.localize('useTabStops', "Inserting and deleting whitespace follows tab stops.") }
|
||||
|
||||
@@ -1220,7 +1220,6 @@ export interface ITextModel {
|
||||
/**
|
||||
* An event emitted when the model has been attached to the first editor or detached from the last editor.
|
||||
* @event
|
||||
* @internal
|
||||
*/
|
||||
onDidChangeAttached(listener: () => void): IDisposable;
|
||||
/**
|
||||
@@ -1247,7 +1246,6 @@ export interface ITextModel {
|
||||
|
||||
/**
|
||||
* Returns if this model is attached to an editor or not.
|
||||
* @internal
|
||||
*/
|
||||
isAttachedToEditor(): boolean;
|
||||
|
||||
|
||||
@@ -278,23 +278,24 @@ export enum EditorOption {
|
||||
tabCompletion = 108,
|
||||
tabIndex = 109,
|
||||
unusualLineTerminators = 110,
|
||||
useTabStops = 111,
|
||||
wordSeparators = 112,
|
||||
wordWrap = 113,
|
||||
wordWrapBreakAfterCharacters = 114,
|
||||
wordWrapBreakBeforeCharacters = 115,
|
||||
wordWrapColumn = 116,
|
||||
wordWrapOverride1 = 117,
|
||||
wordWrapOverride2 = 118,
|
||||
wrappingIndent = 119,
|
||||
wrappingStrategy = 120,
|
||||
showDeprecated = 121,
|
||||
inlayHints = 122,
|
||||
editorClassName = 123,
|
||||
pixelRatio = 124,
|
||||
tabFocusMode = 125,
|
||||
layoutInfo = 126,
|
||||
wrappingInfo = 127
|
||||
useShadowDOM = 111,
|
||||
useTabStops = 112,
|
||||
wordSeparators = 113,
|
||||
wordWrap = 114,
|
||||
wordWrapBreakAfterCharacters = 115,
|
||||
wordWrapBreakBeforeCharacters = 116,
|
||||
wordWrapColumn = 117,
|
||||
wordWrapOverride1 = 118,
|
||||
wordWrapOverride2 = 119,
|
||||
wrappingIndent = 120,
|
||||
wrappingStrategy = 121,
|
||||
showDeprecated = 122,
|
||||
inlayHints = 123,
|
||||
editorClassName = 124,
|
||||
pixelRatio = 125,
|
||||
tabFocusMode = 126,
|
||||
layoutInfo = 127,
|
||||
wrappingInfo = 128
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { Lazy } from 'vs/base/common/lazy';
|
||||
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { IPosition, Position } from 'vs/editor/common/core/position';
|
||||
import { ScrollType } from 'vs/editor/common/editorCommon';
|
||||
import { CodeAction, CodeActionProviderRegistry, Command } from 'vs/editor/common/modes';
|
||||
@@ -92,8 +93,10 @@ export class CodeActionMenu extends Disposable {
|
||||
const anchor = Position.isIPosition(at) ? this._toCoords(at) : at || { x: 0, y: 0 };
|
||||
const resolver = this._keybindingResolver.getResolver();
|
||||
|
||||
const useShadowDOM = this._editor.getOption(EditorOption.useShadowDOM);
|
||||
|
||||
this._contextMenuService.showContextMenu({
|
||||
domForShadowRoot: this._editor.getDomNode()!,
|
||||
domForShadowRoot: useShadowDOM ? this._editor.getDomNode()! : undefined,
|
||||
getAnchor: () => anchor,
|
||||
getActions: () => menuActions,
|
||||
onHide: () => {
|
||||
|
||||
@@ -209,10 +209,12 @@ export class ContextMenuController implements IEditorContribution {
|
||||
anchor = { x: posx, y: posy };
|
||||
}
|
||||
|
||||
const useShadowDOM = this._editor.getOption(EditorOption.useShadowDOM);
|
||||
|
||||
// Show menu
|
||||
this._contextMenuIsBeingShownCount++;
|
||||
this._contextMenuService.showContextMenu({
|
||||
domForShadowRoot: this._editor.getDomNode(),
|
||||
domForShadowRoot: useShadowDOM ? this._editor.getDomNode() : undefined,
|
||||
|
||||
getAnchor: () => anchor!,
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
|
||||
const SEARCH_STRING_MAX_LENGTH = 524288;
|
||||
|
||||
@@ -502,12 +501,7 @@ export const StartFindAction = registerMultiEditorAction(new MultiEditorAction({
|
||||
}
|
||||
}));
|
||||
|
||||
StartFindAction.addImplementation(0, (accessor: ServicesAccessor, args: any): boolean | Promise<void> => {
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
|
||||
if (!editor) {
|
||||
return false;
|
||||
}
|
||||
StartFindAction.addImplementation(0, (accessor: ServicesAccessor, editor: ICodeEditor, args: any): boolean | Promise<void> => {
|
||||
const controller = CommonFindController.get(editor);
|
||||
if (!controller) {
|
||||
return false;
|
||||
@@ -726,10 +720,8 @@ export const StartFindReplaceAction = registerMultiEditorAction(new MultiEditorA
|
||||
}
|
||||
}));
|
||||
|
||||
StartFindReplaceAction.addImplementation(0, (accessor: ServicesAccessor, args: any): boolean | Promise<void> => {
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
const editor = codeEditorService.getFocusedCodeEditor() || codeEditorService.getActiveCodeEditor();
|
||||
if (!editor || !editor.hasModel() || editor.getOption(EditorOption.readOnly)) {
|
||||
StartFindReplaceAction.addImplementation(0, (accessor: ServicesAccessor, editor: ICodeEditor, args: any): boolean | Promise<void> => {
|
||||
if (!editor.hasModel() || editor.getOption(EditorOption.readOnly)) {
|
||||
return false;
|
||||
}
|
||||
const controller = CommonFindController.get(editor);
|
||||
|
||||
@@ -1045,7 +1045,41 @@ export class TitleCaseAction extends AbstractCaseAction {
|
||||
}
|
||||
}
|
||||
|
||||
class BackwardsCompatibleRegExp {
|
||||
|
||||
private _actual: RegExp | null;
|
||||
private _evaluated: boolean;
|
||||
|
||||
constructor(
|
||||
private readonly _pattern: string,
|
||||
private readonly _flags: string
|
||||
) {
|
||||
this._actual = null;
|
||||
this._evaluated = false;
|
||||
}
|
||||
|
||||
public get(): RegExp | null {
|
||||
if (!this._evaluated) {
|
||||
this._evaluated = true;
|
||||
try {
|
||||
this._actual = new RegExp(this._pattern, this._flags);
|
||||
} catch (err) {
|
||||
// this browser does not support this regular expression
|
||||
}
|
||||
}
|
||||
return this._actual;
|
||||
}
|
||||
|
||||
public isSupported(): boolean {
|
||||
return (this.get() !== null);
|
||||
}
|
||||
}
|
||||
|
||||
export class SnakeCaseAction extends AbstractCaseAction {
|
||||
|
||||
public static regExp1 = new BackwardsCompatibleRegExp('(\\p{Ll})(\\p{Lu})', 'gmu');
|
||||
public static regExp2 = new BackwardsCompatibleRegExp('(\\p{Lu}|\\p{N})(\\p{Lu})(\\p{Ll})', 'gmu');
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.action.transformToSnakecase',
|
||||
@@ -1056,9 +1090,15 @@ export class SnakeCaseAction extends AbstractCaseAction {
|
||||
}
|
||||
|
||||
protected _modifyText(text: string, wordSeparators: string): string {
|
||||
const regExp1 = SnakeCaseAction.regExp1.get();
|
||||
const regExp2 = SnakeCaseAction.regExp2.get();
|
||||
if (!regExp1 || !regExp2) {
|
||||
// cannot support this
|
||||
return text;
|
||||
}
|
||||
return (text
|
||||
.replace(/(\p{Ll})(\p{Lu})/gmu, '$1_$2')
|
||||
.replace(/(\p{Lu}|\p{N})(\p{Lu})(\p{Ll})/gmu, '$1_$2$3')
|
||||
.replace(regExp1, '$1_$2')
|
||||
.replace(regExp2, '$1_$2$3')
|
||||
.toLocaleLowerCase()
|
||||
);
|
||||
}
|
||||
@@ -1084,4 +1124,7 @@ registerEditorAction(TransposeAction);
|
||||
registerEditorAction(UpperCaseAction);
|
||||
registerEditorAction(LowerCaseAction);
|
||||
registerEditorAction(TitleCaseAction);
|
||||
registerEditorAction(SnakeCaseAction);
|
||||
|
||||
if (SnakeCaseAction.regExp1.isSupported() && SnakeCaseAction.regExp2.isSupported()) {
|
||||
registerEditorAction(SnakeCaseAction);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import { StandaloneThemeServiceImpl } from 'vs/editor/standalone/browser/standal
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { ILanguageSelection, IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { StandaloneCodeEditorServiceImpl } from 'vs/editor/standalone/browser/standaloneCodeServiceImpl';
|
||||
|
||||
/**
|
||||
* Description of an action contribution
|
||||
@@ -363,6 +364,20 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
|
||||
|
||||
return toDispose;
|
||||
}
|
||||
|
||||
protected override _triggerCommand(handlerId: string, payload: any): void {
|
||||
if (this._codeEditorService instanceof StandaloneCodeEditorServiceImpl) {
|
||||
// Help commands find this editor as the active editor
|
||||
try {
|
||||
this._codeEditorService.setActiveCodeEditor(this);
|
||||
super._triggerCommand(handlerId, payload);
|
||||
} finally {
|
||||
this._codeEditorService.setActiveCodeEditor(null);
|
||||
}
|
||||
} else {
|
||||
super._triggerCommand(handlerId, payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class StandaloneEditor extends StandaloneCodeEditor implements IStandaloneCodeEditor {
|
||||
|
||||
@@ -18,6 +18,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl {
|
||||
|
||||
private readonly _editorIsOpen: IContextKey<boolean>;
|
||||
private _activeCodeEditor: ICodeEditor | null;
|
||||
|
||||
constructor(
|
||||
styleSheet: GlobalStyleSheet | null,
|
||||
@@ -28,6 +29,7 @@ export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl {
|
||||
this.onCodeEditorAdd(() => this._checkContextKey());
|
||||
this.onCodeEditorRemove(() => this._checkContextKey());
|
||||
this._editorIsOpen = contextKeyService.createKey('editorIsOpen', false);
|
||||
this._activeCodeEditor = null;
|
||||
}
|
||||
|
||||
private _checkContextKey(): void {
|
||||
@@ -41,8 +43,12 @@ export class StandaloneCodeEditorServiceImpl extends CodeEditorServiceImpl {
|
||||
this._editorIsOpen.set(hasCodeEditor);
|
||||
}
|
||||
|
||||
public setActiveCodeEditor(activeCodeEditor: ICodeEditor | null): void {
|
||||
this._activeCodeEditor = activeCodeEditor;
|
||||
}
|
||||
|
||||
public getActiveCodeEditor(): ICodeEditor | null {
|
||||
return null; // not supported in the standalone case
|
||||
return this._activeCodeEditor;
|
||||
}
|
||||
|
||||
public openCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise<ICodeEditor | null> {
|
||||
|
||||
@@ -233,7 +233,7 @@ export class StandaloneThemeServiceImpl extends Disposable implements IStandalon
|
||||
this._updateCSS();
|
||||
});
|
||||
|
||||
window.matchMedia('(forced-colors: active)').addEventListener('change', () => {
|
||||
dom.addMatchMediaChangeListener('(forced-colors: active)', () => {
|
||||
this._updateActualTheme();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -86,15 +86,14 @@ function createKeywordMatcher(arr: string[], caseInsensitive: boolean = false):
|
||||
* @example /@@text/ will not be replaced and will become /@text/.
|
||||
*/
|
||||
function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp {
|
||||
// @@ must be interpreted as a literal @, so we replace all occurences of @@ with a placeholder character
|
||||
str = str.replace(/@@/g, `\x01`);
|
||||
|
||||
let n = 0;
|
||||
let hadExpansion: boolean;
|
||||
do {
|
||||
hadExpansion = false;
|
||||
str = str.replace(/(.|^)@(\w+)/g, function (s, charBeforeAtSign, attr?) {
|
||||
if (charBeforeAtSign === '@') {
|
||||
// do not expand @@
|
||||
return s;
|
||||
}
|
||||
str = str.replace(/@(\w+)/g, function (s, attr?) {
|
||||
hadExpansion = true;
|
||||
let sub = '';
|
||||
if (typeof (lexer[attr]) === 'string') {
|
||||
@@ -108,13 +107,13 @@ function compileRegExp(lexer: monarchCommon.ILexerMin, str: string): RegExp {
|
||||
throw monarchCommon.createError(lexer, 'attribute reference \'' + attr + '\' must be a string, used at: ' + str);
|
||||
}
|
||||
}
|
||||
return charBeforeAtSign + (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')');
|
||||
return (monarchCommon.empty(sub) ? '' : '(?:' + sub + ')');
|
||||
});
|
||||
n++;
|
||||
} while (hadExpansion && n < 5);
|
||||
|
||||
// handle escaped @@
|
||||
str = str.replace(/@@/g, '@');
|
||||
str = str.replace(/\x01/g, '@');
|
||||
|
||||
let flags = (lexer.ignoreCase ? 'i' : '') + (lexer.unicode ? 'u' : '');
|
||||
return new RegExp(str, flags);
|
||||
|
||||
@@ -264,4 +264,31 @@ suite('Monarch', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('microsoft/monaco-editor#2424: Allow to target @@', () => {
|
||||
const modeService = new ModeServiceImpl();
|
||||
|
||||
const tokenizer = createMonarchTokenizer(modeService, 'test', {
|
||||
ignoreCase: false,
|
||||
tokenizer: {
|
||||
root: [
|
||||
{
|
||||
regex: /@@@@/,
|
||||
action: { token: 'ham' }
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const lines = [
|
||||
`@@`
|
||||
];
|
||||
|
||||
const actualTokens = getTokens(tokenizer, lines);
|
||||
assert.deepStrictEqual(actualTokens, [
|
||||
[
|
||||
new Token(0, 'ham.test', 'test'),
|
||||
]
|
||||
]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Vendored
+33
-18
@@ -1983,6 +1983,11 @@ declare namespace monaco.editor {
|
||||
* @event
|
||||
*/
|
||||
onDidChangeLanguageConfiguration(listener: (e: IModelLanguageConfigurationChangedEvent) => void): IDisposable;
|
||||
/**
|
||||
* An event emitted when the model has been attached to the first editor or detached from the last editor.
|
||||
* @event
|
||||
*/
|
||||
onDidChangeAttached(listener: () => void): IDisposable;
|
||||
/**
|
||||
* An event emitted right before disposing the model.
|
||||
* @event
|
||||
@@ -1993,6 +1998,10 @@ declare namespace monaco.editor {
|
||||
* and make all necessary clean-up to release this object to the GC.
|
||||
*/
|
||||
dispose(): void;
|
||||
/**
|
||||
* Returns if this model is attached to an editor or not.
|
||||
*/
|
||||
isAttachedToEditor(): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2965,7 +2974,7 @@ declare namespace monaco.editor {
|
||||
*/
|
||||
suggest?: ISuggestOptions;
|
||||
/**
|
||||
* Smart select opptions;
|
||||
* Smart select options.
|
||||
*/
|
||||
smartSelect?: ISmartSelectOptions;
|
||||
/**
|
||||
@@ -3220,6 +3229,10 @@ declare namespace monaco.editor {
|
||||
* Control the behavior and rendering of the inline hints.
|
||||
*/
|
||||
inlayHints?: IEditorInlayHintsOptions;
|
||||
/**
|
||||
* Control if the editor should use shadow DOM.
|
||||
*/
|
||||
useShadowDOM?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4094,23 +4107,24 @@ declare namespace monaco.editor {
|
||||
tabCompletion = 108,
|
||||
tabIndex = 109,
|
||||
unusualLineTerminators = 110,
|
||||
useTabStops = 111,
|
||||
wordSeparators = 112,
|
||||
wordWrap = 113,
|
||||
wordWrapBreakAfterCharacters = 114,
|
||||
wordWrapBreakBeforeCharacters = 115,
|
||||
wordWrapColumn = 116,
|
||||
wordWrapOverride1 = 117,
|
||||
wordWrapOverride2 = 118,
|
||||
wrappingIndent = 119,
|
||||
wrappingStrategy = 120,
|
||||
showDeprecated = 121,
|
||||
inlayHints = 122,
|
||||
editorClassName = 123,
|
||||
pixelRatio = 124,
|
||||
tabFocusMode = 125,
|
||||
layoutInfo = 126,
|
||||
wrappingInfo = 127
|
||||
useShadowDOM = 111,
|
||||
useTabStops = 112,
|
||||
wordSeparators = 113,
|
||||
wordWrap = 114,
|
||||
wordWrapBreakAfterCharacters = 115,
|
||||
wordWrapBreakBeforeCharacters = 116,
|
||||
wordWrapColumn = 117,
|
||||
wordWrapOverride1 = 118,
|
||||
wordWrapOverride2 = 119,
|
||||
wrappingIndent = 120,
|
||||
wrappingStrategy = 121,
|
||||
showDeprecated = 122,
|
||||
inlayHints = 123,
|
||||
editorClassName = 124,
|
||||
pixelRatio = 125,
|
||||
tabFocusMode = 126,
|
||||
layoutInfo = 127,
|
||||
wrappingInfo = 128
|
||||
}
|
||||
export const EditorOptions: {
|
||||
acceptSuggestionOnCommitCharacter: IEditorOption<EditorOption.acceptSuggestionOnCommitCharacter, boolean>;
|
||||
@@ -4226,6 +4240,7 @@ declare namespace monaco.editor {
|
||||
tabCompletion: IEditorOption<EditorOption.tabCompletion, 'on' | 'off' | 'onlySnippets'>;
|
||||
tabIndex: IEditorOption<EditorOption.tabIndex, number>;
|
||||
unusualLineTerminators: IEditorOption<EditorOption.unusualLineTerminators, 'auto' | 'off' | 'prompt'>;
|
||||
useShadowDOM: IEditorOption<EditorOption.useShadowDOM, boolean>;
|
||||
useTabStops: IEditorOption<EditorOption.useTabStops, boolean>;
|
||||
wordSeparators: IEditorOption<EditorOption.wordSeparators, string>;
|
||||
wordWrap: IEditorOption<EditorOption.wordWrap, 'on' | 'off' | 'wordWrapColumn' | 'bounded'>;
|
||||
|
||||
@@ -117,9 +117,9 @@ export interface IWalkthroughStep {
|
||||
readonly id: string;
|
||||
readonly title: string;
|
||||
readonly description: string | undefined;
|
||||
readonly media:
|
||||
| { path: string | { dark: string, light: string, hc: string }, altText: string }
|
||||
| { path: string, },
|
||||
readonly media: { path: string | { dark: string, light: string, hc: string }, altText?: string }
|
||||
readonly completionEvents?: string[];
|
||||
/** @deprecated use `completionEvents: 'onCommand:...'` */
|
||||
readonly doneOn?: { command: string };
|
||||
readonly when?: string;
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ export class FileService extends Disposable implements IFileService {
|
||||
mtime: stat.mtime,
|
||||
ctime: stat.ctime,
|
||||
size: stat.size,
|
||||
readonly: Boolean(stat.permissions ?? 0 & FilePermission.Readonly) ?? Boolean(provider.capabilities & FileSystemProviderCapabilities.Readonly),
|
||||
readonly: Boolean(stat.permissions ?? 0 & FilePermission.Readonly) || Boolean(provider.capabilities & FileSystemProviderCapabilities.Readonly),
|
||||
etag: etag({ mtime: stat.mtime, size: stat.size })
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ export interface ILinkDescriptor {
|
||||
readonly title?: string;
|
||||
}
|
||||
|
||||
export interface ILinkOptions {
|
||||
readonly opener?: (href: string) => void;
|
||||
}
|
||||
|
||||
export interface ILinkStyles {
|
||||
readonly textLinkForeground?: Color;
|
||||
readonly disabled?: boolean;
|
||||
@@ -33,6 +37,7 @@ export class Link extends Disposable {
|
||||
|
||||
constructor(
|
||||
link: ILinkDescriptor,
|
||||
options: ILinkOptions | undefined = undefined,
|
||||
@IOpenerService openerService: IOpenerService
|
||||
) {
|
||||
super();
|
||||
@@ -53,7 +58,11 @@ export class Link extends Disposable {
|
||||
this._register(onOpen(e => {
|
||||
EventHelper.stop(e, true);
|
||||
if (!this.disabled) {
|
||||
openerService.open(link.href, { allowCommands: true });
|
||||
if (options?.opener) {
|
||||
options.opener(link.href);
|
||||
} else {
|
||||
openerService.open(link.href, { allowCommands: true });
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes
|
||||
let product: IProductConfiguration;
|
||||
|
||||
// Native sandbox environment
|
||||
if (typeof globals.vscode !== 'undefined') {
|
||||
if (typeof globals.vscode !== 'undefined' && typeof globals.vscode.context !== 'undefined') {
|
||||
const configuration: ISandboxConfiguration | undefined = globals.vscode.context.configuration();
|
||||
if (configuration) {
|
||||
product = configuration.product;
|
||||
|
||||
@@ -101,7 +101,7 @@ export async function resolveCommonProperties(
|
||||
return result;
|
||||
}
|
||||
|
||||
function verifyMicrosoftInternalDomain(domainList: readonly string[]): boolean {
|
||||
export function verifyMicrosoftInternalDomain(domainList: readonly string[]): boolean {
|
||||
const userDnsDomain = env['USERDNSDOMAIN'];
|
||||
if (!userDnsDomain) {
|
||||
return false;
|
||||
|
||||
@@ -174,7 +174,7 @@ export interface IOffProcessTerminalService {
|
||||
getShellEnvironment(): Promise<IProcessEnvironment | undefined>;
|
||||
setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise<void>;
|
||||
updateTitle(id: number, title: string): Promise<void>;
|
||||
updateIcon(id: number, icon: string): Promise<void>;
|
||||
updateIcon(id: number, icon: string, color?: string): Promise<void>;
|
||||
getTerminalLayoutInfo(): Promise<ITerminalsLayoutInfo | undefined>;
|
||||
reduceConnectionGraceTime(): Promise<void>;
|
||||
}
|
||||
@@ -239,9 +239,8 @@ export interface IPtyService {
|
||||
processBinary(id: number, data: string): Promise<void>;
|
||||
/** Confirm the process is _not_ an orphan. */
|
||||
orphanQuestionReply(id: number): Promise<void>;
|
||||
updateTitle(id: number, title: string): Promise<void>
|
||||
updateIcon(id: number, icon: string): Promise<void>
|
||||
|
||||
updateTitle(id: number, title: string): Promise<void>;
|
||||
updateIcon(id: number, icon: string, color?: string): Promise<void>;
|
||||
getDefaultSystemShell(osOverride?: OperatingSystem): Promise<string>;
|
||||
getProfiles?(includeDetectedProfiles?: boolean): Promise<ITerminalProfile[]>;
|
||||
getEnvironment(): Promise<IProcessEnvironment>;
|
||||
@@ -349,7 +348,7 @@ export interface IShellLaunchConfig {
|
||||
/**
|
||||
* This is a terminal that attaches to an already running terminal.
|
||||
*/
|
||||
attachPersistentProcess?: { id: number; pid: number; title: string; cwd: string; icon?: string; };
|
||||
attachPersistentProcess?: { id: number; pid: number; title: string; cwd: string; icon?: string; color?: string };
|
||||
|
||||
/**
|
||||
* Whether the terminal process environment should be exactly as provided in
|
||||
@@ -393,6 +392,11 @@ export interface IShellLaunchConfig {
|
||||
* icon.
|
||||
*/
|
||||
icon?: string;
|
||||
|
||||
/**
|
||||
* The color ID to use for this terminal. If not specified it will use the default fallback
|
||||
*/
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export interface IShellLaunchConfigDto {
|
||||
|
||||
@@ -56,6 +56,7 @@ export interface IProcessDetails {
|
||||
workspaceName: string;
|
||||
isOrphan: boolean;
|
||||
icon: string | undefined;
|
||||
color: string | undefined;
|
||||
}
|
||||
|
||||
export type ITerminalTabLayoutInfoDto = IRawTerminalTabLayoutInfo<IProcessDetails>;
|
||||
|
||||
@@ -170,8 +170,8 @@ export class PtyHostService extends Disposable implements IPtyService {
|
||||
updateTitle(id: number, title: string): Promise<void> {
|
||||
return this._proxy.updateTitle(id, title);
|
||||
}
|
||||
updateIcon(id: number, icon: string): Promise<void> {
|
||||
return this._proxy.updateIcon(id, icon);
|
||||
updateIcon(id: number, icon: string, color?: string): Promise<void> {
|
||||
return this._proxy.updateIcon(id, icon, color);
|
||||
}
|
||||
attachToProcess(id: number): Promise<void> {
|
||||
return this._proxy.attachToProcess(id);
|
||||
|
||||
@@ -118,8 +118,8 @@ export class PtyService extends Disposable implements IPtyService {
|
||||
this._throwIfNoPty(id).setTitle(title);
|
||||
}
|
||||
|
||||
async updateIcon(id: number, icon: string): Promise<void> {
|
||||
this._throwIfNoPty(id).setIcon(icon);
|
||||
async updateIcon(id: number, icon: string, color?: string): Promise<void> {
|
||||
this._throwIfNoPty(id).setIcon(icon, color);
|
||||
}
|
||||
|
||||
async detachFromProcess(id: number): Promise<void> {
|
||||
@@ -256,7 +256,8 @@ export class PtyService extends Disposable implements IPtyService {
|
||||
workspaceName: persistentProcess.workspaceName,
|
||||
cwd,
|
||||
isOrphan,
|
||||
icon: persistentProcess.icon
|
||||
icon: persistentProcess.icon,
|
||||
color: persistentProcess.color
|
||||
};
|
||||
}
|
||||
|
||||
@@ -309,13 +310,15 @@ export class PersistentTerminalProcess extends Disposable {
|
||||
get pid(): number { return this._pid; }
|
||||
get title(): string { return this._title || this._terminalProcess.currentTitle; }
|
||||
get icon(): string | undefined { return this._icon; }
|
||||
get color(): string | undefined { return this._color; }
|
||||
|
||||
setTitle(title: string): void {
|
||||
this._title = title;
|
||||
}
|
||||
|
||||
setIcon(icon: string): void {
|
||||
setIcon(icon: string, color?: string): void {
|
||||
this._icon = icon;
|
||||
this._color = color;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -326,7 +329,8 @@ export class PersistentTerminalProcess extends Disposable {
|
||||
readonly shouldPersistTerminal: boolean,
|
||||
cols: number, rows: number,
|
||||
private readonly _logService: ILogService,
|
||||
private _icon?: string
|
||||
private _icon?: string,
|
||||
private _color?: string
|
||||
) {
|
||||
super();
|
||||
this._recorder = new TerminalRecorder(cols, rows);
|
||||
|
||||
Vendored
+40
-7
@@ -392,6 +392,25 @@ declare module 'vscode' {
|
||||
Warning = 2,
|
||||
}
|
||||
|
||||
/**
|
||||
* A message regarding a completed search.
|
||||
*/
|
||||
export interface TextSearchCompleteMessage {
|
||||
/**
|
||||
* Markdown text of the message.
|
||||
*/
|
||||
text: string,
|
||||
/**
|
||||
* Whether the source of the message is trusted, command links are disabled for untrusted message sources.
|
||||
* Messaged are untrusted by default.
|
||||
*/
|
||||
trusted?: boolean,
|
||||
/**
|
||||
* The message type, this affects how the message will be rendered.
|
||||
*/
|
||||
type: TextSearchCompleteMessageType,
|
||||
}
|
||||
|
||||
/**
|
||||
* Information collected when text search is complete.
|
||||
*/
|
||||
@@ -411,8 +430,10 @@ declare module 'vscode' {
|
||||
* Messages with "Information" tyle support links in markdown syntax:
|
||||
* - Click to [run a command](command:workbench.action.OpenQuickPick)
|
||||
* - Click to [open a website](https://aka.ms)
|
||||
*
|
||||
* Commands may optionally return { triggerSearch: true } to signal to VS Code that the original search should run be agian.
|
||||
*/
|
||||
message?: { text: string, type: TextSearchCompleteMessageType } | { text: string, type: TextSearchCompleteMessageType }[];
|
||||
message?: TextSearchCompleteMessage | TextSearchCompleteMessage[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1071,8 +1092,10 @@ declare module 'vscode' {
|
||||
*/
|
||||
readonly outputs: ReadonlyArray<NotebookCellOutput>;
|
||||
|
||||
// todo@API maybe just executionSummary or lastExecutionSummary?
|
||||
readonly latestExecutionSummary: NotebookCellExecutionSummary | undefined;
|
||||
/**
|
||||
* The most recent {@link NotebookCellExecutionSummary excution summary} for this cell.
|
||||
*/
|
||||
readonly executionSummary?: NotebookCellExecutionSummary;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1269,9 +1292,17 @@ declare module 'vscode' {
|
||||
// static textplain(value:string): NotebookCellOutputItem;
|
||||
// static errortrace(value:any): NotebookCellOutputItem;
|
||||
|
||||
/**
|
||||
* Creates `application/x.notebook.error`
|
||||
*
|
||||
* @param err An error for which an output item is wanted
|
||||
*/
|
||||
static error(err: Error): NotebookCellOutputItem;
|
||||
|
||||
mime: string;
|
||||
|
||||
//todo@API string or Unit8Array?
|
||||
// value: string | Uint8Array | unknown;
|
||||
value: unknown;
|
||||
|
||||
metadata?: { [key: string]: any };
|
||||
@@ -1320,8 +1351,10 @@ declare module 'vscode' {
|
||||
*/
|
||||
metadata?: NotebookCellMetadata;
|
||||
|
||||
// todo@API just executionSummary or lastExecutionSummary
|
||||
latestExecutionSummary?: NotebookCellExecutionSummary;
|
||||
/**
|
||||
* The execution summary of this cell data.
|
||||
*/
|
||||
executionSummary?: NotebookCellExecutionSummary;
|
||||
|
||||
/**
|
||||
* Create new cell data. Minimal cell data specifies its kind, its source value, and the
|
||||
@@ -1332,9 +1365,9 @@ declare module 'vscode' {
|
||||
* @param languageId The language identifier of the source value.
|
||||
* @param outputs //TODO@API remove ctor?
|
||||
* @param metadata //TODO@API remove ctor?
|
||||
* @param latestExecutionSummary //TODO@API remove ctor?
|
||||
* @param executionSummary //TODO@API remove ctor?
|
||||
*/
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, latestExecutionSummary?: NotebookCellExecutionSummary);
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, executionSummary?: NotebookCellExecutionSummary);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -145,7 +145,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
|
||||
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadBulkEdits)));
|
||||
const extHostNotebook = rpcProtocol.set(ExtHostContext.ExtHostNotebook, new ExtHostNotebookController(rpcProtocol, extHostCommands, extHostDocumentsAndEditors, extHostDocuments, extHostLogService, extensionStoragePaths));
|
||||
const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook));
|
||||
const extHostNotebookKernels = rpcProtocol.set(ExtHostContext.ExtHostNotebookKernels, new ExtHostNotebookKernels(rpcProtocol, initData, extHostNotebook, extHostLogService));
|
||||
const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands, extHostLogService));
|
||||
const extHostEditorInsets = rpcProtocol.set(ExtHostContext.ExtHostEditorInsets, new ExtHostEditorInsets(rpcProtocol.getProxy(MainContext.MainThreadEditorInsets), extHostEditors, { ...initData.environment, remote: initData.remote }));
|
||||
|
||||
@@ -87,7 +87,7 @@ export class ExtHostCell {
|
||||
document: data.document,
|
||||
get outputs() { return that._outputs.slice(0); },
|
||||
get metadata() { return that._metadata; },
|
||||
get latestExecutionSummary() { return that._previousResult; }
|
||||
get executionSummary() { return that._previousResult; }
|
||||
});
|
||||
}
|
||||
return this._apiCell;
|
||||
|
||||
@@ -20,6 +20,7 @@ import { CellEditType, IImmediateCellEditOperation, NullablePartialNotebookCellM
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { NotebookCellExecutionState } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { asArray } from 'vs/base/common/arrays';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
interface IKernelData {
|
||||
extensionId: ExtensionIdentifier,
|
||||
@@ -40,7 +41,8 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
constructor(
|
||||
private readonly _mainContext: IMainContext,
|
||||
private readonly _initData: IExtHostInitDataService,
|
||||
private readonly _extHostNotebook: ExtHostNotebookController
|
||||
private readonly _extHostNotebook: ExtHostNotebookController,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
) {
|
||||
this._proxy = _mainContext.getProxy(MainContext.MainThreadNotebookKernels);
|
||||
}
|
||||
@@ -53,9 +55,12 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const handle = this._handlePool++;
|
||||
const that = this;
|
||||
|
||||
this._logService.trace(`NotebookController[${handle}], CREATED by ${extension.identifier.value}, ${id}`);
|
||||
|
||||
const _defaultExecutHandler = () => console.warn(`NO execute handler from notebook controller '${data.id}' of extension: '${extension.identifier}'`);
|
||||
|
||||
let isDisposed = false;
|
||||
@@ -164,12 +169,14 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
throw new Error('notebook controller is DISPOSED');
|
||||
}
|
||||
if (!associatedNotebooks.has(cell.notebook.uri)) {
|
||||
that._logService.trace(`NotebookController[${handle}] NOT associated to notebook, associated to THESE notebooks:`, Array.from(associatedNotebooks.keys()).map(u => u.toString()));
|
||||
throw new Error(`notebook controller is NOT associated to notebook: ${cell.notebook.uri.toString()}`);
|
||||
}
|
||||
return that._createNotebookCellExecution(cell);
|
||||
},
|
||||
dispose: () => {
|
||||
if (!isDisposed) {
|
||||
this._logService.trace(`NotebookController[${handle}], DISPOSED`);
|
||||
isDisposed = true;
|
||||
this._kernelData.delete(handle);
|
||||
commandDisposables.dispose();
|
||||
@@ -212,6 +219,7 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
} else {
|
||||
obj.associatedNotebooks.delete(notebook.uri);
|
||||
}
|
||||
this._logService.trace(`NotebookController[${handle}] ASSOCIATE notebook`, notebook.uri.toString(), value);
|
||||
// send event
|
||||
obj.onDidChangeSelection.fire({
|
||||
selected: value,
|
||||
@@ -236,9 +244,11 @@ export class ExtHostNotebookKernels implements ExtHostNotebookKernelsShape {
|
||||
}
|
||||
|
||||
try {
|
||||
this._logService.trace(`NotebookController[${handle}] EXECUTE cells`, document.uri.toString(), cells.length);
|
||||
await obj.controller.executeHandler.call(obj.controller, cells, document.apiNotebook, obj.controller);
|
||||
} catch (err) {
|
||||
//
|
||||
this._logService.error(`NotebookController[${handle}] execute cells FAILED`, err);
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1494,7 +1494,7 @@ export namespace NotebookCellData {
|
||||
source: data.value,
|
||||
metadata: {
|
||||
...data.metadata,
|
||||
...NotebookCellPreviousExecutionResult.from(data.latestExecutionSummary ?? {})
|
||||
...NotebookCellPreviousExecutionResult.from(data.executionSummary ?? {})
|
||||
},
|
||||
outputs: data.outputs ? data.outputs.map(NotebookCellOutput.from) : []
|
||||
};
|
||||
|
||||
@@ -3049,15 +3049,15 @@ export class NotebookCellData {
|
||||
languageId: string;
|
||||
outputs?: NotebookCellOutput[];
|
||||
metadata?: NotebookCellMetadata;
|
||||
latestExecutionSummary?: vscode.NotebookCellExecutionSummary;
|
||||
executionSummary?: vscode.NotebookCellExecutionSummary;
|
||||
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, latestExecutionSummary?: vscode.NotebookCellExecutionSummary) {
|
||||
constructor(kind: NotebookCellKind, value: string, languageId: string, outputs?: NotebookCellOutput[], metadata?: NotebookCellMetadata, executionSummary?: vscode.NotebookCellExecutionSummary) {
|
||||
this.kind = kind;
|
||||
this.value = value;
|
||||
this.languageId = languageId;
|
||||
this.outputs = outputs ?? [];
|
||||
this.metadata = metadata;
|
||||
this.latestExecutionSummary = latestExecutionSummary;
|
||||
this.executionSummary = executionSummary;
|
||||
|
||||
NotebookCellData.validate(this);
|
||||
}
|
||||
@@ -3087,6 +3087,13 @@ export class NotebookCellOutputItem {
|
||||
return typeof (<vscode.NotebookCellOutputItem>obj).mime === 'string';
|
||||
}
|
||||
|
||||
static error(err: Error): NotebookCellOutputItem {
|
||||
return new NotebookCellOutputItem(
|
||||
'application/x.notebook.error',
|
||||
JSON.stringify({ name: err.name, message: err.message, stack: err.stack })
|
||||
);
|
||||
}
|
||||
|
||||
constructor(
|
||||
public mime: string,
|
||||
public value: unknown, // JSON'able
|
||||
|
||||
@@ -162,7 +162,7 @@ export class BannerPart extends Part implements IBannerService {
|
||||
const actionContainer = append(this.element, $('div.message-actions-container'));
|
||||
|
||||
for (const action of item.actions) {
|
||||
const actionLink = this._register(this.instantiationService.createInstance(Link, action));
|
||||
const actionLink = this._register(this.instantiationService.createInstance(Link, action, {}));
|
||||
this._register(attachLinkStyler(actionLink, this.themeService, { textLinkForeground: BANNER_FOREGROUND }));
|
||||
actionContainer.appendChild(actionLink.el);
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ function registerOpenEditorAPICommands(): void {
|
||||
group = editorGroupsService.getGroup(viewColumnToEditorGroup(editorGroupsService, columnArg)) ?? editorGroupsService.activeGroup;
|
||||
}
|
||||
|
||||
return editorService.openEditor({ resource: URI.revive(resource), options: { ...optionsArg, override: id } }, group);
|
||||
return editorService.openEditor({ resource: URI.revive(resource), options: { ...optionsArg, pinned: true, override: id } }, group);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ export class EditorControl extends Disposable {
|
||||
this._register(this.workspaceTrustService.onDidChangeTrust(() => this.onDidChangeWorkspaceTrust()));
|
||||
}
|
||||
|
||||
private async onDidChangeWorkspaceTrust(): Promise<void> {
|
||||
private onDidChangeWorkspaceTrust() {
|
||||
|
||||
// If the active editor pane requires workspace trust
|
||||
// we need to re-open it anytime trust changes to
|
||||
@@ -72,7 +72,7 @@ export class EditorControl extends Disposable {
|
||||
// to handle errors properly.
|
||||
const editor = this._activeEditorPane?.input;
|
||||
const options = this._activeEditorPane?.options;
|
||||
if (editor && await editor.requiresWorkspaceTrust()) {
|
||||
if (editor?.requiresWorkspaceTrust()) {
|
||||
this.groupView.openEditor(editor, options);
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ export class EditorControl extends Disposable {
|
||||
async openEditor(editor: EditorInput, options: EditorOptions | undefined, context: IEditorOpenContext = Object.create(null)): Promise<IOpenEditorResult> {
|
||||
|
||||
// Editor descriptor
|
||||
const descriptor = await this.resolveEditorDescriptor(editor);
|
||||
const descriptor = this.getEditorDescriptor(editor);
|
||||
|
||||
// Editor pane
|
||||
const editorPane = this.doShowEditorPane(descriptor);
|
||||
@@ -90,17 +90,16 @@ export class EditorControl extends Disposable {
|
||||
return { editorPane, editorChanged };
|
||||
}
|
||||
|
||||
private async resolveEditorDescriptor(editor: EditorInput): Promise<IEditorDescriptor> {
|
||||
const editorRequiresTrust = await editor.requiresWorkspaceTrust();
|
||||
const editorBlockedByTrust = editorRequiresTrust && !this.workspaceTrustService.isWorkpaceTrusted();
|
||||
private getEditorDescriptor(editor: EditorInput): IEditorDescriptor {
|
||||
if (editor.requiresWorkspaceTrust() && !this.workspaceTrustService.isWorkpaceTrusted()) {
|
||||
// Workspace trust: if an editor signals it needs workspace trust
|
||||
// but the current workspace is untrusted, we fallback to a generic
|
||||
// editor descriptor to indicate this an do NOT load the registered
|
||||
// editor.
|
||||
return WorkspaceTrustRequiredEditor.DESCRIPTOR;
|
||||
}
|
||||
|
||||
// Workspace trust: if an editor signals it needs workspace trust
|
||||
// but the current workspace is untrusted, we fallback to a generic
|
||||
// editor descriptor to indicate this an do NOT load the registered
|
||||
// editor.
|
||||
const descriptor = editorBlockedByTrust ? WorkspaceTrustRequiredEditor.DESCRIPTOR : this.editorsRegistry.getEditor(editor);
|
||||
|
||||
return assertIsDefined(descriptor);
|
||||
return assertIsDefined(this.editorsRegistry.getEditor(editor));
|
||||
}
|
||||
|
||||
private doShowEditorPane(descriptor: IEditorDescriptor): EditorPane {
|
||||
|
||||
@@ -579,7 +579,7 @@ export abstract class ViewPane extends Pane implements IView {
|
||||
if (typeof node === 'string') {
|
||||
append(p, document.createTextNode(node));
|
||||
} else {
|
||||
const link = this.instantiationService.createInstance(Link, node);
|
||||
const link = this.instantiationService.createInstance(Link, node, {});
|
||||
append(p, link.el);
|
||||
disposables.add(link);
|
||||
disposables.add(attachLinkStyler(link, this.themeService));
|
||||
|
||||
@@ -63,6 +63,7 @@ import { ITimerService } from 'vs/workbench/services/timer/browser/timerService'
|
||||
import { WorkspaceTrustManagementService } from 'vs/workbench/services/workspaces/common/workspaceTrust';
|
||||
import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystemProvider';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
class BrowserMain extends Disposable {
|
||||
|
||||
@@ -106,16 +107,22 @@ class BrowserMain extends Disposable {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const lifecycleService = accessor.get(ILifecycleService);
|
||||
const timerService = accessor.get(ITimerService);
|
||||
const openerService = accessor.get(IOpenerService);
|
||||
const productService = accessor.get(IProductService);
|
||||
|
||||
return {
|
||||
commands: {
|
||||
executeCommand: (command, ...args) => commandService.executeCommand(command, ...args)
|
||||
},
|
||||
env: {
|
||||
uriScheme: productService.urlProtocol,
|
||||
async retrievePerformanceMarks() {
|
||||
await timerService.whenReady();
|
||||
|
||||
return timerService.getPerformanceMarks();
|
||||
},
|
||||
async openUri(uri: URI): Promise<boolean> {
|
||||
return openerService.open(uri, {});
|
||||
}
|
||||
},
|
||||
shutdown: () => lifecycleService.shutdown()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { setFullscreen } from 'vs/base/browser/browser';
|
||||
import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpener } from 'vs/base/browser/dom';
|
||||
import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpenerWithSuccess, windowOpenNoOpener } from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -144,7 +144,7 @@ export class BrowserWindow extends Disposable {
|
||||
this.openerService.setDefaultExternalOpener({
|
||||
openExternal: async (href: string) => {
|
||||
if (matchesScheme(href, Schemas.http) || matchesScheme(href, Schemas.https)) {
|
||||
const opened = windowOpenNoOpener(href);
|
||||
const opened = windowOpenNoOpenerWithSuccess(href);
|
||||
if (!opened) {
|
||||
const showResult = await this.dialogService.show(Severity.Warning, localize('unableToOpenExternal', "The browser interrupted the opening of a new tab or window. Press 'Open' to open it anyway."),
|
||||
[localize('open', "Open"), localize('learnMore', "Learn More"), localize('cancel', "Cancel")], { cancelId: 2, detail: href });
|
||||
|
||||
@@ -435,7 +435,7 @@ export interface IEditorInput extends IDisposable {
|
||||
/**
|
||||
* Returns if the input requires workspace trust or not.
|
||||
*/
|
||||
requiresWorkspaceTrust(): Promise<boolean>;
|
||||
requiresWorkspaceTrust(): boolean
|
||||
|
||||
/**
|
||||
* Returns if this input is readonly or not.
|
||||
@@ -577,7 +577,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
|
||||
return { typeId: this.typeId };
|
||||
}
|
||||
|
||||
async requiresWorkspaceTrust(): Promise<boolean> {
|
||||
requiresWorkspaceTrust(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -799,10 +799,8 @@ export class SideBySideEditorInput extends EditorInput {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
override async requiresWorkspaceTrust(): Promise<boolean> {
|
||||
const requiresTrust = await Promise.all([this.primary.requiresWorkspaceTrust(), this.secondary.requiresWorkspaceTrust()]);
|
||||
|
||||
return requiresTrust.some(value => value === true);
|
||||
override requiresWorkspaceTrust(): boolean {
|
||||
return this.primary.requiresWorkspaceTrust() || this.secondary.requiresWorkspaceTrust();
|
||||
}
|
||||
|
||||
override isReadonly(): boolean {
|
||||
|
||||
@@ -877,8 +877,8 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
|
||||
});
|
||||
|
||||
this.registerExtensionAction({
|
||||
id: 'workbench.extensions.action.listTrustRequiredExtensions',
|
||||
title: { value: localize('showTrustRequiredExtensions', "Show Extensions Requiring Trust"), original: 'Show Extensions Requiring Trust' },
|
||||
id: 'workbench.extensions.action.listWorkspaceUnsupportedExtensions',
|
||||
title: { value: localize('showWorkspaceUnsupportedExtensions', "Show Extensions Unsupported By Workspace"), original: 'Show Extensions Unsupported By Workspace' },
|
||||
category: ExtensionsLocalizedLabel,
|
||||
menu: [{
|
||||
id: MenuId.CommandPalette,
|
||||
@@ -889,9 +889,9 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
|
||||
order: 6,
|
||||
}],
|
||||
menuTitles: {
|
||||
[extensionsFilterSubMenu.id]: localize('trust required filter', "Trust Required")
|
||||
[extensionsFilterSubMenu.id]: localize('workspace unsupported filter', "Workspace Unsupported")
|
||||
},
|
||||
run: () => runAction(this.instantiationService.createInstance(SearchExtensionsAction, '@trustRequired'))
|
||||
run: () => runAction(this.instantiationService.createInstance(SearchExtensionsAction, '@workspaceUnsupported'))
|
||||
});
|
||||
|
||||
this.registerExtensionAction({
|
||||
|
||||
@@ -22,7 +22,7 @@ import { InstallLocalExtensionsInRemoteAction, InstallRemoteExtensionsInLocalAct
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInFeatureExtensionsView, BuiltInThemesExtensionsView, BuiltInProgrammingLanguageExtensionsView, ServerInstalledExtensionsView, DefaultRecommendedExtensionsView, TrustRequiredOnStartExtensionsView, TrustRequiredOnDemandExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInFeatureExtensionsView, BuiltInThemesExtensionsView, BuiltInProgrammingLanguageExtensionsView, ServerInstalledExtensionsView, DefaultRecommendedExtensionsView, UntrustedWorkspaceUnsupportedExtensionsView, UntrustedWorkspacePartiallySupportedExtensionsView, VirtualWorkspaceUnsupportedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
@@ -70,8 +70,8 @@ const HasInstalledExtensionsContext = new RawContextKey<boolean>('hasInstalledEx
|
||||
const HasInstalledWebExtensionsContext = new RawContextKey<boolean>('hasInstalledWebExtensions', false);
|
||||
const BuiltInExtensionsContext = new RawContextKey<boolean>('builtInExtensions', false);
|
||||
const SearchBuiltInExtensionsContext = new RawContextKey<boolean>('searchBuiltInExtensions', false);
|
||||
const TrustRequiredExtensionsContext = new RawContextKey<boolean>('trustRequiredExtensions', false);
|
||||
const SearchTrustRequiredExtensionsContext = new RawContextKey<boolean>('searchTrustRequiredExtensions', false);
|
||||
const UnsupportedWorkspaceExtensionsContext = new RawContextKey<boolean>('unsupportedWorkspaceExtensions', false);
|
||||
const SearchUnsupportedWorkspaceExtensionsContext = new RawContextKey<boolean>('searchUnsupportedWorkspaceExtensions', false);
|
||||
const RecommendedExtensionsContext = new RawContextKey<boolean>('recommendedExtensions', false);
|
||||
|
||||
export class ExtensionsViewletViewsContribution implements IWorkbenchContribution {
|
||||
@@ -104,7 +104,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
|
||||
viewDescriptors.push(...this.createBuiltinExtensionsViewDescriptors());
|
||||
|
||||
/* Trust Required extensions views */
|
||||
viewDescriptors.push(...this.createTrustRequiredExtensionsViewDescriptors());
|
||||
viewDescriptors.push(...this.createUnsupportedWorkspaceExtensionsViewDescriptors());
|
||||
|
||||
Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).registerViews(viewDescriptors, this.container);
|
||||
}
|
||||
@@ -344,13 +344,13 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
|
||||
});
|
||||
|
||||
/*
|
||||
* View used for searching trustRequired extensions
|
||||
* View used for searching workspace unsupported extensions
|
||||
*/
|
||||
viewDescriptors.push({
|
||||
id: 'workbench.views.extensions.searchTrustRequired',
|
||||
name: localize('trustRequired', "Trust Required"),
|
||||
id: 'workbench.views.extensions.searchWorkspaceUnsupported',
|
||||
name: localize('workspaceUnsupported', "Workspace Unsupported"),
|
||||
ctorDescriptor: new SyncDescriptor(ExtensionsListView, [{}]),
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchTrustRequiredExtensions')),
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('searchWorkspaceUnsupportedExtensions')),
|
||||
});
|
||||
|
||||
return viewDescriptors;
|
||||
@@ -405,21 +405,28 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
|
||||
return viewDescriptors;
|
||||
}
|
||||
|
||||
private createTrustRequiredExtensionsViewDescriptors(): IViewDescriptor[] {
|
||||
private createUnsupportedWorkspaceExtensionsViewDescriptors(): IViewDescriptor[] {
|
||||
const viewDescriptors: IViewDescriptor[] = [];
|
||||
|
||||
viewDescriptors.push({
|
||||
id: 'workbench.views.extensions.trustRequiredOnStartExtensions',
|
||||
name: localize('trustRequiredOnStartExtensions', "Trust Required To Enable"),
|
||||
ctorDescriptor: new SyncDescriptor(TrustRequiredOnStartExtensionsView, [{}]),
|
||||
when: ContextKeyExpr.has('trustRequiredExtensions'),
|
||||
id: 'workbench.views.extensions.untrustedUnsupportedExtensions',
|
||||
name: localize('untrustedUnsupportedExtensions', "Disabled in Restricted Mode"),
|
||||
ctorDescriptor: new SyncDescriptor(UntrustedWorkspaceUnsupportedExtensionsView, [{}]),
|
||||
when: ContextKeyExpr.has('unsupportedWorkspaceExtensions'),
|
||||
});
|
||||
|
||||
viewDescriptors.push({
|
||||
id: 'workbench.views.extensions.trustRequiredOnDemandExtensions',
|
||||
name: localize('trustRequiredOnDemandExtensions', "Trust Required For Features"),
|
||||
ctorDescriptor: new SyncDescriptor(TrustRequiredOnDemandExtensionsView, [{}]),
|
||||
when: ContextKeyExpr.has('trustRequiredExtensions'),
|
||||
id: 'workbench.views.extensions.untrustedPartiallySupportedExtensions',
|
||||
name: localize('untrustedPartiallySupportedExtensions', "Limited in Restricted Mode"),
|
||||
ctorDescriptor: new SyncDescriptor(UntrustedWorkspacePartiallySupportedExtensionsView, [{}]),
|
||||
when: ContextKeyExpr.has('unsupportedWorkspaceExtensions'),
|
||||
});
|
||||
|
||||
viewDescriptors.push({
|
||||
id: 'workbench.views.extensions.virtualUnsupportedExtensions',
|
||||
name: localize('virtualUnsupportedExtensions', "Disabled in Virtual Workspaces"),
|
||||
ctorDescriptor: new SyncDescriptor(VirtualWorkspaceUnsupportedExtensionsView, [{}]),
|
||||
when: ContextKeyExpr.and(ContextKeyExpr.has('unsupportedWorkspaceExtensions'), ContextKeyExpr.has('virtualWorkspace')),
|
||||
});
|
||||
|
||||
return viewDescriptors;
|
||||
@@ -440,8 +447,8 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
private hasInstalledWebExtensionsContextKey: IContextKey<boolean>;
|
||||
private builtInExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchBuiltInExtensionsContextKey: IContextKey<boolean>;
|
||||
private trustRequiredExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchTrustRequiredExtensionsContextKey: IContextKey<boolean>;
|
||||
private workspaceUnsupportedExtensionsContextKey: IContextKey<boolean>;
|
||||
private searchWorkspaceUnsupportedExtensionsContextKey: IContextKey<boolean>;
|
||||
private recommendedExtensionsContextKey: IContextKey<boolean>;
|
||||
|
||||
private searchDelayer: Delayer<void>;
|
||||
@@ -478,8 +485,8 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
this.sortByContextKey = ExtensionsSortByContext.bindTo(contextKeyService);
|
||||
this.searchMarketplaceExtensionsContextKey = SearchMarketplaceExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchInstalledExtensionsContextKey = SearchIntalledExtensionsContext.bindTo(contextKeyService);
|
||||
this.trustRequiredExtensionsContextKey = TrustRequiredExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchTrustRequiredExtensionsContextKey = SearchTrustRequiredExtensionsContext.bindTo(contextKeyService);
|
||||
this.workspaceUnsupportedExtensionsContextKey = UnsupportedWorkspaceExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchWorkspaceUnsupportedExtensionsContextKey = SearchUnsupportedWorkspaceExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchOutdatedExtensionsContextKey = SearchOutdatedExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchEnabledExtensionsContextKey = SearchEnabledExtensionsContext.bindTo(contextKeyService);
|
||||
this.searchDisabledExtensionsContextKey = SearchDisabledExtensionsContext.bindTo(contextKeyService);
|
||||
@@ -517,7 +524,7 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
|
||||
const header = append(this.root, $('.header'));
|
||||
const placeholder = localize('searchExtensions', "Search Extensions in Marketplace");
|
||||
const searchValue = this.searchViewletState['query.value'] ? this.searchViewletState['query.value'] : (this.workspaceTrustService.isWorkpaceTrusted() ? '' : '@trustRequired');
|
||||
const searchValue = this.searchViewletState['query.value'] ? this.searchViewletState['query.value'] : (this.workspaceTrustService.isWorkpaceTrusted() ? '' : '@workspaceUnsupported');
|
||||
|
||||
this.searchBox = this._register(this.instantiationService.createInstance(SuggestEnabledInput, `${VIEWLET_ID}.searchbox`, header, {
|
||||
triggerCharacters: ['@'],
|
||||
@@ -671,8 +678,8 @@ export class ExtensionsViewPaneContainer extends ViewPaneContainer implements IE
|
||||
this.searchEnabledExtensionsContextKey.set(ExtensionsListView.isEnabledExtensionsQuery(value));
|
||||
this.searchDisabledExtensionsContextKey.set(ExtensionsListView.isDisabledExtensionsQuery(value));
|
||||
this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isSearchBuiltInExtensionsQuery(value));
|
||||
this.trustRequiredExtensionsContextKey.set(ExtensionsListView.isTrustRequiredExtensionsQuery(value));
|
||||
this.searchTrustRequiredExtensionsContextKey.set(ExtensionsListView.isSearchTrustRequiredExtensionsQuery(value));
|
||||
this.workspaceUnsupportedExtensionsContextKey.set(ExtensionsListView.isWorkspaceUnsupportedExtensionsQuery(value));
|
||||
this.searchWorkspaceUnsupportedExtensionsContextKey.set(ExtensionsListView.isSearchWorkspaceUnsupportedExtensionsQuery(value));
|
||||
this.builtInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value));
|
||||
this.recommendedExtensionsContextKey.set(isRecommendedExtensionsQuery);
|
||||
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery);
|
||||
|
||||
@@ -49,6 +49,7 @@ import { IPreferencesService } from 'vs/workbench/services/preferences/common/pr
|
||||
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
|
||||
import { getVirtualWorkspaceScheme } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
// Extensions that are automatically classified as Programming Language extensions, but should be Feature extensions
|
||||
const FORCE_FEATURE_EXTENSIONS = ['vscode.git', 'vscode.search-result'];
|
||||
@@ -121,6 +122,7 @@ export class ExtensionsListView extends ViewPane {
|
||||
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
|
||||
@IExtensionManifestPropertiesService private readonly extensionManifestPropertiesService: IExtensionManifestPropertiesService,
|
||||
@IWorkbenchExtensionManagementService protected readonly extensionManagementService: IWorkbenchExtensionManagementService,
|
||||
@IWorkspaceContextService protected readonly workspaceService: IWorkspaceContextService,
|
||||
@IProductService protected readonly productService: IProductService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@@ -394,8 +396,8 @@ export class ExtensionsListView extends ViewPane {
|
||||
extensions = this.filterEnabledExtensions(local, runningExtensions, query, options);
|
||||
}
|
||||
|
||||
else if (/@trustRequired/i.test(value)) {
|
||||
extensions = this.filterTrustRequiredExtensions(local, query, options);
|
||||
else if (/@workspaceUnsupported/i.test(value)) {
|
||||
extensions = this.filterWorkspaceUnsupportedExtensions(local, query, options);
|
||||
}
|
||||
|
||||
return { extensions, canIncludeInstalledExtensions };
|
||||
@@ -548,32 +550,46 @@ export class ExtensionsListView extends ViewPane {
|
||||
return this.sortExtensions(result, options);
|
||||
}
|
||||
|
||||
private filterTrustRequiredExtensions(local: IExtension[], query: Query, options: IQueryOptions): IExtension[] {
|
||||
private filterWorkspaceUnsupportedExtensions(local: IExtension[], query: Query, options: IQueryOptions): IExtension[] {
|
||||
let value = query.value;
|
||||
const onStartOnly = /@trustRequired:onStart/i.test(value);
|
||||
if (onStartOnly) {
|
||||
value = value.replace(/@trustRequired:onStart/g, '');
|
||||
const untrustedPartiallySupportedOnly = /@workspaceUnsupported:untrustedPartial/i.test(value);
|
||||
if (untrustedPartiallySupportedOnly) {
|
||||
value = value.replace(/@workspaceUnsupported:untrustedPartial/g, '');
|
||||
}
|
||||
const onDemandOnly = /@trustRequired:onDemand/i.test(value);
|
||||
if (onDemandOnly) {
|
||||
value = value.replace(/@trustRequired:onDemand/g, '');
|
||||
const untrustedUnsupportedOnly = /@workspaceUnsupported:untrusted/i.test(value);
|
||||
if (untrustedUnsupportedOnly) {
|
||||
value = value.replace(/@workspaceUnsupported:untrusted/g, '');
|
||||
}
|
||||
const virtualUnsupportedOnly = /@workspaceUnsupported:virtual/i.test(value);
|
||||
if (virtualUnsupportedOnly) {
|
||||
value = value.replace(/@workspaceUnsupported:virtual/g, '');
|
||||
}
|
||||
|
||||
value = value.replace(/@trustRequired/g, '').replace(/@sort:(\w+)(-\w*)?/g, '').trim().toLowerCase();
|
||||
value = value.replace(/@workspaceUnsupported/g, '').replace(/@sort:(\w+)(-\w*)?/g, '').trim().toLowerCase();
|
||||
|
||||
const result = local.filter(extension => extension.local && this.extensionManifestPropertiesService.getExtensionUntrustedWorkspaceSupportType(extension.local.manifest) !== true && (extension.name.toLowerCase().indexOf(value) > -1 || extension.displayName.toLowerCase().indexOf(value) > -1));
|
||||
const isVirtualWorkspace = getVirtualWorkspaceScheme(this.workspaceService.getWorkspace()) !== undefined;
|
||||
const virtualUnsupportedExtensions = local.filter(extension => extension.local && !this.extensionManifestPropertiesService.canSupportVirtualWorkspace(extension.local.manifest) && (extension.name.toLowerCase().indexOf(value) > -1 || extension.displayName.toLowerCase().indexOf(value) > -1));
|
||||
|
||||
if (onStartOnly) {
|
||||
const onStartExtensions = result.filter(extension => extension.local && this.extensionManifestPropertiesService.getExtensionUntrustedWorkspaceSupportType(extension.local.manifest) === false);
|
||||
return this.sortExtensions(onStartExtensions, options);
|
||||
let trustRequiringExtensions = local.filter(extension => extension.local && this.extensionManifestPropertiesService.getExtensionUntrustedWorkspaceSupportType(extension.local.manifest) !== true && (extension.name.toLowerCase().indexOf(value) > -1 || extension.displayName.toLowerCase().indexOf(value) > -1));
|
||||
if (isVirtualWorkspace) {
|
||||
trustRequiringExtensions = trustRequiringExtensions.filter(extension => extension.local && this.extensionManifestPropertiesService.canSupportVirtualWorkspace(extension.local.manifest));
|
||||
}
|
||||
|
||||
if (onDemandOnly) {
|
||||
const onDemandExtensions = result.filter(extension => extension.local && this.extensionManifestPropertiesService.getExtensionUntrustedWorkspaceSupportType(extension.local.manifest) === 'limited');
|
||||
return this.sortExtensions(onDemandExtensions, options);
|
||||
if (untrustedUnsupportedOnly) {
|
||||
const untrustedUnsupportedExtensions = trustRequiringExtensions.filter(extension => extension.local && this.extensionManifestPropertiesService.getExtensionUntrustedWorkspaceSupportType(extension.local.manifest) === false);
|
||||
return this.sortExtensions(untrustedUnsupportedExtensions, options);
|
||||
}
|
||||
|
||||
return this.sortExtensions(result, options);
|
||||
if (untrustedPartiallySupportedOnly) {
|
||||
const untrustedPartiallySupportedExtensions = trustRequiringExtensions.filter(extension => extension.local && this.extensionManifestPropertiesService.getExtensionUntrustedWorkspaceSupportType(extension.local.manifest) === 'limited');
|
||||
return this.sortExtensions(untrustedPartiallySupportedExtensions, options);
|
||||
}
|
||||
|
||||
if (virtualUnsupportedOnly) {
|
||||
return this.sortExtensions(virtualUnsupportedExtensions, options);
|
||||
}
|
||||
|
||||
return this.sortExtensions(trustRequiringExtensions, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -964,9 +980,9 @@ export class ExtensionsListView extends ViewPane {
|
||||
|| this.isBuiltInExtensionsQuery(query)
|
||||
|| this.isSearchBuiltInExtensionsQuery(query)
|
||||
|| this.isBuiltInGroupExtensionsQuery(query)
|
||||
|| this.isSearchTrustRequiredExtensionsQuery(query)
|
||||
|| this.isTrustRequiredExtensionsQuery(query)
|
||||
|| this.isTrustRequiredGroupExtensionsQuery(query);
|
||||
|| this.isSearchWorkspaceUnsupportedExtensionsQuery(query)
|
||||
|| this.isWorkspaceUnsupportedExtensionsQuery(query)
|
||||
|| this.isWorkspaceUnsupportedGroupExtensionsQuery(query);
|
||||
}
|
||||
|
||||
static isSearchBuiltInExtensionsQuery(query: string): boolean {
|
||||
@@ -981,16 +997,16 @@ export class ExtensionsListView extends ViewPane {
|
||||
return /^\s*@builtin:.+$/i.test(query.trim());
|
||||
}
|
||||
|
||||
static isSearchTrustRequiredExtensionsQuery(query: string): boolean {
|
||||
return /@trustRequired\s.+/i.test(query);
|
||||
static isSearchWorkspaceUnsupportedExtensionsQuery(query: string): boolean {
|
||||
return /@workspaceUnsupported\s.+/i.test(query);
|
||||
}
|
||||
|
||||
static isTrustRequiredExtensionsQuery(query: string): boolean {
|
||||
return /^\s*@trustRequired$/i.test(query.trim());
|
||||
static isWorkspaceUnsupportedExtensionsQuery(query: string): boolean {
|
||||
return /^\s*@workspaceUnsupported$/i.test(query.trim());
|
||||
}
|
||||
|
||||
static isTrustRequiredGroupExtensionsQuery(query: string): boolean {
|
||||
return /^\s*@trustRequired:.+$/i.test(query.trim());
|
||||
static isWorkspaceUnsupportedGroupExtensionsQuery(query: string): boolean {
|
||||
return /^\s*@workspaceUnsupported:.+$/i.test(query.trim());
|
||||
}
|
||||
|
||||
static isInstalledExtensionsQuery(query: string): boolean {
|
||||
@@ -1088,15 +1104,21 @@ export class BuiltInProgrammingLanguageExtensionsView extends ExtensionsListView
|
||||
}
|
||||
}
|
||||
|
||||
export class TrustRequiredOnStartExtensionsView extends ExtensionsListView {
|
||||
export class UntrustedWorkspaceUnsupportedExtensionsView extends ExtensionsListView {
|
||||
override async show(query: string): Promise<IPagedModel<IExtension>> {
|
||||
return (query && query.trim() !== '@trustRequired') ? this.showEmptyModel() : super.show('@trustRequired:onStart');
|
||||
return (query && query.trim() !== '@workspaceUnsupported') ? this.showEmptyModel() : super.show('@workspaceUnsupported:untrusted');
|
||||
}
|
||||
}
|
||||
|
||||
export class TrustRequiredOnDemandExtensionsView extends ExtensionsListView {
|
||||
export class UntrustedWorkspacePartiallySupportedExtensionsView extends ExtensionsListView {
|
||||
override async show(query: string): Promise<IPagedModel<IExtension>> {
|
||||
return (query && query.trim() !== '@trustRequired') ? this.showEmptyModel() : super.show('@trustRequired:onDemand');
|
||||
return (query && query.trim() !== '@workspaceUnsupported') ? this.showEmptyModel() : super.show('@workspaceUnsupported:untrustedPartial');
|
||||
}
|
||||
}
|
||||
|
||||
export class VirtualWorkspaceUnsupportedExtensionsView extends ExtensionsListView {
|
||||
override async show(query: string): Promise<IPagedModel<IExtension>> {
|
||||
return (query && query.trim() !== '@workspaceUnsupported') ? this.showEmptyModel() : super.show('@workspaceUnsupported:virtual');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export class Query {
|
||||
}
|
||||
|
||||
static suggestions(query: string): string[] {
|
||||
const commands = ['installed', 'outdated', 'enabled', 'disabled', 'builtin', 'recommended', 'trustRequired', 'sort', 'category', 'tag', 'ext', 'id'] as const;
|
||||
const commands = ['installed', 'outdated', 'enabled', 'disabled', 'builtin', 'recommended', 'workspaceUnsupported', 'sort', 'category', 'tag', 'ext', 'id'] as const;
|
||||
const subcommands = {
|
||||
'sort': ['installs', 'rating', 'name'],
|
||||
'category': EXTENSION_CATEGORIES.map(c => `"${c.toLowerCase()}"`),
|
||||
|
||||
@@ -17,6 +17,7 @@ import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/
|
||||
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
|
||||
import { IWorkingCopyEditorService } from 'vs/workbench/services/workingCopy/common/workingCopyEditorService';
|
||||
|
||||
export class TextFileEditorTracker extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
@@ -26,7 +27,8 @@ export class TextFileEditorTracker extends Disposable implements IWorkbenchContr
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
@ICodeEditorService private readonly codeEditorService: ICodeEditorService,
|
||||
@IFilesConfigurationService private readonly filesConfigurationService: IFilesConfigurationService
|
||||
@IFilesConfigurationService private readonly filesConfigurationService: IFilesConfigurationService,
|
||||
@IWorkingCopyEditorService private readonly workingCopyEditorService: IWorkingCopyEditorService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -57,19 +59,24 @@ export class TextFileEditorTracker extends Disposable implements IWorkbenchContr
|
||||
return false; // resource must be dirty
|
||||
}
|
||||
|
||||
const model = this.textFileService.files.get(resource);
|
||||
if (model?.hasState(TextFileEditorModelState.PENDING_SAVE)) {
|
||||
const fileModel = this.textFileService.files.get(resource);
|
||||
if (fileModel?.hasState(TextFileEditorModelState.PENDING_SAVE)) {
|
||||
return false; // resource must not be pending to save
|
||||
}
|
||||
|
||||
if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY && !model?.hasState(TextFileEditorModelState.ERROR)) {
|
||||
if (this.filesConfigurationService.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY && !fileModel?.hasState(TextFileEditorModelState.ERROR)) {
|
||||
// leave models auto saved after short delay unless
|
||||
// the save resulted in an error
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.editorService.isOpened({ resource, typeId: resource.scheme === Schemas.untitled ? UntitledTextEditorInput.ID : FILE_EDITOR_INPUT_ID })) {
|
||||
return false; // model must not be opened already as file
|
||||
return false; // model must not be opened already as file (fast check via editor type)
|
||||
}
|
||||
|
||||
const model = fileModel ?? this.textFileService.untitled.get(resource);
|
||||
if (model && this.workingCopyEditorService.findEditor(model)) {
|
||||
return false; // model must not be opened already as file (slower check via working copy)
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -30,7 +30,7 @@ export class ExplorerModel implements IDisposable {
|
||||
fileService: IFileService
|
||||
) {
|
||||
const setRoots = () => this._roots = this.contextService.getWorkspace().folders
|
||||
.map(folder => new ExplorerItem(folder.uri, fileService, undefined, true, false, folder.name));
|
||||
.map(folder => new ExplorerItem(folder.uri, fileService, undefined, true, false, false, folder.name));
|
||||
setRoots();
|
||||
|
||||
this._listener = this.contextService.onDidChangeWorkspaceFolders(() => {
|
||||
@@ -89,6 +89,7 @@ export class ExplorerItem {
|
||||
private _parent: ExplorerItem | undefined,
|
||||
private _isDirectory?: boolean,
|
||||
private _isSymbolicLink?: boolean,
|
||||
private _readonly?: boolean,
|
||||
private _name: string = basenameOrAuthority(resource),
|
||||
private _mtime?: number,
|
||||
private _unknown = false
|
||||
@@ -124,7 +125,7 @@ export class ExplorerItem {
|
||||
}
|
||||
|
||||
get isReadonly(): boolean {
|
||||
return this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
|
||||
return this._readonly || this.fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
|
||||
}
|
||||
|
||||
get mtime(): number | undefined {
|
||||
@@ -179,7 +180,7 @@ export class ExplorerItem {
|
||||
}
|
||||
|
||||
static create(fileService: IFileService, raw: IFileStat, parent: ExplorerItem | undefined, resolveTo?: readonly URI[]): ExplorerItem {
|
||||
const stat = new ExplorerItem(raw.resource, fileService, parent, raw.isDirectory, raw.isSymbolicLink, raw.name, raw.mtime, !raw.isFile && !raw.isDirectory);
|
||||
const stat = new ExplorerItem(raw.resource, fileService, parent, raw.isDirectory, raw.isSymbolicLink, raw.readonly, raw.name, raw.mtime, !raw.isFile && !raw.isDirectory);
|
||||
|
||||
// Recursively add children if present
|
||||
if (stat.isDirectory) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { TestFileService } from 'vs/workbench/test/browser/workbenchTestServices
|
||||
|
||||
const fileService = new TestFileService();
|
||||
function createStat(this: any, path: string, name: string, isFolder: boolean, hasChildren: boolean, size: number, mtime: number): ExplorerItem {
|
||||
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, false, name, mtime);
|
||||
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, false, false, name, mtime);
|
||||
}
|
||||
|
||||
suite('Files - View Model', function () {
|
||||
@@ -245,19 +245,19 @@ suite('Files - View Model', function () {
|
||||
});
|
||||
|
||||
test('Merge Local with Disk', function () {
|
||||
const merge1 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, 'to', Date.now());
|
||||
const merge2 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, 'to', Date.now());
|
||||
const merge1 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, false, 'to', Date.now());
|
||||
const merge2 = new ExplorerItem(URI.file(join('C:\\', '/path/to')), fileService, undefined, true, false, false, 'to', Date.now());
|
||||
|
||||
// Merge Properties
|
||||
ExplorerItem.mergeLocalWithDisk(merge2, merge1);
|
||||
assert.strictEqual(merge1.mtime, merge2.mtime);
|
||||
|
||||
// Merge Child when isDirectoryResolved=false is a no-op
|
||||
merge2.addChild(new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, 'foo.html', Date.now()));
|
||||
merge2.addChild(new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, false, 'foo.html', Date.now()));
|
||||
ExplorerItem.mergeLocalWithDisk(merge2, merge1);
|
||||
|
||||
// Merge Child with isDirectoryResolved=true
|
||||
const child = new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, 'foo.html', Date.now());
|
||||
const child = new ExplorerItem(URI.file(join('C:\\', '/path/to/foo.html')), fileService, undefined, true, false, false, 'foo.html', Date.now());
|
||||
merge2.removeChild(child);
|
||||
merge2.addChild(child);
|
||||
(<any>merge2)._isDirectoryResolved = true;
|
||||
|
||||
@@ -19,7 +19,7 @@ const $ = dom.$;
|
||||
const fileService = new TestFileService();
|
||||
|
||||
function createStat(this: any, path: string, name: string, isFolder: boolean, hasChildren: boolean, size: number, mtime: number, isSymLink = false, isUnknown = false): ExplorerItem {
|
||||
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, isSymLink, name, mtime, isUnknown);
|
||||
return new ExplorerItem(toResource.call(this, path), fileService, undefined, isFolder, isSymLink, false, name, mtime, isUnknown);
|
||||
}
|
||||
|
||||
suite('Files - ExplorerView', () => {
|
||||
|
||||
@@ -6,41 +6,3 @@
|
||||
// Scrollable Element
|
||||
|
||||
export const SCROLLABLE_ELEMENT_PADDING_TOP = 20;
|
||||
// export const SCROLLABLE_ELEMENT_PADDING_TOP_WITH_TOOLBAR = 8;
|
||||
|
||||
// Code cell layout:
|
||||
// [CODE_CELL_LEFT_MARGIN][CELL_RUN_GUTTER][editorWidth][CELL_RIGHT_MARGIN]
|
||||
|
||||
// Markdown cell layout:
|
||||
// [CELL_MARGIN][content][CELL_RIGHT_MARGIN]
|
||||
|
||||
// Markdown editor cell layout:
|
||||
// [CODE_CELL_LEFT_MARGIN][content][CELL_RIGHT_MARGIN]
|
||||
|
||||
// Cell sizing related
|
||||
export const CELL_RIGHT_MARGIN = 16;
|
||||
export const CELL_RUN_GUTTER = 28;
|
||||
export const CODE_CELL_LEFT_MARGIN = 32;
|
||||
|
||||
export const EDITOR_TOOLBAR_HEIGHT = 0;
|
||||
export const BOTTOM_CELL_TOOLBAR_GAP = 18;
|
||||
export const BOTTOM_CELL_TOOLBAR_HEIGHT = 22;
|
||||
export const CELL_STATUSBAR_HEIGHT = 22;
|
||||
|
||||
// Margin above editor
|
||||
export const CELL_TOP_MARGIN = 6;
|
||||
export const CELL_BOTTOM_MARGIN = 6;
|
||||
|
||||
export const MARKDOWN_CELL_TOP_MARGIN = 8;
|
||||
export const MARKDOWN_CELL_BOTTOM_MARGIN = 8;
|
||||
|
||||
// Top and bottom padding inside the monaco editor in a cell, which are included in `cell.editorHeight`
|
||||
// export const EDITOR_TOP_PADDING = 12;
|
||||
export const EDITOR_BOTTOM_PADDING = 4;
|
||||
export const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12;
|
||||
|
||||
export const CELL_OUTPUT_PADDING = 14;
|
||||
|
||||
export const COLLAPSED_INDICATOR_HEIGHT = 24;
|
||||
|
||||
export const MARKDOWN_PREVIEW_PADDING = 8;
|
||||
|
||||
@@ -35,6 +35,9 @@ import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/not
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { flatten } from 'vs/base/common/arrays';
|
||||
|
||||
// Kernel Command
|
||||
export const SELECT_KERNEL_ID = 'notebook.selectKernel';
|
||||
|
||||
// Notebook Commands
|
||||
const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute';
|
||||
const CANCEL_NOTEBOOK_COMMAND_ID = 'notebook.cancelExecution';
|
||||
|
||||
@@ -28,6 +28,7 @@ import { StartFindAction, StartFindReplaceAction } from 'vs/editor/contrib/find/
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { NLS_MATCHES_LOCATION, NLS_NO_RESULTS } from 'vs/editor/contrib/find/findWidget';
|
||||
import { FindModel } from 'vs/workbench/contrib/notebook/browser/contrib/find/findModel';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
||||
const FIND_HIDE_TRANSITION = 'find-hide-transition';
|
||||
const FIND_SHOW_TRANSITION = 'find-show-transition';
|
||||
@@ -325,7 +326,7 @@ registerAction2(class extends Action2 {
|
||||
}
|
||||
});
|
||||
|
||||
StartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => {
|
||||
StartFindAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
|
||||
|
||||
@@ -338,7 +339,7 @@ StartFindAction.addImplementation(100, (accessor: ServicesAccessor, args: any) =
|
||||
return true;
|
||||
});
|
||||
|
||||
StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, args: any) => {
|
||||
StartFindReplaceAction.addImplementation(100, (accessor: ServicesAccessor, codeEditor: ICodeEditor, args: any) => {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ export class FoldingController extends Disposable implements INotebookEditorCont
|
||||
return;
|
||||
}
|
||||
|
||||
this._localStore.add(this._notebookEditor.viewModel.eventDispatcher.onDidChangeCellState(e => {
|
||||
this._localStore.add(this._notebookEditor.viewModel.viewContext.eventDispatcher.onDidChangeCellState(e => {
|
||||
if (e.source.editStateChanged && e.cell.cellKind === CellKind.Markup) {
|
||||
this._foldingModel?.recompute();
|
||||
// this._updateEditorFoldingRanges();
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IQuickInputButton, IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { getNotebookEditorFromEditorPane, INotebookEditor, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NOTEBOOK_ACTIONS_CATEGORY, SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { getNotebookEditorFromEditorPane, INotebookEditor, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
@@ -26,16 +26,23 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { HoverProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
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,
|
||||
icon: selectKernelIcon,
|
||||
f1: true,
|
||||
menu: {
|
||||
id: MenuId.EditorTitle,
|
||||
when: ContextKeyExpr.and(NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_KERNEL_COUNT.notEqualsTo(0), ContextKeyExpr.equals('config.notebook.experimental.showKernelInEditorTitle', true),),
|
||||
group: 'navigation',
|
||||
order: -10
|
||||
},
|
||||
description: {
|
||||
description: nls.localize('notebookActions.selectKernel.args', "Notebook Kernel Args"),
|
||||
args: [
|
||||
@@ -57,7 +64,6 @@ registerAction2(class extends Action2 {
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -265,7 +271,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution {
|
||||
text: `$(notebook-kernel-select) ${kernel.label}`,
|
||||
ariaLabel: kernel.label,
|
||||
tooltip: isSuggested ? nls.localize('tooltop', "{0} (suggestion)", tooltip) : tooltip,
|
||||
command: 'notebook.selectKernel',
|
||||
command: SELECT_KERNEL_ID,
|
||||
},
|
||||
'notebook.selectKernel',
|
||||
nls.localize('notebook.info', "Notebook Kernel Info"),
|
||||
@@ -282,7 +288,7 @@ export class KernelStatus extends Disposable implements IWorkbenchContribution {
|
||||
{
|
||||
text: nls.localize('kernel.select.label', "Select Kernel"),
|
||||
ariaLabel: nls.localize('kernel.select.label', "Select Kernel"),
|
||||
command: 'notebook.selectKernel',
|
||||
command: SELECT_KERNEL_ID,
|
||||
backgroundColor: { id: 'statusBarItem.prominentBackground' }
|
||||
},
|
||||
'notebook.selectKernel',
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/edit
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { DiffElementViewModelBase, getFormatedMetadataJSON, OUTPUT_EDITOR_HEIGHT_MAGIC, PropertyFoldingState, SideBySideDiffElementViewModel, SingleSideDiffElementViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffElementViewModel';
|
||||
import { CellDiffSideBySideRenderTemplate, CellDiffSingleSideRenderTemplate, DiffSide, DIFF_CELL_MARGIN, INotebookTextDiffEditor, NOTEBOOK_DIFF_CELL_PROPERTY, NOTEBOOK_DIFF_CELL_PROPERTY_EXPANDED } from 'vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser';
|
||||
import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CodeEditorWidget, ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
@@ -26,7 +25,6 @@ import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/men
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { CodiconActionViewItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellActionView';
|
||||
import { getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { collapsedIcon, expandedIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { OutputContainer } from 'vs/workbench/contrib/notebook/browser/diff/diffElementOutputs';
|
||||
import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions';
|
||||
@@ -980,7 +978,8 @@ export class DeletedElement extends SingleSideDiffElement {
|
||||
const originalCell = this.cell.original!;
|
||||
const lineCount = originalCell.textModel.textBuffer.getLineCount();
|
||||
const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17;
|
||||
const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING;
|
||||
const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding();
|
||||
const editorHeight = lineCount * lineHeight + editorPadding.top + editorPadding.bottom;
|
||||
|
||||
this._editor = this.templateData.sourceEditor;
|
||||
this._editor.layout({
|
||||
@@ -1131,7 +1130,8 @@ export class InsertElement extends SingleSideDiffElement {
|
||||
const modifiedCell = this.cell.modified!;
|
||||
const lineCount = modifiedCell.textModel.textBuffer.getLineCount();
|
||||
const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17;
|
||||
const editorHeight = lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING;
|
||||
const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding();
|
||||
const editorHeight = lineCount * lineHeight + editorPadding.top + editorPadding.bottom;
|
||||
|
||||
this._editor = this.templateData.sourceEditor;
|
||||
this._editor.layout(
|
||||
@@ -1469,7 +1469,9 @@ export class ModifiedElement extends AbstractElementRenderer {
|
||||
const modifiedCell = this.cell.modified!;
|
||||
const lineCount = modifiedCell.textModel.textBuffer.getLineCount();
|
||||
const lineHeight = this.notebookEditor.getLayoutInfo().fontInfo.lineHeight || 17;
|
||||
const editorHeight = this.cell.layoutInfo.editorHeight !== 0 ? this.cell.layoutInfo.editorHeight : lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING;
|
||||
const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding();
|
||||
|
||||
const editorHeight = this.cell.layoutInfo.editorHeight !== 0 ? this.cell.layoutInfo.editorHeight : lineCount * lineHeight + editorPadding.top + editorPadding.bottom;
|
||||
this._editorContainer = this.templateData.editorContainer;
|
||||
this._editor = this.templateData.sourceEditor;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
|
||||
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
|
||||
export enum DiffSide {
|
||||
Original = 0,
|
||||
@@ -26,6 +27,7 @@ export interface IDiffCellInfo extends ICommonCellInfo {
|
||||
}
|
||||
|
||||
export interface INotebookTextDiffEditor extends ICommonNotebookEditor {
|
||||
notebookOptions: NotebookOptions;
|
||||
readonly textModel?: NotebookTextModel;
|
||||
onMouseUp: Event<{ readonly event: MouseEvent; readonly target: DiffElementViewModelBase; }>;
|
||||
onDidDynamicOutputRendered: Event<{ cell: IGenericCellViewModel, output: ICellOutputViewModel }>;
|
||||
|
||||
@@ -38,9 +38,9 @@ import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { DiffNestedCellViewModel } from 'vs/workbench/contrib/notebook/browser/diff/diffNestedCellViewModel';
|
||||
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
|
||||
import { CELL_OUTPUT_PADDING, MARKDOWN_PREVIEW_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { NotebookDiffEditorEventDispatcher, NotebookDiffLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/diff/eventDispatcher';
|
||||
import { readFontInfo } from 'vs/editor/browser/config/configuration';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -75,6 +75,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
protected _onDidDynamicOutputRendered = new Emitter<{ cell: IGenericCellViewModel, output: ICellOutputViewModel }>();
|
||||
onDidDynamicOutputRendered = this._onDidDynamicOutputRendered.event;
|
||||
|
||||
private _notebookOptions: NotebookOptions;
|
||||
|
||||
get notebookOptions() {
|
||||
return this._notebookOptions;
|
||||
}
|
||||
|
||||
private readonly _localStore = this._register(new DisposableStore());
|
||||
|
||||
private _isDisposed: boolean = false;
|
||||
@@ -93,10 +99,11 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
@IStorageService storageService: IStorageService,
|
||||
) {
|
||||
super(NotebookTextDiffEditor.ID, telemetryService, themeService, storageService);
|
||||
this._notebookOptions = new NotebookOptions(this.configurationService);
|
||||
this._register(this._notebookOptions);
|
||||
const editorOptions = this.configurationService.getValue<IEditorOptions>('editor');
|
||||
this._fontInfo = readFontInfo(BareFontInfo.createFromRawSettings(editorOptions, getZoomLevel(), getPixelRatio()));
|
||||
this._revealFirst = true;
|
||||
|
||||
this._outputRenderer = new OutputRenderer(this, this.instantiationService);
|
||||
}
|
||||
|
||||
@@ -366,21 +373,12 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
}));
|
||||
}
|
||||
|
||||
private readonly webviewOptions = {
|
||||
outputNodePadding: CELL_OUTPUT_PADDING,
|
||||
outputNodeLeftPadding: 32,
|
||||
previewNodePadding: MARKDOWN_PREVIEW_PADDING,
|
||||
leftMargin: 0,
|
||||
rightMargin: 0,
|
||||
runGutter: 0
|
||||
};
|
||||
|
||||
private async _createModifiedWebview(id: string, resource: URI): Promise<void> {
|
||||
if (this._modifiedWebview) {
|
||||
this._modifiedWebview.dispose();
|
||||
}
|
||||
|
||||
this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this.webviewOptions) as BackLayerWebView<IDiffCellInfo>;
|
||||
this._modifiedWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this._notebookOptions.computeDiffWebviewOptions()) as BackLayerWebView<IDiffCellInfo>;
|
||||
// attach the webview container to the DOM tree first
|
||||
this._list.rowsContainer.insertAdjacentElement('afterbegin', this._modifiedWebview.element);
|
||||
await this._modifiedWebview.createWebview();
|
||||
@@ -393,7 +391,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD
|
||||
this._originalWebview.dispose();
|
||||
}
|
||||
|
||||
this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this.webviewOptions) as BackLayerWebView<IDiffCellInfo>;
|
||||
this._originalWebview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this._notebookOptions.computeDiffWebviewOptions()) as BackLayerWebView<IDiffCellInfo>;
|
||||
// attach the webview container to the DOM tree first
|
||||
this._list.rowsContainer.insertAdjacentElement('afterbegin', this._originalWebview.element);
|
||||
await this._originalWebview.createWebview();
|
||||
|
||||
@@ -42,22 +42,6 @@ export interface INotebookRendererContribution {
|
||||
readonly [NotebookRendererContribution.optionalDependencies]: readonly string[];
|
||||
}
|
||||
|
||||
enum NotebookMarkupRendererContribution {
|
||||
id = 'id',
|
||||
displayName = 'displayName',
|
||||
entrypoint = 'entrypoint',
|
||||
dependsOn = 'dependsOn',
|
||||
mimeTypes = 'mimeTypes',
|
||||
}
|
||||
|
||||
export interface INotebookMarkupRendererContribution {
|
||||
readonly [NotebookMarkupRendererContribution.id]?: string;
|
||||
readonly [NotebookMarkupRendererContribution.displayName]: string;
|
||||
readonly [NotebookMarkupRendererContribution.entrypoint]: string;
|
||||
readonly [NotebookMarkupRendererContribution.dependsOn]: string | undefined;
|
||||
readonly [NotebookMarkupRendererContribution.mimeTypes]: string[] | undefined;
|
||||
}
|
||||
|
||||
const notebookProviderContribution: IJSONSchema = {
|
||||
description: nls.localize('contributes.notebook.provider', 'Contributes notebook document provider.'),
|
||||
type: 'array',
|
||||
@@ -164,48 +148,6 @@ const notebookRendererContribution: IJSONSchema = {
|
||||
}
|
||||
}
|
||||
};
|
||||
const notebookMarkupRendererContribution: IJSONSchema = {
|
||||
description: nls.localize('contributes.notebook.markdownRenderer', 'Contributes a renderer for markdown cells in notebooks.'),
|
||||
type: 'array',
|
||||
defaultSnippets: [{ body: [{ id: '', displayName: '', entrypoint: '' }] }],
|
||||
items: {
|
||||
type: 'object',
|
||||
required: [
|
||||
NotebookMarkupRendererContribution.id,
|
||||
NotebookMarkupRendererContribution.displayName,
|
||||
NotebookMarkupRendererContribution.entrypoint,
|
||||
],
|
||||
properties: {
|
||||
[NotebookMarkupRendererContribution.id]: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.notebook.markdownRenderer.id', 'Unique identifier of the notebook markdown renderer.'),
|
||||
},
|
||||
[NotebookMarkupRendererContribution.displayName]: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.notebook.markdownRenderer.displayName', 'Human readable name of the notebook markdown renderer.'),
|
||||
},
|
||||
[NotebookMarkupRendererContribution.entrypoint]: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.notebook.markdownRenderer.entrypoint', 'File to load in the webview to render the extension.'),
|
||||
},
|
||||
[NotebookMarkupRendererContribution.mimeTypes]: {
|
||||
type: 'array',
|
||||
items: { type: 'string' },
|
||||
description: nls.localize('contributes.notebook.markdownRenderer.mimeTypes', 'The mime type that the renderer handles.'),
|
||||
},
|
||||
[NotebookMarkupRendererContribution.dependsOn]: {
|
||||
type: 'string',
|
||||
description: nls.localize('contributes.notebook.markdownRenderer.dependsOn', 'If specified, this renderer augments another renderer instead of providing full rendering.'),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const notebooksExtensionPoint2 = ExtensionsRegistry.registerExtensionPoint<INotebookEditorContribution[]>(
|
||||
{
|
||||
extensionPoint: 'notebookProvider',
|
||||
jsonSchema: { deprecationMessage: 'Use \'notebooks\' instead' }
|
||||
});
|
||||
|
||||
export const notebooksExtensionPoint = ExtensionsRegistry.registerExtensionPoint<INotebookEditorContribution[]>(
|
||||
{
|
||||
@@ -218,9 +160,3 @@ export const notebookRendererExtensionPoint = ExtensionsRegistry.registerExtensi
|
||||
extensionPoint: 'notebookOutputRenderer',
|
||||
jsonSchema: notebookRendererContribution
|
||||
});
|
||||
|
||||
export const notebookMarkupRendererExtensionPoint = ExtensionsRegistry.registerExtensionPoint<INotebookMarkupRendererContribution[]>(
|
||||
{
|
||||
extensionPoint: 'notebookMarkupRenderers',
|
||||
jsonSchema: notebookMarkupRendererContribution
|
||||
});
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .kernel-action-view-item {
|
||||
border-radius: 5px;
|
||||
}
|
||||
.monaco-workbench .kernel-action-view-item:hover {
|
||||
background-color: var(--code-toolbarHoverBackground);
|
||||
}
|
||||
|
||||
.monaco-workbench .kernel-action-view-item .action-label {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.monaco-workbench .kernel-action-view-item .kernel-label {
|
||||
font-size: 11px;
|
||||
padding: 3px 5px 3px 3px;
|
||||
border-radius: 5px;
|
||||
height: 16px;
|
||||
display: inline-flex;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import { IListContextMenuEvent, IListEvent, IListMouseEvent } from 'vs/base/brow
|
||||
import { IListOptions, IListStyles } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ScrollEvent } from 'vs/base/common/scrollable';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -31,6 +31,7 @@ import { IResourceEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { CellEditorStatusBar } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
|
||||
import { INotebookWebviewMessage } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
|
||||
export const NOTEBOOK_EDITOR_ID = 'workbench.editor.notebook';
|
||||
export const NOTEBOOK_DIFF_EDITOR_ID = 'workbench.editor.notebookTextDiffEditor';
|
||||
@@ -382,6 +383,7 @@ export interface INotebookEditor extends ICommonNotebookEditor {
|
||||
readonly onDidScroll: Event<void>;
|
||||
|
||||
readonly onDidChangeActiveCell: Event<void>;
|
||||
readonly notebookOptions: NotebookOptions;
|
||||
isDisposed: boolean;
|
||||
dispose(): void;
|
||||
|
||||
@@ -908,20 +910,6 @@ export function getNotebookEditorFromEditorPane(editorPane?: IEditorPane): INote
|
||||
return editorPane?.getId() === NOTEBOOK_EDITOR_ID ? editorPane.getControl() as INotebookEditor | undefined : undefined;
|
||||
}
|
||||
|
||||
let EDITOR_TOP_PADDING = 12;
|
||||
const editorTopPaddingChangeEmitter = new Emitter<void>();
|
||||
|
||||
export const EditorTopPaddingChangeEvent = editorTopPaddingChangeEmitter.event;
|
||||
|
||||
export function updateEditorTopPadding(top: number) {
|
||||
EDITOR_TOP_PADDING = top;
|
||||
editorTopPaddingChangeEmitter.fire();
|
||||
}
|
||||
|
||||
export function getEditorTopPadding() {
|
||||
return EDITOR_TOP_PADDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* ranges: model selections
|
||||
* this will convert model selections to view indexes first, and then include the hidden ranges in the list view
|
||||
|
||||
@@ -29,6 +29,10 @@ import { NotebookEditorOptions, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/
|
||||
import { IBorrowValue, INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
|
||||
import { clearMarks, getAndClearMarks, mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { NotebooKernelActionViewItem } from 'vs/workbench/contrib/notebook/browser/notebookKernelActionViewItem';
|
||||
|
||||
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';
|
||||
|
||||
@@ -103,6 +107,14 @@ export class NotebookEditor extends EditorPane {
|
||||
return this._rootElement;
|
||||
}
|
||||
|
||||
override getActionViewItem(action: IAction): IActionViewItem | undefined {
|
||||
if (action.id === SELECT_KERNEL_ID) {
|
||||
// this is being disposed by the consumer
|
||||
return this.instantiationService.createInstance(NotebooKernelActionViewItem, action, this);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
override getControl(): NotebookEditorWidget | undefined {
|
||||
return this._widget.value;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { CellKind, INotebookKernel, INotebookTextModel, NotebookCellExecutionSta
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { SELECT_KERNEL_ID } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
|
||||
export class NotebookEditorKernelManager extends Disposable {
|
||||
|
||||
@@ -36,7 +37,7 @@ export class NotebookEditorKernelManager extends Disposable {
|
||||
|
||||
let kernel = this.getSelectedOrSuggestedKernel(notebook);
|
||||
if (!kernel) {
|
||||
await this._commandService.executeCommand('notebook.selectKernel');
|
||||
await this._commandService.executeCommand(SELECT_KERNEL_ID);
|
||||
kernel = this.getSelectedOrSuggestedKernel(notebook);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ import { IEditorMemento } from 'vs/workbench/common/editor';
|
||||
import { Memento, MementoObject } from 'vs/workbench/common/memento';
|
||||
import { PANEL_BORDER } from 'vs/workbench/common/theme';
|
||||
import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_OUTPUT_PADDING, CELL_RIGHT_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, MARKDOWN_CELL_BOTTOM_MARGIN, MARKDOWN_CELL_TOP_MARGIN, MARKDOWN_PREVIEW_PADDING, SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellEditState, CellFocusMode, IActiveNotebookEditor, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IGenericCellViewModel, IInsetRenderOutput, INotebookCellList, INotebookCellOutputLayoutInfo, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorMouseEvent, NotebookEditorOptions, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_ID, NOTEBOOK_OUTPUT_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookDecorationCSSRules, NotebookRefCountedStyleSheet } from 'vs/workbench/contrib/notebook/browser/notebookEditorDecorations';
|
||||
import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
|
||||
@@ -59,7 +58,7 @@ import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbenc
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, CellToolbarLocKey, CellToolbarVisibility, ExperimentalUseMarkdownRenderer, SelectionStateType, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, ExperimentalUseMarkdownRenderer, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
@@ -75,6 +74,9 @@ import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
|
||||
import { readFontInfo } from 'vs/editor/browser/config/configuration';
|
||||
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { NotebookEditorContextKeys } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidgetContextKeys';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
import { SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -203,6 +205,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
private _overlayContainer!: HTMLElement;
|
||||
private _notebookTopToolbarContainer!: HTMLElement;
|
||||
private _body!: HTMLElement;
|
||||
private _styleElement!: HTMLStyleElement;
|
||||
private _overflowContainer!: HTMLElement;
|
||||
private _webview: BackLayerWebView<ICommonCellInfo> | null = null;
|
||||
private _webviewResolvePromise: Promise<BackLayerWebView<ICommonCellInfo> | null> | null = null;
|
||||
@@ -213,7 +216,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
private _dndController: CellDragAndDropController | null = null;
|
||||
private _listTopCellToolbar: ListTopCellToolbar | null = null;
|
||||
private _renderedEditors: Map<ICellViewModel, ICodeEditor | undefined> = new Map();
|
||||
private _eventDispatcher: NotebookEventDispatcher | undefined;
|
||||
private _viewContext: ViewContext | undefined;
|
||||
private _notebookViewModel: NotebookViewModel | undefined;
|
||||
private _localStore: DisposableStore = this._register(new DisposableStore());
|
||||
private _localCellStateListeners: DisposableStore[] = [];
|
||||
@@ -306,6 +309,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
|
||||
public readonly scopedContextKeyService: IContextKeyService;
|
||||
private readonly instantiationService: IInstantiationService;
|
||||
private readonly _notebookOptions: NotebookOptions;
|
||||
|
||||
get notebookOptions() {
|
||||
return this._notebookOptions;
|
||||
}
|
||||
|
||||
constructor(
|
||||
readonly creationOptions: INotebookEditorCreationOptions,
|
||||
@@ -330,6 +338,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
this.isEmbedded = creationOptions.isEmbedded || false;
|
||||
|
||||
this.useRenderer = !isWeb && !!this.configurationService.getValue<boolean>(ExperimentalUseMarkdownRenderer) && !accessibilityService.isScreenReaderOptimized();
|
||||
this._notebookOptions = new NotebookOptions(this.configurationService);
|
||||
this._register(this._notebookOptions);
|
||||
|
||||
this._overlayContainer = document.createElement('div');
|
||||
this.scopedContextKeyService = contextKeyService.createScoped(this._overlayContainer);
|
||||
@@ -356,8 +366,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
this.layout(this._dimension);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
if (e.affectsConfiguration(CellToolbarLocKey) || e.affectsConfiguration(ShowCellStatusBarKey) || e.affectsConfiguration(CellToolbarVisibility)) {
|
||||
this._register(this._notebookOptions.onDidChangeOptions(e => {
|
||||
if (e.cellStatusBarVisibility || e.cellToolbarLocation || e.cellToolbarInteraction) {
|
||||
this._updateForNotebookConfiguration();
|
||||
}
|
||||
}));
|
||||
@@ -488,43 +500,16 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
return;
|
||||
}
|
||||
|
||||
const cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocKey);
|
||||
this._overlayContainer.classList.remove('cell-title-toolbar-left');
|
||||
this._overlayContainer.classList.remove('cell-title-toolbar-right');
|
||||
this._overlayContainer.classList.remove('cell-title-toolbar-hidden');
|
||||
const cellToolbarLocation = this._notebookOptions.computeCellToolbarLocation(this.viewModel?.viewType);
|
||||
this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`);
|
||||
|
||||
if (typeof cellToolbarLocation === 'string') {
|
||||
if (cellToolbarLocation === 'left' || cellToolbarLocation === 'right' || cellToolbarLocation === 'hidden') {
|
||||
this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocation}`);
|
||||
}
|
||||
} else {
|
||||
if (this.viewModel) {
|
||||
const notebookSpecificSetting = cellToolbarLocation[this.viewModel.viewType] ?? cellToolbarLocation['default'];
|
||||
let cellToolbarLocationForCurrentView = 'right';
|
||||
|
||||
switch (notebookSpecificSetting) {
|
||||
case 'left':
|
||||
cellToolbarLocationForCurrentView = 'left';
|
||||
break;
|
||||
case 'right':
|
||||
cellToolbarLocationForCurrentView = 'right';
|
||||
case 'hidden':
|
||||
cellToolbarLocationForCurrentView = 'hidden';
|
||||
default:
|
||||
cellToolbarLocationForCurrentView = 'right';
|
||||
break;
|
||||
}
|
||||
|
||||
this._overlayContainer.classList.add(`cell-title-toolbar-${cellToolbarLocationForCurrentView}`);
|
||||
} else {
|
||||
this._overlayContainer.classList.add(`cell-title-toolbar-right`);
|
||||
}
|
||||
}
|
||||
|
||||
const showCellStatusBar = this.configurationService.getValue<boolean>(ShowCellStatusBarKey);
|
||||
const showCellStatusBar = this._notebookOptions.getLayoutConfiguration().showCellStatusBar;
|
||||
this._overlayContainer.classList.toggle('cell-statusbar-hidden', !showCellStatusBar);
|
||||
|
||||
const cellToolbarInteraction = this.configurationService.getValue<string>(CellToolbarVisibility);
|
||||
const cellToolbarInteraction = this._notebookOptions.getLayoutConfiguration().cellToolbarInteraction;
|
||||
let cellToolbarInteractionState = 'hover';
|
||||
this._overlayContainer.classList.remove('cell-toolbar-hover');
|
||||
this._overlayContainer.classList.remove('cell-toolbar-click');
|
||||
@@ -547,15 +532,74 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
this._notebookTopToolbarContainer.style.display = 'none';
|
||||
DOM.append(parent, this._notebookTopToolbarContainer);
|
||||
this._body = document.createElement('div');
|
||||
this._body.classList.add('cell-list-container');
|
||||
this._createCellList();
|
||||
DOM.append(parent, this._body);
|
||||
this._body.classList.add('cell-list-container');
|
||||
this._createLayoutStyles();
|
||||
this._createCellList();
|
||||
|
||||
this._overflowContainer = document.createElement('div');
|
||||
this._overflowContainer.classList.add('notebook-overflow-widget-container', 'monaco-editor');
|
||||
DOM.append(parent, this._overflowContainer);
|
||||
}
|
||||
|
||||
private _createLayoutStyles(): void {
|
||||
this._styleElement = DOM.createStyleSheet(this._body);
|
||||
const {
|
||||
cellRightMargin,
|
||||
cellTopMargin,
|
||||
cellRunGutter,
|
||||
cellBottomMargin,
|
||||
codeCellLeftMargin,
|
||||
markdownCellBottomMargin,
|
||||
markdownCellTopMargin,
|
||||
bottomCellToolbarGap,
|
||||
bottomCellToolbarHeight,
|
||||
collapsedIndicatorHeight
|
||||
} = this._notebookOptions.getLayoutConfiguration();
|
||||
|
||||
const styleSheets: string[] = [];
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${codeCellLeftMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${codeCellLeftMargin + cellRunGutter}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell { margin-right: ${cellRightMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${cellTopMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${markdownCellBottomMargin}px; padding-top: ${markdownCellTopMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .output { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .output { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`);
|
||||
|
||||
styleSheets.push(`.notebookOverlay .output-show-more-container { margin: 0px ${cellRightMargin}px 0px ${codeCellLeftMargin + cellRunGutter}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .output-show-more-container { width: calc(100% - ${codeCellLeftMargin + cellRunGutter + cellRightMargin}px); }`);
|
||||
|
||||
styleSheets.push(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${cellRunGutter}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell .run-button-container { width: 20px; left: ${codeCellLeftMargin + Math.floor(cellRunGutter - 20) / 2}px }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${cellTopMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${bottomCellToolbarGap}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left,
|
||||
.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-drag-handle { width: ${codeCellLeftMargin + cellRunGutter}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .cell-focus-indicator-left { width: ${codeCellLeftMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${cellRightMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${cellBottomMargin}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${cellBottomMargin}px; }`);
|
||||
|
||||
styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-collapsed-part { margin-left: ${codeCellLeftMargin + cellRunGutter}px; height: ${collapsedIndicatorHeight}px; }`);
|
||||
styleSheets.push(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${SCROLLABLE_ELEMENT_PADDING_TOP}px }`);
|
||||
|
||||
styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { height: ${bottomCellToolbarHeight}px }`);
|
||||
styleSheets.push(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { height: ${bottomCellToolbarHeight}px }`);
|
||||
|
||||
// left and right border margins
|
||||
styleSheets.push(`
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-left:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-right:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-left:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before {
|
||||
top: -${cellTopMargin}px; height: calc(100% + ${cellTopMargin + cellBottomMargin}px)
|
||||
}`);
|
||||
|
||||
this._styleElement.textContent = styleSheets.join('\n');
|
||||
}
|
||||
|
||||
private _createCellList(): void {
|
||||
this._body.classList.add('cell-list-container');
|
||||
|
||||
@@ -1076,14 +1120,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
}
|
||||
|
||||
private async _createWebview(id: string, resource: URI): Promise<void> {
|
||||
this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, {
|
||||
outputNodePadding: CELL_OUTPUT_PADDING,
|
||||
outputNodeLeftPadding: CELL_OUTPUT_PADDING,
|
||||
previewNodePadding: MARKDOWN_PREVIEW_PADDING,
|
||||
leftMargin: CODE_CELL_LEFT_MARGIN,
|
||||
rightMargin: CELL_RIGHT_MARGIN,
|
||||
runGutter: CELL_RUN_GUTTER,
|
||||
});
|
||||
this._webview = this.instantiationService.createInstance(BackLayerWebView, this, id, resource, this._notebookOptions.computeWebviewOptions());
|
||||
this._webview.element.style.width = '100%';
|
||||
|
||||
// attach the webview container to the DOM tree first
|
||||
@@ -1093,9 +1130,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
private async _attachModel(textModel: NotebookTextModel, viewState: INotebookEditorViewState | undefined) {
|
||||
await this._createWebview(this.getId(), textModel.uri);
|
||||
|
||||
this._eventDispatcher = new NotebookEventDispatcher();
|
||||
this.viewModel = this.instantiationService.createInstance(NotebookViewModel, textModel.viewType, textModel, this._eventDispatcher, this.getLayoutInfo());
|
||||
this._eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
|
||||
this._viewContext = new ViewContext(this._notebookOptions, new NotebookEventDispatcher());
|
||||
this.viewModel = this.instantiationService.createInstance(NotebookViewModel, textModel.viewType, textModel, this._viewContext, this.getLayoutInfo());
|
||||
this._viewContext.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
|
||||
|
||||
this._updateForOptions();
|
||||
this._updateForNotebookConfiguration();
|
||||
@@ -1449,7 +1486,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
this._webviewTransparentCover.style.width = `${dimension.width}px`;
|
||||
}
|
||||
|
||||
this._eventDispatcher?.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
|
||||
this._viewContext?.eventDispatcher.emit([new NotebookLayoutChangedEvent({ width: true, fontInfo: true }, this.getLayoutInfo())]);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
@@ -2385,9 +2422,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
|
||||
updateMarkdownCellHeight(cellId: string, height: number, isInit: boolean) {
|
||||
const cell = this.getCellById(cellId);
|
||||
const layoutConfiguration = this._notebookOptions.getLayoutConfiguration();
|
||||
if (cell && cell instanceof MarkdownCellViewModel) {
|
||||
if (height + BOTTOM_CELL_TOOLBAR_GAP !== cell.layoutInfo.totalHeight) {
|
||||
this._debug('updateMarkdownCellHeight', cell.handle, height + BOTTOM_CELL_TOOLBAR_GAP, isInit);
|
||||
if (height + layoutConfiguration.bottomCellToolbarGap !== cell.layoutInfo.totalHeight) {
|
||||
this._debug('updateMarkdownCellHeight', cell.handle, height + layoutConfiguration.bottomCellToolbarGap, isInit);
|
||||
cell.renderedMarkdownHeight = height;
|
||||
}
|
||||
}
|
||||
@@ -2461,7 +2499,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
this._webviewTransparentCover = null;
|
||||
this._dndController = null;
|
||||
this._listTopCellToolbar = null;
|
||||
this._eventDispatcher = undefined;
|
||||
this._viewContext = undefined;
|
||||
this._notebookViewModel = undefined;
|
||||
this._cellContextKeyManager = null;
|
||||
this._renderedEditors.clear();
|
||||
@@ -2653,17 +2691,20 @@ registerThemingParticipant((theme, collector) => {
|
||||
collector.addRule(`.notebookOverlay .output-show-more-container { background-color: ${containerBackground}; }`);
|
||||
}
|
||||
|
||||
const notebookBackground = theme.getColor(editorBackground);
|
||||
if (notebookBackground) {
|
||||
collector.addRule(`.notebookOverlay .cell-drag-image .cell-editor-container > div { background: ${notebookBackground} !important; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list-row .cell-title-toolbar { background-color: ${notebookBackground}; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list-row.cell-drag-image { background-color: ${notebookBackground}; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container .action-item { background-color: ${notebookBackground} }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-top-cell-toolbar-container .action-item { background-color: ${notebookBackground} }`);
|
||||
}
|
||||
|
||||
const editorBackgroundColor = theme.getColor(cellEditorBackground) ?? theme.getColor(editorBackground);
|
||||
if (editorBackgroundColor) {
|
||||
collector.addRule(`.notebookOverlay .cell .monaco-editor-background,
|
||||
.notebookOverlay .cell .margin-view-overlays,
|
||||
.notebookOverlay .cell .cell-statusbar-container { background: ${editorBackgroundColor}; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-drag-image .cell-editor-container > div { background: ${editorBackgroundColor} !important; }`);
|
||||
|
||||
collector.addRule(`.notebookOverlay .monaco-list-row .cell-title-toolbar { background-color: ${editorBackgroundColor}; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list-row.cell-drag-image { background-color: ${editorBackgroundColor}; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-bottom-toolbar-container .action-item { background-color: ${editorBackgroundColor} }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-top-cell-toolbar-container .action-item { background-color: ${editorBackgroundColor} }`);
|
||||
.notebookOverlay .cell .margin-view-overlays,
|
||||
.notebookOverlay .cell .cell-statusbar-container { background: ${editorBackgroundColor}; }`);
|
||||
}
|
||||
|
||||
const cellToolbarSeperator = theme.getColor(CELL_TOOLBAR_SEPERATOR);
|
||||
@@ -2822,43 +2863,5 @@ registerThemingParticipant((theme, collector) => {
|
||||
}`);
|
||||
}
|
||||
|
||||
// Cell Margin
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row div.cell.code { margin-left: ${CODE_CELL_LEFT_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .code-cell-row div.cell.code { margin-left: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell { margin-right: ${CELL_RIGHT_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .cell-inner-container { padding-top: ${CELL_TOP_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container { padding-bottom: ${MARKDOWN_CELL_BOTTOM_MARGIN}px; padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .cell-inner-container.webview-backed-markdown-cell { padding: 0; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .markdown-cell-row > .webview-backed-markdown-cell.markdown-cell-edit-mode .cell.code { padding-bottom: ${MARKDOWN_CELL_BOTTOM_MARGIN}px; padding-top: ${MARKDOWN_CELL_TOP_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .output { margin: 0px ${CELL_RIGHT_MARGIN}px 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`);
|
||||
collector.addRule(`.notebookOverlay .output { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN}px); }`);
|
||||
|
||||
collector.addRule(`.notebookOverlay .output-show-more-container { margin: 0px ${CELL_RIGHT_MARGIN}px 0px ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`);
|
||||
collector.addRule(`.notebookOverlay .output-show-more-container { width: calc(100% - ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN}px); }`);
|
||||
|
||||
collector.addRule(`.notebookOverlay .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell .run-button-container { width: 20px; left: ${CODE_CELL_LEFT_MARGIN + Math.floor(CELL_RUN_GUTTER - 20) / 2}px }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row :not(.webview-backed-markdown-cell) .cell-focus-indicator-top { height: ${CELL_TOP_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-side { bottom: ${BOTTOM_CELL_TOOLBAR_GAP}px; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-focus-indicator-left,
|
||||
.notebookOverlay .monaco-list .monaco-list-row.code-cell-row .cell-drag-handle { width: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row.markdown-cell-row .cell-focus-indicator-left { width: ${CODE_CELL_LEFT_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator.cell-focus-indicator-right { width: ${CELL_RIGHT_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-focus-indicator-bottom { height: ${CELL_BOTTOM_MARGIN}px; }`);
|
||||
collector.addRule(`.notebookOverlay .monaco-list .monaco-list-row .cell-shadow-container-bottom { top: ${CELL_BOTTOM_MARGIN}px; }`);
|
||||
|
||||
collector.addRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-collapsed-part { margin-left: ${CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER}px; height: ${COLLAPSED_INDICATOR_HEIGHT}px; }`);
|
||||
collector.addRule(`.notebookOverlay .cell-list-top-cell-toolbar-container { top: -${SCROLLABLE_ELEMENT_PADDING_TOP}px }`);
|
||||
|
||||
collector.addRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell-bottom-toolbar-container { height: ${BOTTOM_CELL_TOOLBAR_HEIGHT}px }`);
|
||||
collector.addRule(`.monaco-workbench .notebookOverlay > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .cell-list-top-cell-toolbar-container { height: ${BOTTOM_CELL_TOOLBAR_HEIGHT}px }`);
|
||||
|
||||
// left and right border margins
|
||||
collector.addRule(`
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-left:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list .monaco-list-row.code-cell-row.focused .cell-focus-indicator-right:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-left:before,
|
||||
.monaco-workbench .notebookOverlay .monaco-list.selection-multiple .monaco-list-row.code-cell-row.selected .cell-focus-indicator-right:before {
|
||||
top: -${CELL_TOP_MARGIN}px; height: calc(100% + ${CELL_TOP_MARGIN + CELL_BOTTOM_MARGIN}px)
|
||||
}`);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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/notebookKernelActionViewItem';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor';
|
||||
import { selectKernelIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { INotebookKernelMatchResult, INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { toolbarHoverBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
const value = theme.getColor(toolbarHoverBackground);
|
||||
collector.addRule(`:root {
|
||||
--code-toolbarHoverBackground: ${value};
|
||||
}`);
|
||||
});
|
||||
|
||||
export class NotebooKernelActionViewItem extends ActionViewItem {
|
||||
|
||||
private _kernelLabel?: HTMLAnchorElement;
|
||||
|
||||
constructor(
|
||||
actualAction: IAction,
|
||||
private readonly _editor: NotebookEditor,
|
||||
@INotebookKernelService private readonly _notebookKernelService: INotebookKernelService,
|
||||
) {
|
||||
super(
|
||||
undefined,
|
||||
new Action('fakeAction', undefined, ThemeIcon.asClassName(selectKernelIcon), true, (event) => actualAction.run(event)),
|
||||
{ label: false, icon: true }
|
||||
);
|
||||
this._register(_editor.onDidChangeModel(this._update, this));
|
||||
this._register(_notebookKernelService.onDidChangeNotebookAffinity(this._update, this));
|
||||
this._register(_notebookKernelService.onDidChangeNotebookKernelBinding(this._update, this));
|
||||
}
|
||||
|
||||
override render(container: HTMLElement): void {
|
||||
this._update();
|
||||
super.render(container);
|
||||
container.classList.add('kernel-action-view-item');
|
||||
this._kernelLabel = document.createElement('a');
|
||||
container.appendChild(this._kernelLabel);
|
||||
this.updateLabel();
|
||||
}
|
||||
|
||||
override updateLabel() {
|
||||
if (this._kernelLabel) {
|
||||
this._kernelLabel.classList.add('kernel-label');
|
||||
this._kernelLabel.innerText = this._action.label;
|
||||
this._kernelLabel.title = this._action.tooltip;
|
||||
}
|
||||
}
|
||||
|
||||
private _update(): void {
|
||||
const widget = this._editor.getControl();
|
||||
if (!widget || !widget.hasModel()) {
|
||||
this._resetAction();
|
||||
return;
|
||||
}
|
||||
const notebook = widget.viewModel.notebookDocument;
|
||||
const info = this._notebookKernelService.getMatchingKernel(notebook);
|
||||
this._updateActionFromKernelInfo(info);
|
||||
}
|
||||
|
||||
private _updateActionFromKernelInfo(info: INotebookKernelMatchResult): void {
|
||||
|
||||
if (info.all.length === 0) {
|
||||
// should not happen - means "bad" context keys
|
||||
this._resetAction();
|
||||
return;
|
||||
}
|
||||
|
||||
this._action.enabled = true;
|
||||
const selectedOrSuggested = info.selected ?? info.suggested;
|
||||
if (selectedOrSuggested) {
|
||||
// selected or suggested kernel
|
||||
this._action.label = selectedOrSuggested.label;
|
||||
this._action.tooltip = selectedOrSuggested.description ?? selectedOrSuggested.detail ?? '';
|
||||
if (!info.selected) {
|
||||
// special UI for selected kernel?
|
||||
}
|
||||
|
||||
} else {
|
||||
// many kernels
|
||||
this._action.label = localize('select', "Select Kernel");
|
||||
this._action.tooltip = '';
|
||||
}
|
||||
}
|
||||
|
||||
private _resetAction(): void {
|
||||
this._action.enabled = false;
|
||||
this._action.label = '';
|
||||
this._action.class = '';
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,14 @@ import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.pr
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { Memento } from 'vs/workbench/common/memento';
|
||||
import { INotebookEditorContribution, notebookMarkupRendererExtensionPoint, notebooksExtensionPoint, notebookRendererExtensionPoint, notebooksExtensionPoint2 } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
|
||||
import { NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { INotebookEditorContribution, notebooksExtensionPoint, notebookRendererExtensionPoint } from 'vs/workbench/contrib/notebook/browser/extensionPoint';
|
||||
import { NotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookMarkupRendererInfo, INotebookContributionData, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookContributionData, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
|
||||
import { NotebookMarkupRendererInfo as NotebookMarkupRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookMarkdownRenderer';
|
||||
import { updateEditorTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer';
|
||||
import { NotebookEditorDescriptor, NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
import { ComplexNotebookProviderInfo, INotebookContentProvider, INotebookSerializer, INotebookService, SimpleNotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
@@ -81,7 +81,6 @@ export class NotebookProviderInfoStore extends Disposable {
|
||||
}));
|
||||
|
||||
notebooksExtensionPoint.setHandler(extensions => this._setupHandler(extensions));
|
||||
notebooksExtensionPoint2.setHandler(extensions => this._setupHandler(extensions));
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
@@ -250,6 +249,10 @@ export class NotebookOutputRendererInfoStore {
|
||||
return this.contributedRenderers.get(rendererId);
|
||||
}
|
||||
|
||||
getAll(): NotebookOutputRendererInfo[] {
|
||||
return Array.from(this.contributedRenderers.values());
|
||||
}
|
||||
|
||||
add(info: NotebookOutputRendererInfo): void {
|
||||
if (this.contributedRenderers.has(info.id)) {
|
||||
return;
|
||||
@@ -302,7 +305,6 @@ export class NotebookService extends Disposable implements INotebookService {
|
||||
private readonly _notebookProviders = new Map<string, ComplexNotebookProviderInfo | SimpleNotebookProviderInfo>();
|
||||
private readonly _notebookProviderInfoStore: NotebookProviderInfoStore;
|
||||
private readonly _notebookRenderersInfoStore = this._instantiationService.createInstance(NotebookOutputRendererInfoStore);
|
||||
private readonly _markdownRenderersInfos = new Set<INotebookMarkupRendererInfo>();
|
||||
private readonly _models = new ResourceMap<ModelData>();
|
||||
|
||||
private readonly _onWillAddNotebookDocument = this._register(new Emitter<NotebookTextModel>());
|
||||
@@ -369,38 +371,6 @@ export class NotebookService extends Disposable implements INotebookService {
|
||||
}
|
||||
}
|
||||
});
|
||||
notebookMarkupRendererExtensionPoint.setHandler((renderers) => {
|
||||
this._markdownRenderersInfos.clear();
|
||||
|
||||
for (const extension of renderers) {
|
||||
if (!extension.description.enableProposedApi && !extension.description.isBuiltin) {
|
||||
// Only allow proposed extensions to use this extension point
|
||||
return;
|
||||
}
|
||||
|
||||
for (const notebookContribution of extension.value) {
|
||||
if (!notebookContribution.entrypoint) { // avoid crashing
|
||||
console.error(`Cannot register renderer for ${extension.description.identifier.value} since it did not have an entrypoint. This is now required: https://github.com/microsoft/vscode/issues/102644`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const id = notebookContribution.id;
|
||||
if (!id) {
|
||||
console.error(`Notebook renderer from ${extension.description.identifier.value} is missing an 'id'`);
|
||||
continue;
|
||||
}
|
||||
|
||||
this._markdownRenderersInfos.add(new NotebookMarkupRendererInfo({
|
||||
id,
|
||||
extension: extension.description,
|
||||
entrypoint: notebookContribution.entrypoint,
|
||||
displayName: notebookContribution.displayName,
|
||||
mimeTypes: notebookContribution.mimeTypes,
|
||||
dependsOn: notebookContribution.dependsOn,
|
||||
}));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const updateOrder = () => {
|
||||
const userOrder = this._configurationService.getValue<string[]>(DisplayOrderKey);
|
||||
@@ -552,8 +522,8 @@ export class NotebookService extends Disposable implements INotebookService {
|
||||
this._notebookRenderersInfoStore.setPreferred(mimeType, rendererId);
|
||||
}
|
||||
|
||||
getMarkupRendererInfo(): INotebookMarkupRendererInfo[] {
|
||||
return Array.from(this._markdownRenderersInfos);
|
||||
getRenderers(): INotebookRendererInfo[] {
|
||||
return this._notebookRenderersInfoStore.getAll();
|
||||
}
|
||||
|
||||
// --- notebook documents: create, destory, retrieve, enumerate
|
||||
|
||||
@@ -9,36 +9,35 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { ICellOutputViewModel, ICommonNotebookEditor, IOutputTransformContribution, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
export class OutputRenderer extends Disposable {
|
||||
protected _contributions: { [key: string]: IOutputTransformContribution; };
|
||||
protected _renderers: IOutputTransformContribution[];
|
||||
private _richMimeTypeRenderers = new Map<string, IOutputTransformContribution>();
|
||||
|
||||
private readonly _richMimeTypeRenderers = new Map<string, IOutputTransformContribution>();
|
||||
|
||||
constructor(
|
||||
notebookEditor: ICommonNotebookEditor,
|
||||
private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
|
||||
this._contributions = {};
|
||||
this._renderers = [];
|
||||
|
||||
const contributions = NotebookRegistry.getOutputTransformContributions();
|
||||
|
||||
for (const desc of contributions) {
|
||||
for (const desc of NotebookRegistry.getOutputTransformContributions()) {
|
||||
try {
|
||||
const contribution = this.instantiationService.createInstance(desc.ctor, notebookEditor);
|
||||
this._contributions[desc.id] = contribution;
|
||||
contribution.getMimetypes().forEach(mimetype => {
|
||||
this._richMimeTypeRenderers.set(mimetype, contribution);
|
||||
});
|
||||
this._register(contribution);
|
||||
} catch (err) {
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
this._richMimeTypeRenderers.clear();
|
||||
}
|
||||
|
||||
getContribution(preferredMimeType: string | undefined): IOutputTransformContribution | undefined {
|
||||
if (preferredMimeType) {
|
||||
return this._richMimeTypeRenderers.get(preferredMimeType);
|
||||
@@ -47,17 +46,16 @@ export class OutputRenderer extends Disposable {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
renderNoop(viewModel: ICellOutputViewModel, container: HTMLElement): IRenderOutput {
|
||||
private _renderNoop(viewModel: ICellOutputViewModel, container: HTMLElement): IRenderOutput {
|
||||
const contentNode = document.createElement('p');
|
||||
|
||||
contentNode.innerText = `No renderer could be found for output.`;
|
||||
contentNode.innerText = localize('empty', "No renderer could be found for output.");
|
||||
container.appendChild(contentNode);
|
||||
return { type: RenderOutputType.Mainframe };
|
||||
}
|
||||
|
||||
render(viewModel: ICellOutputViewModel, container: HTMLElement, preferredMimeType: string | undefined, notebookUri: URI): IRenderOutput {
|
||||
if (!viewModel.model.outputs.length) {
|
||||
return this.renderNoop(viewModel, container);
|
||||
return this._renderNoop(viewModel, container);
|
||||
}
|
||||
|
||||
if (!preferredMimeType || !this._richMimeTypeRenderers.has(preferredMimeType)) {
|
||||
@@ -67,9 +65,9 @@ export class OutputRenderer extends Disposable {
|
||||
const mimeTypesMessage = mimeTypes.join(', ');
|
||||
|
||||
if (preferredMimeType) {
|
||||
contentNode.innerText = `No renderer could be found for MIME type: ${preferredMimeType}`;
|
||||
contentNode.innerText = localize('noRenderer.1', "No renderer could be found for MIME type: {0}", preferredMimeType);
|
||||
} else {
|
||||
contentNode.innerText = `No renderer could be found for output. It has the following MIME types: ${mimeTypesMessage}`;
|
||||
contentNode.innerText = localize('noRenderer.2', "No renderer could be found for output. It has the following MIME types: {0}", mimeTypesMessage);
|
||||
}
|
||||
|
||||
container.appendChild(contentNode);
|
||||
@@ -82,13 +80,7 @@ export class OutputRenderer extends Disposable {
|
||||
if (items.length && renderer) {
|
||||
return renderer.render(viewModel, items, container, notebookUri);
|
||||
} else {
|
||||
return this.renderNoop(viewModel, container);
|
||||
return this._renderNoop(viewModel, container);
|
||||
}
|
||||
}
|
||||
|
||||
override dispose() {
|
||||
this._contributions = {};
|
||||
this._renderers = [];
|
||||
this._richMimeTypeRenderers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
import { isArray } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -14,6 +14,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { handleANSIOutput } from 'vs/workbench/contrib/debug/browser/debugANSIHandling';
|
||||
@@ -120,6 +121,8 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut
|
||||
return ['text/x-javascript'];
|
||||
}
|
||||
|
||||
private readonly _cellDisposables = new Map<number, DisposableStore>();
|
||||
|
||||
constructor(
|
||||
public notebookEditor: ICommonNotebookEditor,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@@ -129,7 +132,19 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut
|
||||
super();
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
dispose(this._cellDisposables.values());
|
||||
this._cellDisposables.clear();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
|
||||
let cellDisposables = this._cellDisposables.get(output.cellViewModel.handle);
|
||||
cellDisposables?.dispose();
|
||||
cellDisposables = new DisposableStore();
|
||||
this._cellDisposables.set(output.cellViewModel.handle, cellDisposables);
|
||||
|
||||
const str = items.map(item => getStringValue(item.value)).join('');
|
||||
const editor = this.instantiationService.createInstance(CodeEditorWidget, container, {
|
||||
...getOutputSimpleEditorOptions(),
|
||||
@@ -155,6 +170,9 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut
|
||||
width
|
||||
});
|
||||
|
||||
cellDisposables.add(editor);
|
||||
cellDisposables.add(textModel);
|
||||
|
||||
container.style.height = `${height + 8}px`;
|
||||
|
||||
return { type: RenderOutputType.Mainframe };
|
||||
@@ -260,6 +278,64 @@ class ErrorRendererContrib extends Disposable implements IOutputRendererContribu
|
||||
}
|
||||
}
|
||||
|
||||
class JSErrorRendererContrib implements IOutputRendererContribution {
|
||||
|
||||
constructor(
|
||||
public notebookEditor: ICommonNotebookEditor,
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
) { }
|
||||
|
||||
dispose(): void {
|
||||
// nothing
|
||||
}
|
||||
|
||||
getType() {
|
||||
return RenderOutputType.Mainframe;
|
||||
}
|
||||
|
||||
getMimetypes() {
|
||||
return ['application/x.notebook.error'];
|
||||
}
|
||||
|
||||
render(_output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, _notebookUri: URI): IRenderOutput {
|
||||
const linkDetector = this._instantiationService.createInstance(LinkDetector);
|
||||
|
||||
for (let item of items) {
|
||||
|
||||
if (typeof item.value !== 'string') {
|
||||
this._logService.warn('INVALID output item (not a string)', item.value);
|
||||
continue;
|
||||
}
|
||||
|
||||
let err: Error;
|
||||
try {
|
||||
err = <Error>JSON.parse(item.value);
|
||||
} catch (e) {
|
||||
this._logService.warn('INVALID output item (failed to parse)', e);
|
||||
continue;
|
||||
}
|
||||
|
||||
const header = document.createElement('div');
|
||||
const headerMessage = err.name && err.message ? `${err.name}: ${err.message}` : err.name || err.message;
|
||||
if (headerMessage) {
|
||||
header.innerText = headerMessage;
|
||||
container.appendChild(header);
|
||||
}
|
||||
const stack = document.createElement('pre');
|
||||
stack.classList.add('traceback');
|
||||
if (err.stack) {
|
||||
stack.appendChild(handleANSIOutput(err.stack, linkDetector, this._themeService, undefined));
|
||||
}
|
||||
container.appendChild(stack);
|
||||
container.classList.add('error');
|
||||
}
|
||||
|
||||
return { type: RenderOutputType.Mainframe };
|
||||
}
|
||||
}
|
||||
|
||||
class PlainTextRendererContrib extends Disposable implements IOutputRendererContribution {
|
||||
getType() {
|
||||
return RenderOutputType.Mainframe;
|
||||
@@ -442,6 +518,7 @@ NotebookRegistry.registerOutputTransform('jpeg', JPEGRendererContrib);
|
||||
NotebookRegistry.registerOutputTransform('plain', PlainTextRendererContrib);
|
||||
NotebookRegistry.registerOutputTransform('code', CodeRendererContrib);
|
||||
NotebookRegistry.registerOutputTransform('error-trace', ErrorRendererContrib);
|
||||
NotebookRegistry.registerOutputTransform('jserror', JSErrorRendererContrib);
|
||||
NotebookRegistry.registerOutputTransform('stream-text', StreamRendererContrib);
|
||||
NotebookRegistry.registerOutputTransform('stderr', StderrRendererContrib);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import { CellEditState, ICellOutputViewModel, ICommonCellInfo, ICommonNotebookEd
|
||||
import { preloadsScriptStr, WebviewPreloadRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads';
|
||||
import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { INotebookKernel, INotebookRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookKernel, INotebookRendererInfo, NotebookRendererMatch } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IWebviewService, WebviewContentPurpose, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
@@ -713,41 +713,41 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
||||
}
|
||||
|
||||
private getMarkdownRenderer(): WebviewPreloadRenderer[] {
|
||||
const allRenderers = this.notebookService.getMarkupRendererInfo();
|
||||
|
||||
const markdownMimeType = 'text/markdown';
|
||||
const allRenderers = this.notebookService.getRenderers()
|
||||
.filter(renderer => renderer.matchesWithoutKernel(markdownMimeType) !== NotebookRendererMatch.Never);
|
||||
|
||||
const topLevelMarkdownRenderers = allRenderers
|
||||
.filter(renderer => !renderer.dependsOn)
|
||||
.filter(renderer => renderer.mimeTypes?.includes(markdownMimeType));
|
||||
.filter(renderer => renderer.dependencies.length === 0);
|
||||
|
||||
const subRenderers = new Map<string, Array<{ entrypoint: string }>>();
|
||||
for (const renderer of allRenderers) {
|
||||
if (renderer.dependsOn) {
|
||||
if (!subRenderers.has(renderer.dependsOn)) {
|
||||
subRenderers.set(renderer.dependsOn, []);
|
||||
for (const dep of renderer.dependencies) {
|
||||
if (!subRenderers.has(dep)) {
|
||||
subRenderers.set(dep, []);
|
||||
}
|
||||
const entryPoint = this.asWebviewUri(renderer.entrypoint);
|
||||
subRenderers.get(renderer.dependsOn)!.push({ entrypoint: entryPoint.toString(true) });
|
||||
const entryPoint = this.asWebviewUri(renderer.entrypoint, renderer.extensionLocation);
|
||||
subRenderers.get(dep)!.push({ entrypoint: entryPoint.toString(true) });
|
||||
}
|
||||
}
|
||||
|
||||
return topLevelMarkdownRenderers.map((renderer): WebviewPreloadRenderer => {
|
||||
const src = this.asWebviewUri(renderer.entrypoint);
|
||||
const src = this.asWebviewUri(renderer.entrypoint, renderer.extensionLocation);
|
||||
return {
|
||||
entrypoint: src.toString(),
|
||||
mimeTypes: [markdownMimeType],
|
||||
mimeTypes: renderer.mimeTypes,
|
||||
dependencies: subRenderers.get(renderer.id) || [],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private asWebviewUri(uri: URI) {
|
||||
private asWebviewUri(uri: URI, fromExtension: URI | undefined) {
|
||||
const remoteAuthority = fromExtension?.scheme === Schemas.vscodeRemote ? fromExtension.authority : undefined;
|
||||
return asWebviewUri({
|
||||
isExtensionDevelopmentDebug: this.environmentService.isExtensionDevelopment,
|
||||
webviewCspSource: this.environmentService.webviewCspSource,
|
||||
webviewResourceRoot: this.environmentService.webviewResourceRoot,
|
||||
remote: { authority: undefined } // TODO
|
||||
remote: { authority: remoteAuthority }
|
||||
}, this.id, uri);
|
||||
}
|
||||
|
||||
@@ -781,11 +781,11 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
||||
resolveFunc = resolve;
|
||||
});
|
||||
|
||||
const baseUrl = this.asWebviewUri(dirname(this.documentUri));
|
||||
const baseUrl = this.asWebviewUri(dirname(this.documentUri), undefined);
|
||||
|
||||
if (!isWeb) {
|
||||
const loaderUri = FileAccess.asFileUri('vs/loader.js', require);
|
||||
const loader = this.asWebviewUri(loaderUri);
|
||||
const loader = this.asWebviewUri(loaderUri, undefined);
|
||||
|
||||
coreDependencies = `<script src="${loader}"></script><script>
|
||||
var requirejs = (function() {
|
||||
@@ -1131,7 +1131,7 @@ var requirejs = (function() {
|
||||
|
||||
this.localResourceRootsCache = [
|
||||
...this.notebookService.getNotebookProviderResourceRoots(),
|
||||
...this.notebookService.getMarkupRendererInfo().map(x => dirname(x.entrypoint)),
|
||||
...this.notebookService.getRenderers().map(x => dirname(x.entrypoint)),
|
||||
...workspaceFolders,
|
||||
rootPath,
|
||||
];
|
||||
@@ -1145,7 +1145,6 @@ var requirejs = (function() {
|
||||
allowMultipleAPIAcquire: true,
|
||||
allowScripts: true,
|
||||
localResourceRoots: this.localResourceRootsCache,
|
||||
useRootAuthority: true
|
||||
}, undefined);
|
||||
|
||||
webview.html = content;
|
||||
@@ -1572,7 +1571,7 @@ var requirejs = (function() {
|
||||
const resources: IPreloadResource[] = [];
|
||||
for (const preload of kernel.preloadUris) {
|
||||
const uri = this.environmentService.isExtensionDevelopment && (preload.scheme === 'http' || preload.scheme === 'https')
|
||||
? preload : this.asWebviewUri(preload);
|
||||
? preload : this.asWebviewUri(preload, undefined);
|
||||
|
||||
if (!this._preloadsCache.has(uri.toString())) {
|
||||
resources.push({ uri: uri.toString(), originalUri: preload.toString(), source: 'kernel' });
|
||||
@@ -1598,7 +1597,7 @@ var requirejs = (function() {
|
||||
for (const rendererInfo of renderers) {
|
||||
extensionLocations.push(rendererInfo.extensionLocation);
|
||||
for (const preload of [rendererInfo.entrypoint, ...rendererInfo.preloads]) {
|
||||
const uri = this.asWebviewUri(preload);
|
||||
const uri = this.asWebviewUri(preload, rendererInfo.extensionLocation);
|
||||
const resource: IPreloadResource = {
|
||||
uri: uri.toString(),
|
||||
originalUri: preload.toString(),
|
||||
|
||||
@@ -9,7 +9,6 @@ import { domEvent } from 'vs/base/browser/event';
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { BaseCellRenderTemplate, expandCellRangesWithHiddenCells, ICellViewModel, INotebookCellList, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { cloneNotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { CellEditType, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
@@ -157,7 +156,8 @@ export class CellDragAndDropController extends Disposable {
|
||||
}
|
||||
|
||||
private updateInsertIndicator(dropDirection: string, insertionIndicatorAbsolutePos: number) {
|
||||
const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + BOTTOM_CELL_TOOLBAR_GAP / 2;
|
||||
const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration();
|
||||
const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + layoutInfo.bottomCellToolbarGap / 2;
|
||||
if (insertionIndicatorTop >= 0) {
|
||||
this.listInsertionIndicator.style.top = `${insertionIndicatorTop}px`;
|
||||
this.setInsertIndicatorVisibility(true);
|
||||
@@ -199,7 +199,8 @@ export class CellDragAndDropController extends Disposable {
|
||||
const cellTop = this.list.getAbsoluteTopOfElement(draggedOverCell);
|
||||
const cellHeight = this.list.elementHeight(draggedOverCell);
|
||||
const insertionIndicatorAbsolutePos = dropDirection === 'above' ? cellTop : cellTop + cellHeight;
|
||||
const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + BOTTOM_CELL_TOOLBAR_GAP / 2;
|
||||
const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration();
|
||||
const insertionIndicatorTop = insertionIndicatorAbsolutePos - this.list.scrollTop + layoutInfo.bottomCellToolbarGap / 2;
|
||||
const editorHeight = this.notebookEditor.getDomNode().getBoundingClientRect().height;
|
||||
if (insertionIndicatorTop < 0 || insertionIndicatorTop > editorHeight) {
|
||||
// Ignore drop, insertion point is off-screen
|
||||
|
||||
@@ -10,15 +10,14 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IEditorOptions, LineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { EDITOR_BOTTOM_PADDING, EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { EditorTopPaddingChangeEvent, getEditorTopPadding, getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { NOTEBOOK_ACTIONS_CATEGORY } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
|
||||
export class CellEditorOptions extends Disposable {
|
||||
|
||||
@@ -48,27 +47,24 @@ export class CellEditorOptions extends Disposable {
|
||||
private readonly _onDidChange = new Emitter<IEditorOptions>();
|
||||
readonly onDidChange: Event<IEditorOptions> = this._onDidChange.event;
|
||||
|
||||
constructor(readonly configurationService: IConfigurationService, language: string) {
|
||||
constructor(readonly notebookOptions: NotebookOptions, readonly configurationService: IConfigurationService, language: string) {
|
||||
super();
|
||||
this._register(configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('editor') || e.affectsConfiguration('notebook') || e.affectsConfiguration(ShowCellStatusBarKey)) {
|
||||
if (e.affectsConfiguration('editor') || e.affectsConfiguration('notebook')) {
|
||||
this._value = computeEditorOptions();
|
||||
this._onDidChange.fire(this.value);
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(EditorTopPaddingChangeEvent(() => {
|
||||
this._value = computeEditorOptions();
|
||||
this._onDidChange.fire(this.value);
|
||||
this._register(notebookOptions.onDidChangeOptions(e => {
|
||||
if (e.cellStatusBarVisibility || e.editorTopPadding) {
|
||||
this._value = computeEditorOptions();
|
||||
this._onDidChange.fire(this.value);
|
||||
}
|
||||
}));
|
||||
|
||||
const computeEditorOptions = () => {
|
||||
const showCellStatusBar = configurationService.getValue<boolean>(ShowCellStatusBarKey);
|
||||
const editorPadding = {
|
||||
top: getEditorTopPadding(),
|
||||
bottom: showCellStatusBar ? EDITOR_BOTTOM_PADDING : EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR
|
||||
};
|
||||
|
||||
const editorPadding = this.notebookOptions.computeEditorPadding();
|
||||
const renderLiNumbers = configurationService.getValue<'on' | 'off'>('notebook.lineNumbers') === 'on';
|
||||
const lineNumbers: LineNumbersType = renderLiNumbers ? 'on' : 'off';
|
||||
const editorOptions = deepClone(configurationService.getValue<IEditorOptions>('editor', { overrideIdentifier: language }));
|
||||
|
||||
@@ -13,7 +13,7 @@ import { IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/commo
|
||||
import { CodeCellRenderTemplate, ICellOutputViewModel, IInsetRenderOutput, INotebookEditor, IRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { BUILTIN_RENDERER_ID, CellUri, NotebookCellOutputsSplice, IOrderedMimeType, mimeTypeIsAlwaysSecure, INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { BUILTIN_RENDERER_ID, CellUri, NotebookCellOutputsSplice, IOrderedMimeType, INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
||||
@@ -444,18 +444,7 @@ export class CellOutputContainer extends Disposable {
|
||||
}
|
||||
|
||||
private _calcuateOutputsToRender(): ICellOutputViewModel[] {
|
||||
const outputs = this.viewCell.outputsViewModels.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputsViewModels.length));
|
||||
if (!this.notebookEditor.viewModel!.metadata.trusted) {
|
||||
// not trusted
|
||||
const secureOutput = outputs.filter(output => {
|
||||
const mimeTypes = output.model.outputs.map(op => op.mime);
|
||||
return mimeTypes.some(mimeTypeIsAlwaysSecure);
|
||||
});
|
||||
|
||||
return secureOutput;
|
||||
}
|
||||
|
||||
return outputs;
|
||||
return this.viewCell.outputsViewModels.slice(0, Math.min(OUTPUT_COUNT_LIMIT, this.viewCell.outputsViewModels.length));
|
||||
}
|
||||
|
||||
private _outputHeightTimer: any = null;
|
||||
|
||||
@@ -35,7 +35,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP, CELL_BOTTOM_MARGIN, CELL_TOP_MARGIN, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { DeleteCellAction, INotebookActionContext, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/coreActions';
|
||||
import { BaseCellRenderTemplate, CellEditState, CodeCellLayoutInfo, CodeCellRenderTemplate, EXPAND_CELL_INPUT_COMMAND_ID, ICellViewModel, INotebookEditor, isCodeCellRenderTemplate, MarkdownCellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellContextKeyManager } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellContextKeys';
|
||||
@@ -100,7 +99,7 @@ abstract class AbstractCellRenderer {
|
||||
language: string,
|
||||
protected dndController: CellDragAndDropController | undefined,
|
||||
) {
|
||||
this.editorOptions = new CellEditorOptions(configurationService, language);
|
||||
this.editorOptions = new CellEditorOptions(notebookEditor.notebookOptions, configurationService, language);
|
||||
this.cellMenus = this.instantiationService.createInstance(CellMenus);
|
||||
}
|
||||
|
||||
@@ -184,17 +183,18 @@ abstract class AbstractCellRenderer {
|
||||
this.notebookEditor.focus();
|
||||
}
|
||||
|
||||
const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration();
|
||||
if (actions.primary.length || actions.secondary.length) {
|
||||
templateData.container.classList.add('cell-has-toolbar-actions');
|
||||
if (isCodeCellRenderTemplate(templateData)) {
|
||||
templateData.focusIndicatorLeft.style.top = `${EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN}px`;
|
||||
templateData.focusIndicatorRight.style.top = `${EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN}px`;
|
||||
templateData.focusIndicatorLeft.style.top = `${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px`;
|
||||
templateData.focusIndicatorRight.style.top = `${layoutInfo.editorToolbarHeight + layoutInfo.cellTopMargin}px`;
|
||||
}
|
||||
} else {
|
||||
templateData.container.classList.remove('cell-has-toolbar-actions');
|
||||
if (isCodeCellRenderTemplate(templateData)) {
|
||||
templateData.focusIndicatorLeft.style.top = `${CELL_TOP_MARGIN}px`;
|
||||
templateData.focusIndicatorRight.style.top = `${CELL_TOP_MARGIN}px`;
|
||||
templateData.focusIndicatorLeft.style.top = `${layoutInfo.cellTopMargin}px`;
|
||||
templateData.focusIndicatorRight.style.top = `${layoutInfo.cellTopMargin}px`;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -467,7 +467,7 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
|
||||
}));
|
||||
|
||||
this.updateForHover(element, templateData);
|
||||
const cellEditorOptions = new CellEditorOptions(this.configurationService, 'markdown');
|
||||
const cellEditorOptions = new CellEditorOptions(this.notebookEditor.notebookOptions, this.configurationService, 'markdown');
|
||||
cellEditorOptions.setLineNumbers(element.lineNumbers);
|
||||
elementDisposables.add(cellEditorOptions);
|
||||
|
||||
@@ -508,11 +508,10 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
|
||||
}
|
||||
|
||||
private updateForLayout(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void {
|
||||
templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP - CELL_BOTTOM_MARGIN}px`;
|
||||
|
||||
const focusSideHeight = element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP;
|
||||
templateData.focusIndicatorLeft.style.height = `${focusSideHeight}px`;
|
||||
templateData.focusIndicatorRight.style.height = `${focusSideHeight}px`;
|
||||
const indicatorPostion = this.notebookEditor.notebookOptions.computeIndicatorPosition(element.layoutInfo.totalHeight);
|
||||
templateData.focusIndicatorBottom.style.top = `${indicatorPostion.bottomIndicatorTop}px`;
|
||||
templateData.focusIndicatorLeft.style.height = `${indicatorPostion.verticalIndicatorHeight}px`;
|
||||
templateData.focusIndicatorRight.style.height = `${indicatorPostion.verticalIndicatorHeight}px`;
|
||||
}
|
||||
|
||||
private updateForHover(element: MarkdownCellViewModel, templateData: MarkdownCellRenderTemplate): void {
|
||||
@@ -879,12 +878,13 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
}
|
||||
|
||||
private updateForLayout(element: CodeCellViewModel, templateData: CodeCellRenderTemplate): void {
|
||||
const layoutInfo = this.notebookEditor.notebookOptions.getLayoutConfiguration();
|
||||
templateData.focusIndicatorLeft.style.height = `${element.layoutInfo.indicatorHeight}px`;
|
||||
templateData.focusIndicatorRight.style.height = `${element.layoutInfo.indicatorHeight}px`;
|
||||
templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP - CELL_BOTTOM_MARGIN}px`;
|
||||
templateData.focusIndicatorBottom.style.top = `${element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap - layoutInfo.cellBottomMargin}px`;
|
||||
templateData.outputContainer.style.top = `${element.layoutInfo.outputContainerOffset}px`;
|
||||
templateData.outputShowMoreContainer.style.top = `${element.layoutInfo.outputShowMoreContainerOffset}px`;
|
||||
templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - BOTTOM_CELL_TOOLBAR_GAP}px`;
|
||||
templateData.dragHandle.style.height = `${element.layoutInfo.totalHeight - layoutInfo.bottomCellToolbarGap}px`;
|
||||
}
|
||||
|
||||
renderElement(element: CodeCellViewModel, index: number, templateData: CodeCellRenderTemplate, height: number | undefined): void {
|
||||
@@ -938,7 +938,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
elementDisposables.add(this.instantiationService.createInstance(CodeCell, this.notebookEditor, element, templateData));
|
||||
this.renderedEditors.set(element, templateData.editor);
|
||||
|
||||
const cellEditorOptions = new CellEditorOptions(this.configurationService, element.language);
|
||||
const cellEditorOptions = new CellEditorOptions(this.notebookEditor.notebookOptions, this.configurationService, element.language);
|
||||
elementDisposables.add(cellEditorOptions);
|
||||
elementDisposables.add(cellEditorOptions.onDidChange(newValue => templateData.editor.updateOptions(newValue)));
|
||||
templateData.editor.updateOptions(cellEditorOptions.value);
|
||||
|
||||
@@ -10,8 +10,7 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDimension } from 'vs/editor/common/editorCommon';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellFocusMode, CodeCellRenderTemplate, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellFocusMode, CodeCellRenderTemplate, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellOutputContainer } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellOutput';
|
||||
import { ClickTargetType } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellWidgets';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
@@ -40,8 +39,10 @@ export class CodeCell extends Disposable {
|
||||
const width = this.viewCell.layoutInfo.editorWidth;
|
||||
const lineNum = this.viewCell.lineCount;
|
||||
const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17;
|
||||
const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding();
|
||||
|
||||
const editorHeight = this.viewCell.layoutInfo.editorHeight === 0
|
||||
? lineNum * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING
|
||||
? lineNum * lineHeight + editorPadding.top + editorPadding.bottom
|
||||
: this.viewCell.layoutInfo.editorHeight;
|
||||
|
||||
this.layoutEditor(
|
||||
|
||||
@@ -10,8 +10,7 @@ import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposab
|
||||
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellEditState, CellFocusMode, MarkdownCellRenderTemplate, ICellViewModel, getEditorTopPadding, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellEditState, CellFocusMode, MarkdownCellRenderTemplate, ICellViewModel, IActiveNotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellFoldingState } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -295,7 +294,8 @@ export class StatefulMarkdownCell extends Disposable {
|
||||
const width = this.viewCell.layoutInfo.editorWidth;
|
||||
const lineNum = this.viewCell.lineCount;
|
||||
const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17;
|
||||
editorHeight = Math.max(lineNum, 1) * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING;
|
||||
const editorPadding = this.notebookEditor.notebookOptions.computeEditorPadding();
|
||||
editorHeight = Math.max(lineNum, 1) * lineHeight + editorPadding.top + editorPadding.bottom;
|
||||
|
||||
this.templateData.editorContainer.innerText = '';
|
||||
|
||||
|
||||
@@ -955,7 +955,6 @@ async function webviewPreloads(style: PreloadStyles, rendererData: readonly Webv
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: handle namespace
|
||||
if (typeof content === 'string') {
|
||||
if (content.trim().length === 0) {
|
||||
previewContainerNode.classList.add('emptyMarkdownCell');
|
||||
|
||||
@@ -12,12 +12,12 @@ import { IPosition } from 'vs/editor/common/core/position';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import * as model from 'vs/editor/common/model';
|
||||
import { SearchParams } from 'vs/editor/common/model/textModelSearch';
|
||||
import { CELL_STATUSBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions, getEditorTopPadding } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellKind, INotebookSearchOptions, ShowCellStatusBarKey, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel, INotebookCellDecorationOptions } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellKind, INotebookSearchOptions, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
|
||||
export abstract class BaseCellViewModel extends Disposable {
|
||||
|
||||
@@ -129,6 +129,7 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
readonly viewType: string,
|
||||
readonly model: NotebookCellTextModel,
|
||||
public id: string,
|
||||
private readonly _viewContext: ViewContext,
|
||||
private readonly _configurationService: IConfigurationService,
|
||||
private readonly _modelService: ITextModelService,
|
||||
) {
|
||||
@@ -138,11 +139,13 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
this._onDidChangeState.fire({ metadataChanged: true, runStateChanged: e.runStateChanged });
|
||||
}));
|
||||
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(ShowCellStatusBarKey)) {
|
||||
this._register(this._viewContext.notebookOptions.onDidChangeOptions(e => {
|
||||
if (e.cellStatusBarVisibility) {
|
||||
this.layoutChange({});
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('notebook.lineNumbers')) {
|
||||
this.lineNumbers = 'inherit';
|
||||
}
|
||||
@@ -150,8 +153,7 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
}
|
||||
|
||||
getEditorStatusbarHeight() {
|
||||
const showCellStatusBar = this._configurationService.getValue<boolean>(ShowCellStatusBarKey);
|
||||
return showCellStatusBar ? CELL_STATUSBAR_HEIGHT : 0;
|
||||
return this._viewContext.notebookOptions.computeStatusBarHeight();
|
||||
}
|
||||
|
||||
abstract hasDynamicHeight(): boolean;
|
||||
@@ -394,7 +396,8 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._textEditor.getTopForLineNumber(line) + getEditorTopPadding();
|
||||
const editorPadding = this._viewContext.notebookOptions.computeEditorPadding();
|
||||
return this._textEditor.getTopForLineNumber(line) + editorPadding.top;
|
||||
}
|
||||
|
||||
getPositionScrollTopOffset(line: number, column: number): number {
|
||||
@@ -402,7 +405,8 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this._textEditor.getTopForPosition(line, column) + getEditorTopPadding();
|
||||
const editorPadding = this._viewContext.notebookOptions.computeEditorPadding();
|
||||
return this._textEditor.getTopForPosition(line, column) + editorPadding.top;
|
||||
}
|
||||
|
||||
cursorAtBoundary(): CursorAtBoundary {
|
||||
|
||||
@@ -9,10 +9,9 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_RIGHT_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, getEditorTopPadding, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellEditState, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo, CodeCellLayoutState, ICellOutputViewModel, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/cellOutputViewModel';
|
||||
import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { CellKind, INotebookSearchOptions, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
@@ -96,12 +95,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
viewType: string,
|
||||
model: NotebookCellTextModel,
|
||||
initialNotebookLayoutInfo: NotebookLayoutInfo | null,
|
||||
readonly eventDispatcher: NotebookEventDispatcher,
|
||||
readonly viewContext: ViewContext,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
@ITextModelService modelService: ITextModelService,
|
||||
) {
|
||||
super(viewType, model, UUID.generateUuid(), configurationService, modelService);
|
||||
super(viewType, model, UUID.generateUuid(), viewContext, configurationService, modelService);
|
||||
this._outputViewModels = this.model.outputs.map(output => new CellOutputViewModel(this, output, this._notebookService));
|
||||
|
||||
this._register(this.model.onDidChangeOutputs((splices) => {
|
||||
@@ -132,7 +131,9 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
this._layoutInfo = {
|
||||
fontInfo: initialNotebookLayoutInfo?.fontInfo || null,
|
||||
editorHeight: 0,
|
||||
editorWidth: initialNotebookLayoutInfo ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0,
|
||||
editorWidth: initialNotebookLayoutInfo
|
||||
? this.viewContext.notebookOptions.computeCodeCellEditorWidth(initialNotebookLayoutInfo.width)
|
||||
: 0,
|
||||
outputContainerOffset: 0,
|
||||
outputTotalHeight: 0,
|
||||
outputShowMoreContainerHeight: 0,
|
||||
@@ -144,15 +145,12 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
};
|
||||
}
|
||||
|
||||
private computeEditorWidth(outerWidth: number): number {
|
||||
return outerWidth - (CODE_CELL_LEFT_MARGIN + CELL_RUN_GUTTER + CELL_RIGHT_MARGIN);
|
||||
}
|
||||
|
||||
layoutChange(state: CodeCellLayoutChangeEvent, source?: string) {
|
||||
// recompute
|
||||
this._ensureOutputsTop();
|
||||
const notebookLayoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration();
|
||||
const outputShowMoreContainerHeight = state.outputShowMoreContainerHeight ? state.outputShowMoreContainerHeight : this._layoutInfo.outputShowMoreContainerHeight;
|
||||
let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? COLLAPSED_INDICATOR_HEIGHT : this._outputsTop!.getTotalValue());
|
||||
let outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.outputCollapsed ? notebookLayoutConfiguration.collapsedIndicatorHeight : this._outputsTop!.getTotalValue());
|
||||
|
||||
if (!this.metadata?.inputCollapsed) {
|
||||
let newState: CodeCellLayoutState;
|
||||
@@ -176,10 +174,18 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
|
||||
const statusbarHeight = this.getEditorStatusbarHeight();
|
||||
const indicatorHeight = editorHeight + statusbarHeight + outputTotalHeight + outputShowMoreContainerHeight;
|
||||
const outputContainerOffset = EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN + editorHeight + statusbarHeight;
|
||||
const outputShowMoreContainerOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2 - outputShowMoreContainerHeight;
|
||||
const bottomToolbarOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2;
|
||||
const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth;
|
||||
const outputContainerOffset = notebookLayoutConfiguration.editorToolbarHeight
|
||||
+ notebookLayoutConfiguration.cellTopMargin // CELL_TOP_MARGIN
|
||||
+ editorHeight
|
||||
+ statusbarHeight;
|
||||
const outputShowMoreContainerOffset = totalHeight
|
||||
- notebookLayoutConfiguration.bottomCellToolbarGap
|
||||
- notebookLayoutConfiguration.bottomCellToolbarHeight / 2
|
||||
- outputShowMoreContainerHeight;
|
||||
const bottomToolbarOffset = this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight);
|
||||
const editorWidth = state.outerWidth !== undefined
|
||||
? this.viewContext.notebookOptions.computeCodeCellEditorWidth(state.outerWidth)
|
||||
: this._layoutInfo?.editorWidth;
|
||||
|
||||
this._layoutInfo = {
|
||||
fontInfo: state.font ?? this._layoutInfo.fontInfo ?? null,
|
||||
@@ -196,12 +202,23 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
};
|
||||
} else {
|
||||
outputTotalHeight = Math.max(this._outputMinHeight, this.metadata?.inputCollapsed && this.metadata.outputCollapsed ? 0 : outputTotalHeight);
|
||||
const indicatorHeight = COLLAPSED_INDICATOR_HEIGHT + outputTotalHeight + outputShowMoreContainerHeight;
|
||||
const outputContainerOffset = CELL_TOP_MARGIN + COLLAPSED_INDICATOR_HEIGHT;
|
||||
const totalHeight = CELL_TOP_MARGIN + COLLAPSED_INDICATOR_HEIGHT + CELL_BOTTOM_MARGIN + BOTTOM_CELL_TOOLBAR_GAP + outputTotalHeight + outputShowMoreContainerHeight;
|
||||
const outputShowMoreContainerOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2 - outputShowMoreContainerHeight;
|
||||
const bottomToolbarOffset = totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2;
|
||||
const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth;
|
||||
const indicatorHeight = notebookLayoutConfiguration.collapsedIndicatorHeight + outputTotalHeight + outputShowMoreContainerHeight;
|
||||
|
||||
const outputContainerOffset = notebookLayoutConfiguration.cellTopMargin + notebookLayoutConfiguration.collapsedIndicatorHeight;
|
||||
const totalHeight =
|
||||
notebookLayoutConfiguration.cellTopMargin
|
||||
+ notebookLayoutConfiguration.collapsedIndicatorHeight
|
||||
+ notebookLayoutConfiguration.cellBottomMargin //CELL_BOTTOM_MARGIN
|
||||
+ notebookLayoutConfiguration.bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP
|
||||
+ outputTotalHeight + outputShowMoreContainerHeight;
|
||||
const outputShowMoreContainerOffset = totalHeight
|
||||
- notebookLayoutConfiguration.bottomCellToolbarGap
|
||||
- notebookLayoutConfiguration.bottomCellToolbarHeight / 2
|
||||
- outputShowMoreContainerHeight;
|
||||
const bottomToolbarOffset = this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight);
|
||||
const editorWidth = state.outerWidth !== undefined
|
||||
? this.viewContext.notebookOptions.computeCodeCellEditorWidth(state.outerWidth)
|
||||
: this._layoutInfo?.editorWidth;
|
||||
|
||||
this._layoutInfo = {
|
||||
fontInfo: state.font ?? this._layoutInfo.fontInfo ?? null,
|
||||
@@ -282,11 +299,23 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
}
|
||||
|
||||
const verticalScrollbarHeight = hasScrolling ? 12 : 0; // take zoom level into account
|
||||
return this.lineCount * lineHeight + getEditorTopPadding() + EDITOR_BOTTOM_PADDING + verticalScrollbarHeight;
|
||||
const editorPadding = this.viewContext.notebookOptions.computeEditorPadding();
|
||||
return this.lineCount * lineHeight
|
||||
+ editorPadding.top
|
||||
+ editorPadding.bottom // EDITOR_BOTTOM_PADDING
|
||||
+ verticalScrollbarHeight;
|
||||
}
|
||||
|
||||
private computeTotalHeight(editorHeight: number, outputsTotalHeight: number, outputShowMoreContainerHeight: number): number {
|
||||
return EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN + editorHeight + this.getEditorStatusbarHeight() + outputsTotalHeight + outputShowMoreContainerHeight + BOTTOM_CELL_TOOLBAR_GAP + CELL_BOTTOM_MARGIN;
|
||||
const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration();
|
||||
return layoutConfiguration.editorToolbarHeight //EDITOR_TOOLBAR_HEIGHT
|
||||
+ layoutConfiguration.cellTopMargin // CELL_TOP_MARGIN
|
||||
+ editorHeight
|
||||
+ this.getEditorStatusbarHeight()
|
||||
+ outputsTotalHeight
|
||||
+ outputShowMoreContainerHeight
|
||||
+ layoutConfiguration.bottomCellToolbarGap //BOTTOM_CELL_TOOLBAR_GAP
|
||||
+ layoutConfiguration.cellBottomMargin; // CELL_BOTTOM_MARGIN;
|
||||
}
|
||||
|
||||
protected onDidChangeTextModelContent(): void {
|
||||
|
||||
@@ -8,15 +8,15 @@ import * as UUID from 'vs/base/common/uuid';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import * as nls from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, MARKDOWN_CELL_BOTTOM_MARGIN, MARKDOWN_CELL_TOP_MARGIN, CELL_RIGHT_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel';
|
||||
import { CellEditState, CellFindMatch, ICellOutputViewModel, ICellViewModel, MarkdownCellLayoutChangeEvent, MarkdownCellLayoutInfo, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
|
||||
import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel';
|
||||
import { NotebookCellStateChangedEvent, NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { NotebookCellStateChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { CellKind, INotebookSearchOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
|
||||
export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel {
|
||||
readonly cellKind = CellKind.Markup;
|
||||
@@ -29,7 +29,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
|
||||
|
||||
set renderedMarkdownHeight(newHeight: number) {
|
||||
if (this.getEditState() === CellEditState.Preview) {
|
||||
const newTotalHeight = newHeight + BOTTOM_CELL_TOOLBAR_GAP;
|
||||
const newTotalHeight = newHeight + this.viewContext.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap; // BOTTOM_CELL_TOOLBAR_GAP;
|
||||
this.totalHeight = newTotalHeight;
|
||||
}
|
||||
}
|
||||
@@ -47,8 +47,13 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
|
||||
private _editorHeight = 0;
|
||||
set editorHeight(newHeight: number) {
|
||||
this._editorHeight = newHeight;
|
||||
const layoutConfiguration = this.viewContext.notebookOptions.getLayoutConfiguration();
|
||||
|
||||
this.totalHeight = this._editorHeight + MARKDOWN_CELL_TOP_MARGIN + MARKDOWN_CELL_BOTTOM_MARGIN + BOTTOM_CELL_TOOLBAR_GAP + this.getEditorStatusbarHeight();
|
||||
this.totalHeight = this._editorHeight
|
||||
+ layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN
|
||||
+ layoutConfiguration.markdownCellBottomMargin // MARKDOWN_CELL_BOTTOM_MARGIN
|
||||
+ layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP
|
||||
+ this.viewContext.notebookOptions.computeStatusBarHeight();
|
||||
}
|
||||
|
||||
get editorHeight() {
|
||||
@@ -102,23 +107,25 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
|
||||
model: NotebookCellTextModel,
|
||||
initialNotebookLayoutInfo: NotebookLayoutInfo | null,
|
||||
readonly foldingDelegate: EditorFoldingStateDelegate,
|
||||
readonly eventDispatcher: NotebookEventDispatcher,
|
||||
readonly viewContext: ViewContext,
|
||||
private readonly _mdRenderer: MarkdownRenderer,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ITextModelService textModelService: ITextModelService,
|
||||
) {
|
||||
super(viewType, model, UUID.generateUuid(), configurationService, textModelService);
|
||||
super(viewType, model, UUID.generateUuid(), viewContext, configurationService, textModelService);
|
||||
|
||||
this._layoutInfo = {
|
||||
editorHeight: 0,
|
||||
fontInfo: initialNotebookLayoutInfo?.fontInfo || null,
|
||||
editorWidth: initialNotebookLayoutInfo?.width ? this.computeEditorWidth(initialNotebookLayoutInfo.width) : 0,
|
||||
bottomToolbarOffset: BOTTOM_CELL_TOOLBAR_GAP,
|
||||
editorWidth: initialNotebookLayoutInfo?.width
|
||||
? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(initialNotebookLayoutInfo.width)
|
||||
: 0,
|
||||
bottomToolbarOffset: this.viewContext.notebookOptions.getLayoutConfiguration().bottomCellToolbarGap, // BOTTOM_CELL_TOOLBAR_GAP,
|
||||
totalHeight: 0
|
||||
};
|
||||
|
||||
this._register(this.onDidChangeState(e => {
|
||||
eventDispatcher.emit([new NotebookCellStateChangedEvent(e, this)]);
|
||||
this.viewContext.eventDispatcher.emit([new NotebookCellStateChangedEvent(e, this)]);
|
||||
}));
|
||||
|
||||
this._register(model.onDidChangeMetadata(e => {
|
||||
@@ -144,34 +151,34 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
|
||||
this._onDidChangeState.fire({ foldingStateChanged: true });
|
||||
}
|
||||
|
||||
private computeEditorWidth(outerWidth: number) {
|
||||
return outerWidth - CODE_CELL_LEFT_MARGIN - CELL_RIGHT_MARGIN;
|
||||
}
|
||||
|
||||
layoutChange(state: MarkdownCellLayoutChangeEvent) {
|
||||
// recompute
|
||||
|
||||
if (!this.metadata?.inputCollapsed) {
|
||||
const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth;
|
||||
const editorWidth = state.outerWidth !== undefined
|
||||
? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth)
|
||||
: this._layoutInfo.editorWidth;
|
||||
const totalHeight = state.totalHeight === undefined ? this._layoutInfo.totalHeight : state.totalHeight;
|
||||
|
||||
this._layoutInfo = {
|
||||
fontInfo: state.font || this._layoutInfo.fontInfo,
|
||||
editorWidth,
|
||||
editorHeight: this._editorHeight,
|
||||
bottomToolbarOffset: totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2,
|
||||
bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight),
|
||||
totalHeight
|
||||
};
|
||||
} else {
|
||||
const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo.editorWidth;
|
||||
const totalHeight = MARKDOWN_CELL_TOP_MARGIN + COLLAPSED_INDICATOR_HEIGHT + BOTTOM_CELL_TOOLBAR_GAP + MARKDOWN_CELL_BOTTOM_MARGIN;
|
||||
const editorWidth = state.outerWidth !== undefined
|
||||
? this.viewContext.notebookOptions.computeMarkdownCellEditorWidth(state.outerWidth)
|
||||
: this._layoutInfo.editorWidth;
|
||||
const totalHeight = this.viewContext.notebookOptions.computeCollapsedMarkdownCellHeight();
|
||||
|
||||
state.totalHeight = totalHeight;
|
||||
|
||||
this._layoutInfo = {
|
||||
fontInfo: state.font || this._layoutInfo.fontInfo,
|
||||
editorWidth,
|
||||
editorHeight: this._editorHeight,
|
||||
bottomToolbarOffset: totalHeight - BOTTOM_CELL_TOOLBAR_GAP - BOTTOM_CELL_TOOLBAR_HEIGHT / 2,
|
||||
bottomToolbarOffset: this.viewContext.notebookOptions.computeBottomToolbarOffset(totalHeight),
|
||||
totalHeight
|
||||
};
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { CellEditState, CellFindMatch, ICellViewModel, NotebookLayoutInfo, INotebookDeltaDecoration, INotebookDeltaCellStatusBarItems, CellFocusMode, CellFindMatchWithIndex } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { NotebookEventDispatcher, NotebookMetadataChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { NotebookMetadataChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { CellFoldingState, EditorFoldingStateDelegate } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
@@ -36,6 +36,7 @@ import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/
|
||||
import { NotebookCellSelectionCollection } from 'vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { groupByNumber } from 'vs/base/common/collections';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
|
||||
export interface INotebookEditorViewState {
|
||||
editingCells: { [key: number]: boolean };
|
||||
@@ -172,10 +173,6 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
|
||||
return this._notebook.metadata;
|
||||
}
|
||||
|
||||
get trusted() {
|
||||
return !!this._notebook.metadata?.trusted;
|
||||
}
|
||||
|
||||
private readonly _onDidChangeViewCells = this._register(new Emitter<INotebookViewCellsUpdateEvent>());
|
||||
get onDidChangeViewCells(): Event<INotebookViewCellsUpdateEvent> { return this._onDidChangeViewCells.event; }
|
||||
|
||||
@@ -233,7 +230,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
|
||||
constructor(
|
||||
public viewType: string,
|
||||
private _notebook: NotebookTextModel,
|
||||
readonly eventDispatcher: NotebookEventDispatcher,
|
||||
readonly viewContext: ViewContext,
|
||||
private _layoutInfo: NotebookLayoutInfo | null,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||
@@ -326,7 +323,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
|
||||
this._register(this._notebook.onDidChangeContent(contentChanges => {
|
||||
contentChanges.rawEvents.forEach(e => {
|
||||
if (e.kind === NotebookCellsChangeType.ChangeDocumentMetadata) {
|
||||
this.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]);
|
||||
this.viewContext.eventDispatcher.emit([new NotebookMetadataChangedEvent(this._notebook.metadata)]);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -335,7 +332,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(this.eventDispatcher.onDidChangeLayout((e) => {
|
||||
this._register(this.viewContext.eventDispatcher.onDidChangeLayout((e) => {
|
||||
this._layoutInfo = e.value;
|
||||
|
||||
this._viewCells.forEach(cell => {
|
||||
@@ -1181,9 +1178,9 @@ export type CellViewModel = CodeCellViewModel | MarkdownCellViewModel;
|
||||
|
||||
export function createCellViewModel(instantiationService: IInstantiationService, notebookViewModel: NotebookViewModel, cell: NotebookCellTextModel) {
|
||||
if (cell.cellKind === CellKind.Code) {
|
||||
return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel.eventDispatcher);
|
||||
return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel.viewContext);
|
||||
} else {
|
||||
const mdRenderer = instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookViewModel.uri) });
|
||||
return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel, notebookViewModel.eventDispatcher, mdRenderer);
|
||||
return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel, notebookViewModel.viewContext, mdRenderer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
|
||||
export class ViewContext {
|
||||
constructor(
|
||||
readonly notebookOptions: NotebookOptions,
|
||||
readonly eventDispatcher: NotebookEventDispatcher
|
||||
) {
|
||||
}
|
||||
}
|
||||
@@ -134,19 +134,14 @@ export interface INotebookRendererInfo {
|
||||
extensionLocation: URI;
|
||||
extensionId: ExtensionIdentifier;
|
||||
|
||||
readonly mimeTypes: readonly string[];
|
||||
|
||||
readonly dependencies: readonly string[];
|
||||
|
||||
matchesWithoutKernel(mimeType: string): NotebookRendererMatch;
|
||||
matches(mimeType: string, kernelProvides: ReadonlyArray<string>): NotebookRendererMatch;
|
||||
}
|
||||
|
||||
export interface INotebookMarkupRendererInfo {
|
||||
readonly id: string;
|
||||
readonly entrypoint: URI;
|
||||
readonly extensionLocation: URI;
|
||||
readonly extensionId: ExtensionIdentifier;
|
||||
readonly extensionIsBuiltin: boolean;
|
||||
readonly dependsOn: string | undefined;
|
||||
readonly mimeTypes: readonly string[] | undefined;
|
||||
}
|
||||
|
||||
export interface NotebookCellOutputMetadata {
|
||||
/**
|
||||
@@ -549,8 +544,9 @@ const _mimeTypeInfo = new Map<string, MimeTypeInfo>([
|
||||
['text/html', { supportedByCore: true }],
|
||||
['image/svg+xml', { supportedByCore: true }],
|
||||
['image/jpeg', { supportedByCore: true }],
|
||||
['text/x-javascript', { supportedByCore: true }],
|
||||
['text/x-javascript', { alwaysSecure: true, supportedByCore: true }], // secure because rendered as text, not executed
|
||||
['application/x.notebook.error-traceback', { alwaysSecure: true, supportedByCore: true }],
|
||||
['application/x.notebook.error', { alwaysSecure: true, supportedByCore: true }],
|
||||
['application/x.notebook.stream', { alwaysSecure: true, supportedByCore: true, mergeable: true }],
|
||||
['application/x.notebook.stdout', { alwaysSecure: true, supportedByCore: true, mergeable: true }],
|
||||
['application/x.notebook.stderr', { alwaysSecure: true, supportedByCore: true, mergeable: true }],
|
||||
|
||||
@@ -465,7 +465,7 @@ export class SimpleNotebookEditorModel extends EditorModel implements INotebookE
|
||||
}
|
||||
|
||||
isReadonly(): boolean {
|
||||
return this._fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
|
||||
return this._workingCopy?.isReadonly() || this._fileService.hasCapability(this.resource, FileSystemProviderCapabilities.Readonly);
|
||||
}
|
||||
|
||||
revert(options?: IRevertOptions): Promise<void> {
|
||||
|
||||
@@ -1,39 +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 { joinPath } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { INotebookMarkupRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
|
||||
export class NotebookMarkupRendererInfo implements INotebookMarkupRendererInfo {
|
||||
|
||||
readonly id: string;
|
||||
readonly entrypoint: URI;
|
||||
readonly displayName: string;
|
||||
readonly extensionLocation: URI;
|
||||
readonly extensionId: ExtensionIdentifier;
|
||||
readonly extensionIsBuiltin: boolean;
|
||||
readonly dependsOn: string | undefined;
|
||||
readonly mimeTypes: readonly string[] | undefined;
|
||||
|
||||
constructor(descriptor: {
|
||||
readonly id: string;
|
||||
readonly displayName: string;
|
||||
readonly entrypoint: string;
|
||||
readonly extension: IExtensionDescription;
|
||||
readonly mimeTypes: readonly string[] | undefined,
|
||||
readonly dependsOn: string | undefined,
|
||||
}) {
|
||||
this.id = descriptor.id;
|
||||
this.extensionId = descriptor.extension.identifier;
|
||||
this.extensionLocation = descriptor.extension.extensionLocation;
|
||||
this.entrypoint = joinPath(this.extensionLocation, descriptor.entrypoint);
|
||||
this.displayName = descriptor.displayName;
|
||||
this.extensionIsBuiltin = descriptor.extension.isBuiltin;
|
||||
this.dependsOn = descriptor.dependsOn;
|
||||
this.mimeTypes = descriptor.mimeTypes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { CellToolbarLocKey, CellToolbarVisibility, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
|
||||
const CELL_STATUSBAR_HEIGHT = 22;
|
||||
const EDITOR_TOOLBAR_HEIGHT = 0;
|
||||
const CELL_OUTPUT_PADDING = 14;
|
||||
const MARKDOWN_PREVIEW_PADDING = 8;
|
||||
const CELL_RIGHT_MARGIN = 16;
|
||||
const CELL_RUN_GUTTER = 28;
|
||||
const CODE_CELL_LEFT_MARGIN = 32;
|
||||
const BOTTOM_CELL_TOOLBAR_GAP = 18;
|
||||
const BOTTOM_CELL_TOOLBAR_HEIGHT = 22;
|
||||
|
||||
// Margin above editor
|
||||
const CELL_TOP_MARGIN = 6;
|
||||
const CELL_BOTTOM_MARGIN = 6;
|
||||
|
||||
const MARKDOWN_CELL_TOP_MARGIN = 8;
|
||||
const MARKDOWN_CELL_BOTTOM_MARGIN = 8;
|
||||
|
||||
const COLLAPSED_INDICATOR_HEIGHT = 24;
|
||||
const EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR = 12;
|
||||
const EDITOR_BOTTOM_PADDING = 4;
|
||||
|
||||
let EDITOR_TOP_PADDING = 12;
|
||||
const editorTopPaddingChangeEmitter = new Emitter<void>();
|
||||
|
||||
export const EditorTopPaddingChangeEvent = editorTopPaddingChangeEmitter.event;
|
||||
|
||||
export function updateEditorTopPadding(top: number) {
|
||||
EDITOR_TOP_PADDING = top;
|
||||
editorTopPaddingChangeEmitter.fire();
|
||||
}
|
||||
|
||||
export function getEditorTopPadding() {
|
||||
return EDITOR_TOP_PADDING;
|
||||
}
|
||||
|
||||
export interface NotebookLayoutConfiguration {
|
||||
cellRightMargin: number;
|
||||
cellRunGutter: number;
|
||||
cellTopMargin: number;
|
||||
cellBottomMargin: number;
|
||||
cellOutputPadding: number;
|
||||
codeCellLeftMargin: number;
|
||||
markdownCellTopMargin: number;
|
||||
markdownCellBottomMargin: number;
|
||||
markdownPreviewPadding: number;
|
||||
bottomCellToolbarGap: number;
|
||||
bottomCellToolbarHeight: number;
|
||||
editorToolbarHeight: number;
|
||||
editorTopPadding: number;
|
||||
editorBottomPadding: number;
|
||||
editorBottomPaddingWithoutStatusBar: number;
|
||||
collapsedIndicatorHeight: number;
|
||||
showCellStatusBar: boolean;
|
||||
cellStatusBarHeight: number;
|
||||
cellToolbarLocation: string | { [key: string]: string };
|
||||
cellToolbarInteraction: string;
|
||||
}
|
||||
|
||||
interface NotebookOptionsChangeEvent {
|
||||
cellStatusBarVisibility?: boolean;
|
||||
cellToolbarLocation?: boolean;
|
||||
cellToolbarInteraction?: boolean;
|
||||
editorTopPadding?: boolean;
|
||||
}
|
||||
export class NotebookOptions {
|
||||
private _layoutConfiguration: NotebookLayoutConfiguration;
|
||||
protected readonly _onDidChangeOptions = new Emitter<NotebookOptionsChangeEvent>();
|
||||
readonly onDidChangeOptions = this._onDidChangeOptions.event;
|
||||
private _disposables: IDisposable[];
|
||||
|
||||
constructor(readonly configurationService: IConfigurationService) {
|
||||
const showCellStatusBar = this.configurationService.getValue<boolean>(ShowCellStatusBarKey);
|
||||
const cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocKey);
|
||||
const cellToolbarInteraction = this.configurationService.getValue<string>(CellToolbarVisibility);
|
||||
|
||||
this._disposables = [];
|
||||
this._layoutConfiguration = {
|
||||
cellRightMargin: CELL_RIGHT_MARGIN,
|
||||
cellRunGutter: CELL_RUN_GUTTER,
|
||||
cellTopMargin: CELL_TOP_MARGIN,
|
||||
cellBottomMargin: CELL_BOTTOM_MARGIN,
|
||||
codeCellLeftMargin: CODE_CELL_LEFT_MARGIN,
|
||||
markdownCellTopMargin: MARKDOWN_CELL_TOP_MARGIN,
|
||||
markdownCellBottomMargin: MARKDOWN_CELL_BOTTOM_MARGIN,
|
||||
bottomCellToolbarGap: BOTTOM_CELL_TOOLBAR_GAP,
|
||||
bottomCellToolbarHeight: BOTTOM_CELL_TOOLBAR_HEIGHT,
|
||||
editorTopPadding: EDITOR_TOP_PADDING,
|
||||
editorBottomPadding: EDITOR_BOTTOM_PADDING,
|
||||
editorBottomPaddingWithoutStatusBar: EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR,
|
||||
editorToolbarHeight: EDITOR_TOOLBAR_HEIGHT,
|
||||
cellOutputPadding: CELL_OUTPUT_PADDING,
|
||||
collapsedIndicatorHeight: COLLAPSED_INDICATOR_HEIGHT,
|
||||
markdownPreviewPadding: MARKDOWN_PREVIEW_PADDING,
|
||||
cellStatusBarHeight: CELL_STATUSBAR_HEIGHT,
|
||||
showCellStatusBar,
|
||||
cellToolbarLocation,
|
||||
cellToolbarInteraction
|
||||
};
|
||||
|
||||
this._disposables.push(this.configurationService.onDidChangeConfiguration(e => {
|
||||
let cellStatusBarVisibility = e.affectsConfiguration(ShowCellStatusBarKey);
|
||||
let cellToolbarLocation = e.affectsConfiguration(CellToolbarLocKey);
|
||||
let cellToolbarInteraction = e.affectsConfiguration(CellToolbarVisibility);
|
||||
|
||||
if (!cellStatusBarVisibility && !cellToolbarLocation && !cellToolbarInteraction) {
|
||||
return;
|
||||
}
|
||||
|
||||
const configuration = Object.assign({}, this._layoutConfiguration);
|
||||
|
||||
if (cellStatusBarVisibility) {
|
||||
configuration.showCellStatusBar = this.configurationService.getValue<boolean>(ShowCellStatusBarKey);
|
||||
}
|
||||
|
||||
if (cellToolbarLocation) {
|
||||
configuration.cellToolbarLocation = this.configurationService.getValue<string | { [key: string]: string }>(CellToolbarLocKey);
|
||||
}
|
||||
|
||||
if (cellToolbarInteraction) {
|
||||
configuration.cellToolbarInteraction = this.configurationService.getValue<string>(CellToolbarVisibility);
|
||||
}
|
||||
|
||||
this._layoutConfiguration = configuration;
|
||||
|
||||
// trigger event
|
||||
this._onDidChangeOptions.fire({
|
||||
cellStatusBarVisibility: cellStatusBarVisibility,
|
||||
cellToolbarLocation: cellToolbarLocation,
|
||||
cellToolbarInteraction: cellToolbarInteraction
|
||||
});
|
||||
}));
|
||||
|
||||
this._disposables.push(EditorTopPaddingChangeEvent(() => {
|
||||
const configuration = Object.assign({}, this._layoutConfiguration);
|
||||
configuration.editorTopPadding = getEditorTopPadding();
|
||||
this._layoutConfiguration = configuration;
|
||||
this._onDidChangeOptions.fire({ editorTopPadding: true });
|
||||
}));
|
||||
}
|
||||
|
||||
getLayoutConfiguration(): NotebookLayoutConfiguration {
|
||||
return this._layoutConfiguration;
|
||||
}
|
||||
|
||||
computeCollapsedMarkdownCellHeight(): number {
|
||||
return this._layoutConfiguration.markdownCellTopMargin // MARKDOWN_CELL_TOP_MARGIN
|
||||
+ this._layoutConfiguration.collapsedIndicatorHeight // COLLAPSED_INDICATOR_HEIGHT
|
||||
+ this._layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP
|
||||
+ this._layoutConfiguration.markdownCellBottomMargin; // MARKDOWN_CELL_BOTTOM_MARGIN;
|
||||
}
|
||||
|
||||
computeBottomToolbarOffset(totalHeight: number) {
|
||||
return totalHeight
|
||||
- this._layoutConfiguration.bottomCellToolbarGap // BOTTOM_CELL_TOOLBAR_GAP
|
||||
- this._layoutConfiguration.bottomCellToolbarHeight / 2;
|
||||
}
|
||||
|
||||
computeCodeCellEditorWidth(outerWidth: number): number {
|
||||
return outerWidth - (
|
||||
this._layoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN
|
||||
+ this._layoutConfiguration.cellRunGutter // CELL_RUN_GUTTER
|
||||
+ this._layoutConfiguration.cellRightMargin // CELL_RIGHT_MARGIN
|
||||
);
|
||||
}
|
||||
|
||||
computeMarkdownCellEditorWidth(outerWidth: number): number {
|
||||
return outerWidth
|
||||
- this._layoutConfiguration.codeCellLeftMargin // CODE_CELL_LEFT_MARGIN
|
||||
- this._layoutConfiguration.cellRightMargin; // CELL_RIGHT_MARGIN;
|
||||
}
|
||||
|
||||
computeStatusBarHeight(): number {
|
||||
if (this._layoutConfiguration.showCellStatusBar) {
|
||||
return this._layoutConfiguration.cellStatusBarHeight;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
computeCellToolbarLocation(viewType?: string): 'right' | 'left' | 'hidden' {
|
||||
const cellToolbarLocation = this._layoutConfiguration.cellToolbarLocation;
|
||||
|
||||
if (typeof cellToolbarLocation === 'string') {
|
||||
if (cellToolbarLocation === 'left' || cellToolbarLocation === 'right' || cellToolbarLocation === 'hidden') {
|
||||
return cellToolbarLocation;
|
||||
}
|
||||
} else {
|
||||
if (viewType) {
|
||||
const notebookSpecificSetting = cellToolbarLocation[viewType] ?? cellToolbarLocation['default'];
|
||||
let cellToolbarLocationForCurrentView: 'right' | 'left' | 'hidden' = 'right';
|
||||
|
||||
switch (notebookSpecificSetting) {
|
||||
case 'left':
|
||||
cellToolbarLocationForCurrentView = 'left';
|
||||
break;
|
||||
case 'right':
|
||||
cellToolbarLocationForCurrentView = 'right';
|
||||
break;
|
||||
case 'hidden':
|
||||
cellToolbarLocationForCurrentView = 'hidden';
|
||||
break;
|
||||
default:
|
||||
cellToolbarLocationForCurrentView = 'right';
|
||||
break;
|
||||
}
|
||||
|
||||
return cellToolbarLocationForCurrentView;
|
||||
}
|
||||
}
|
||||
|
||||
return 'right';
|
||||
}
|
||||
|
||||
computeEditorPadding() {
|
||||
return {
|
||||
top: getEditorTopPadding(),
|
||||
bottom: this._layoutConfiguration.showCellStatusBar
|
||||
? this._layoutConfiguration.editorBottomPadding// EDITOR_BOTTOM_PADDING
|
||||
: this._layoutConfiguration.editorBottomPaddingWithoutStatusBar // EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR
|
||||
};
|
||||
}
|
||||
|
||||
computeWebviewOptions() {
|
||||
return {
|
||||
outputNodePadding: this._layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING,
|
||||
outputNodeLeftPadding: this._layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING,
|
||||
previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING,
|
||||
leftMargin: this._layoutConfiguration.codeCellLeftMargin, // CODE_CELL_LEFT_MARGIN,
|
||||
rightMargin: this._layoutConfiguration.cellRightMargin, // CELL_RIGHT_MARGIN,
|
||||
runGutter: this._layoutConfiguration.cellRunGutter, // CELL_RUN_GUTTER,
|
||||
};
|
||||
}
|
||||
|
||||
computeDiffWebviewOptions() {
|
||||
return {
|
||||
outputNodePadding: this._layoutConfiguration.cellOutputPadding, // CELL_OUTPUT_PADDING,
|
||||
outputNodeLeftPadding: 32,
|
||||
previewNodePadding: this._layoutConfiguration.markdownPreviewPadding, // MARKDOWN_PREVIEW_PADDING,
|
||||
leftMargin: 0,
|
||||
rightMargin: 0,
|
||||
runGutter: 0
|
||||
};
|
||||
}
|
||||
|
||||
computeIndicatorPosition(totalHeight: number) {
|
||||
return {
|
||||
bottomIndicatorTop: totalHeight - this._layoutConfiguration.bottomCellToolbarGap - this._layoutConfiguration.cellBottomMargin,
|
||||
verticalIndicatorHeight: totalHeight - this._layoutConfiguration.bottomCellToolbarGap
|
||||
};
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposables.forEach(d => d.dispose());
|
||||
this._disposables = [];
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,10 @@ class DependencyList {
|
||||
this.defined = this.value.size > 0;
|
||||
}
|
||||
|
||||
public values(): string[] {
|
||||
return Array.from(this.value);
|
||||
}
|
||||
|
||||
/** Gets whether any of the 'available' dependencies match the ones in this list */
|
||||
public matches(available: ReadonlyArray<string>) {
|
||||
// For now this is simple, but this may expand to support globs later
|
||||
@@ -39,7 +43,7 @@ export class NotebookOutputRendererInfo implements INotebookRendererInfo {
|
||||
// todo: re-add preloads in pure renderer API
|
||||
readonly preloads: ReadonlyArray<URI> = [];
|
||||
|
||||
private readonly mimeTypes: readonly string[];
|
||||
readonly mimeTypes: readonly string[];
|
||||
private readonly mimeTypeGlobs: glob.ParsedPattern[];
|
||||
|
||||
constructor(descriptor: {
|
||||
@@ -62,6 +66,10 @@ export class NotebookOutputRendererInfo implements INotebookRendererInfo {
|
||||
this.optionalDependencies = new DependencyList(descriptor.optionalDependencies ?? Iterable.empty());
|
||||
}
|
||||
|
||||
get dependencies(): string[] {
|
||||
return this.hardDependencies.values();
|
||||
}
|
||||
|
||||
matchesWithoutKernel(mimeType: string) {
|
||||
if (!this.matchesMimeTypeOnly(mimeType)) {
|
||||
return NotebookRendererMatch.Never;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { NotebookProviderInfo } from 'vs/workbench/contrib/notebook/common/notebookProvider';
|
||||
import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { INotebookRendererInfo, NotebookDataDto, TransientOptions, IOrderedMimeType, IOutputDto, INotebookMarkupRendererInfo, INotebookContributionData } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookRendererInfo, NotebookDataDto, TransientOptions, IOrderedMimeType, IOutputDto, INotebookContributionData } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
@@ -73,7 +73,7 @@ export interface INotebookService {
|
||||
getMimeTypeInfo(textModel: NotebookTextModel, kernelProvides: readonly string[] | undefined, output: IOutputDto): readonly IOrderedMimeType[];
|
||||
|
||||
getRendererInfo(id: string): INotebookRendererInfo | undefined;
|
||||
getMarkupRendererInfo(): INotebookMarkupRendererInfo[];
|
||||
getRenderers(): INotebookRendererInfo[];
|
||||
|
||||
/** Updates the preferred renderer for the given mimetype in the workspace. */
|
||||
updateMimePreferredRenderer(mimeType: string, rendererId: string): void;
|
||||
|
||||
@@ -18,8 +18,10 @@ import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { reduceCellRanges } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, diff, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { NotebookEditorTestModel, setupInstantiationService, withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
|
||||
@@ -37,8 +39,8 @@ suite('NotebookViewModel', () => {
|
||||
test('ctor', function () {
|
||||
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService);
|
||||
const model = new NotebookEditorTestModel(notebook);
|
||||
const eventDispatcher = new NotebookEventDispatcher();
|
||||
const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, bulkEditService, undoRedoService, textModelService);
|
||||
const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher());
|
||||
const viewModel = new NotebookViewModel('notebook', model.notebook, viewContext, null, instantiationService, bulkEditService, undoRedoService, textModelService);
|
||||
assert.strictEqual(viewModel.viewType, 'notebook');
|
||||
});
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/workspaceTrust';
|
||||
import { TestWorkspaceTrustRequestService } from 'vs/workbench/services/workspaces/test/common/testWorkspaceTrustService';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
|
||||
export class TestCell extends NotebookCellTextModel {
|
||||
constructor(
|
||||
@@ -172,8 +174,8 @@ function _createTestNotebookEditor(instantiationService: TestInstantiationServic
|
||||
}), notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false });
|
||||
|
||||
const model = new NotebookEditorTestModel(notebook);
|
||||
const eventDispatcher = new NotebookEventDispatcher();
|
||||
const viewModel: NotebookViewModel = instantiationService.createInstance(NotebookViewModel, viewType, model.notebook, eventDispatcher, null);
|
||||
const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher());
|
||||
const viewModel: NotebookViewModel = instantiationService.createInstance(NotebookViewModel, viewType, model.notebook, viewContext, null);
|
||||
|
||||
const cellList = createNotebookCellList(instantiationService);
|
||||
cellList.attachViewModel(viewModel);
|
||||
|
||||
@@ -37,7 +37,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { editorBackground, errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { editorBackground, editorErrorForeground, errorForeground, focusBorder, foreground, inputValidationErrorBackground, inputValidationErrorBorder, inputValidationErrorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
|
||||
import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { getIgnoredSettings } from 'vs/platform/userDataSync/common/settingsMerge';
|
||||
@@ -60,7 +60,6 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { settingsMoreActionIcon } from 'vs/workbench/contrib/preferences/browser/preferencesIcons';
|
||||
import { IWorkbenchConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { SettingsTarget } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets';
|
||||
import { untrustedForegroundColor } from 'vs/workbench/contrib/workspace/browser/workspaceTrustColors';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -1537,8 +1536,8 @@ export class SettingUntrustedRenderer extends AbstractSettingRenderer implements
|
||||
const manageWorkspaceTrustLabel = localize('manageWorkspaceTrust', "Manage Workspace Trust");
|
||||
const trustLabelElement = $('.setting-item-trust-description');
|
||||
const untrustedWorkspaceIcon = DOM.append(trustLabelElement, $('span.codicon.codicon-workspace-untrusted'));
|
||||
template.toDispose.add(attachStylerCallback(this._themeService, { untrustedForegroundColor }, colors => {
|
||||
untrustedWorkspaceIcon.style.setProperty('--workspace-trust-state-untrusted-color', colors.untrustedForegroundColor?.toString() || '');
|
||||
template.toDispose.add(attachStylerCallback(this._themeService, { editorErrorForeground }, colors => {
|
||||
untrustedWorkspaceIcon.style.setProperty('--workspace-trust-state-untrusted-color', colors.editorErrorForeground?.toString() || '');
|
||||
}));
|
||||
const element = DOM.append(trustLabelElement, $('span'));
|
||||
element.textContent = localize('trustLabel', "This setting can only be applied in a trusted workspace");
|
||||
|
||||
@@ -51,6 +51,7 @@ import { IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IHoverDelegateOptions } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
|
||||
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
|
||||
import { STATUS_BAR_HOST_NAME_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
|
||||
export const forwardedPortsViewEnabled = new RawContextKey<boolean>('forwardedPortsViewEnabled', false, nls.localize('tunnel.forwardedPortsViewEnabled', "Whether the Ports view is enabled."));
|
||||
|
||||
@@ -1318,7 +1319,7 @@ namespace ChangeLocalPortAction {
|
||||
export function handler(): ICommandHandler {
|
||||
return async (accessor, arg) => {
|
||||
const remoteExplorerService = accessor.get(IRemoteExplorerService);
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
const dialogService = accessor.get(IDialogService);
|
||||
const tunnelService = accessor.get(ITunnelService);
|
||||
const context = (arg !== undefined || arg instanceof TunnelItem) ? arg : accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName);
|
||||
if (context instanceof TunnelItem) {
|
||||
@@ -1330,7 +1331,9 @@ namespace ChangeLocalPortAction {
|
||||
const numberValue = Number(value);
|
||||
const newForward = await remoteExplorerService.forward({ host: context.remoteHost, port: context.remotePort }, numberValue, context.name, undefined, true);
|
||||
if (newForward && newForward.tunnelLocalPort !== numberValue) {
|
||||
notificationService.warn(nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available. Port number {1} has been used instead", value, newForward.tunnelLocalPort ?? newForward.localAddress));
|
||||
dialogService.show(Severity.Info,
|
||||
nls.localize('remote.tunnel.changeLocalPortNumber', "The local port {0} is not available.\n\nThis usually happens when there is already another process using port {0}.\n\nPort number {1} has been used instead.", value, newForward.tunnelLocalPort ?? newForward.localAddress),
|
||||
[nls.localize('remote.tunnel.changeLocalPortNumber.Ok', "Ok")]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Iterable } from 'vs/base/common/iterator';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
|
||||
import { parseLinkedText } from 'vs/base/common/linkedText';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as env from 'vs/base/common/platform';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -35,6 +36,7 @@ import * as nls from 'vs/nls';
|
||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
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';
|
||||
@@ -75,6 +77,7 @@ import { createEditorFromSearchResult } from 'vs/workbench/contrib/searchEditor/
|
||||
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IPreferencesService, ISettingsEditorOptions } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { IPatternInfo, ISearchComplete, ISearchConfiguration, ISearchConfigurationProperties, ITextQuery, SearchCompletionExitCode, SearchSortOrder, TextSearchCompleteMessageType } from 'vs/workbench/services/search/common/search';
|
||||
import { TextSearchCompleteMessage } from 'vs/workbench/services/search/common/searchExtTypes';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
|
||||
const $ = dom.$;
|
||||
@@ -159,6 +162,7 @@ export class SearchView extends ViewPane {
|
||||
@IProgressService private readonly progressService: IProgressService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
|
||||
@@ -1524,7 +1528,7 @@ export class SearchView extends ViewPane {
|
||||
if (completed && completed.messages) {
|
||||
for (const message of completed.messages) {
|
||||
if (message.type === TextSearchCompleteMessageType.Information) {
|
||||
this.addMessage(message.text);
|
||||
this.addMessage(message);
|
||||
}
|
||||
else if (message.type === TextSearchCompleteMessageType.Warning) {
|
||||
warningMessage += (warningMessage ? ' - ' : '') + message.text;
|
||||
@@ -1641,8 +1645,8 @@ export class SearchView extends ViewPane {
|
||||
}
|
||||
}
|
||||
|
||||
private addMessage(message: string) {
|
||||
const linkedText = parseLinkedText(message);
|
||||
private addMessage(message: TextSearchCompleteMessage) {
|
||||
const linkedText = parseLinkedText(message.text);
|
||||
|
||||
const messageBox = this.messagesElement.firstChild as HTMLDivElement;
|
||||
if (!messageBox) {
|
||||
@@ -1659,7 +1663,26 @@ export class SearchView extends ViewPane {
|
||||
if (typeof node === 'string') {
|
||||
dom.append(span, document.createTextNode(node));
|
||||
} else {
|
||||
const link = this.instantiationService.createInstance(Link, node);
|
||||
const link = this.instantiationService.createInstance(Link, node, {
|
||||
opener: async href => {
|
||||
if (!message.trusted) { return; }
|
||||
const parsed = URI.parse(href, true);
|
||||
if (parsed.scheme === Schemas.command && message.trusted) {
|
||||
const result = await this.commandService.executeCommand(parsed.path);
|
||||
if ((result as any)?.triggerSearch) {
|
||||
this.triggerQueryChange();
|
||||
}
|
||||
} else if (parsed.scheme === Schemas.https) {
|
||||
this.openerService.open(parsed);
|
||||
} else {
|
||||
if (parsed.scheme === Schemas.command && !message.trusted) {
|
||||
this.notificationService.error(nls.localize('unable to open trust', "Unable to open command link from untrusted source: {0}", href));
|
||||
} else {
|
||||
this.notificationService.error(nls.localize('unable to open', "Unable to open unknown link: {0}", href));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
dom.append(span, link.el);
|
||||
this.messageDisposables.add(link);
|
||||
this.messageDisposables.add(attachLinkStyler(link, this.themeService));
|
||||
|
||||
@@ -538,12 +538,8 @@ class SearchEditorWorkingCopyEditorHandler extends Disposable implements IWorkbe
|
||||
|
||||
private installHandler(): void {
|
||||
this._register(this.workingCopyEditorService.registerHandler({
|
||||
handles: workingCopy => {
|
||||
return workingCopy.resource.scheme === SearchEditorConstants.SearchEditorScheme;
|
||||
},
|
||||
isOpen: (workingCopy, editor) => {
|
||||
return editor instanceof SearchEditorInput && isEqual(workingCopy.resource, editor.modelUri);
|
||||
},
|
||||
handles: workingCopy => workingCopy.resource.scheme === SearchEditorConstants.SearchEditorScheme,
|
||||
isOpen: (workingCopy, editor) => editor instanceof SearchEditorInput && isEqual(workingCopy.resource, editor.modelUri),
|
||||
createEditor: workingCopy => {
|
||||
const input = this.instantiationService.invokeFunction(getOrMakeSearchEditorInput, { from: 'model', modelUri: workingCopy.resource });
|
||||
input.setDirty(true);
|
||||
|
||||
@@ -55,6 +55,10 @@ import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { parseLinkedText } from 'vs/base/common/linkedText';
|
||||
import { Link } from 'vs/platform/opener/browser/link';
|
||||
import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { TextSearchCompleteMessage } from 'vs/workbench/services/search/common/searchExtTypes';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
const RESULT_LINE_REGEX = /^(\s+)(\d+)(:| )(\s+)(.*)$/;
|
||||
const FILE_LINE_REGEX = /^(\S.*):$/;
|
||||
@@ -97,6 +101,8 @@ export class SearchEditor extends BaseTextEditor {
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IContextKeyService readonly contextKeyService: IContextKeyService,
|
||||
@IOpenerService readonly openerService: IOpenerService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IEditorProgressService readonly progressService: IEditorProgressService,
|
||||
@ITextResourceConfigurationService textResourceService: ITextResourceConfigurationService,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@@ -557,7 +563,7 @@ export class SearchEditor extends BaseTextEditor {
|
||||
if (searchOperation && searchOperation.messages) {
|
||||
for (const message of searchOperation.messages) {
|
||||
if (message.type === TextSearchCompleteMessageType.Information) {
|
||||
this.addMessage(message.text);
|
||||
this.addMessage(message);
|
||||
}
|
||||
else if (message.type === TextSearchCompleteMessageType.Warning) {
|
||||
warningMessage += (warningMessage ? ' - ' : '') + message.text;
|
||||
@@ -576,8 +582,8 @@ export class SearchEditor extends BaseTextEditor {
|
||||
input.setMatchRanges(results.matchRanges);
|
||||
}
|
||||
|
||||
private addMessage(message: string) {
|
||||
const linkedText = parseLinkedText(message);
|
||||
private addMessage(message: TextSearchCompleteMessage) {
|
||||
const linkedText = parseLinkedText(message.text);
|
||||
|
||||
let messageBox: HTMLElement;
|
||||
if (this.messageBox.firstChild) {
|
||||
@@ -594,7 +600,25 @@ export class SearchEditor extends BaseTextEditor {
|
||||
if (typeof node === 'string') {
|
||||
DOM.append(messageBox, document.createTextNode(node));
|
||||
} else {
|
||||
const link = this.instantiationService.createInstance(Link, node);
|
||||
const link = this.instantiationService.createInstance(Link, node, {
|
||||
opener: async href => {
|
||||
const parsed = URI.parse(href, true);
|
||||
if (parsed.scheme === Schemas.command && message.trusted) {
|
||||
const result = await this.commandService.executeCommand(parsed.path);
|
||||
if ((result as any)?.triggerSearch) {
|
||||
this.triggerSearch();
|
||||
}
|
||||
} else if (parsed.scheme === Schemas.https) {
|
||||
this.openerService.open(parsed);
|
||||
} else {
|
||||
if (parsed.scheme === Schemas.command && !message.trusted) {
|
||||
this.notificationService.error(localize('unable to open trust', "Unable to open command link from untrusted source: {0}", href));
|
||||
} else {
|
||||
this.notificationService.error(localize('unable to open', "Unable to open unknown link: {0}", href));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
DOM.append(messageBox, link.el);
|
||||
this.messageDisposables.add(link);
|
||||
this.messageDisposables.add(attachLinkStyler(link, this.themeService));
|
||||
@@ -652,7 +676,9 @@ export class SearchEditor extends BaseTextEditor {
|
||||
this.saveViewState();
|
||||
|
||||
await super.setInput(newInput, options, context, token);
|
||||
if (token.isCancellationRequested) { return; }
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { configurationModel, resultsModel } = await newInput.getModels();
|
||||
if (token.isCancellationRequested) { return; }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user