mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-24 00:05:46 +01:00
Merge remote-tracking branch 'origin/main' into alex/update-playwright
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
"labels": {
|
||||
"L10N": {"assign": []},
|
||||
"VIM": {"assign": []},
|
||||
"accessibility": { "assign": ["isidorn"]},
|
||||
"accessibility": { "assign": ["isidorn", "sana-ajani"]},
|
||||
"api": {"assign": ["jrieken"]},
|
||||
"api-finalization": {"assign": []},
|
||||
"api-proposal": {"assign": ["jrieken"]},
|
||||
|
||||
@@ -409,5 +409,11 @@
|
||||
"gjsjohnmurray",
|
||||
"IllusionMH"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "*workspace-trust-docs",
|
||||
"action": "close",
|
||||
"comment": "This issue appears to be the result of the new workspace trust feature shipped in June 2021. This security-focused feature has major impact on the functionality of VS Code. Due to the volume of issues, we ask that you take some time to review our [comprehensive documentation](https://aka.ms/vscode-workspace-trust) on the feature. If your issue is still not resolved, please let us know."
|
||||
}
|
||||
]
|
||||
|
||||
@@ -11,7 +11,6 @@ export function activate() {
|
||||
});
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.classList.add('markdown-style');
|
||||
style.textContent = `
|
||||
.emptyMarkdownCell::before {
|
||||
content: "${document.documentElement.style.getPropertyValue('--notebook-cell-markup-empty-content')}";
|
||||
@@ -134,7 +133,10 @@ export function activate() {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
`;
|
||||
document.head.append(style);
|
||||
const template = document.createElement('template');
|
||||
template.classList.add('markdown-style');
|
||||
template.content.appendChild(style);
|
||||
document.head.appendChild(template);
|
||||
|
||||
return {
|
||||
renderOutputItem: (outputInfo: { text(): string }, element: HTMLElement) => {
|
||||
@@ -148,8 +150,12 @@ export function activate() {
|
||||
previewRoot.appendChild(defaultStyles.cloneNode(true));
|
||||
|
||||
// And then contributed styles
|
||||
for (const markdownStyleNode of document.getElementsByClassName('markdown-style')) {
|
||||
previewRoot.appendChild(markdownStyleNode.cloneNode(true));
|
||||
for (const element of document.getElementsByClassName('markdown-style')) {
|
||||
if (element instanceof HTMLTemplateElement) {
|
||||
previewRoot.appendChild(element.content.cloneNode(true));
|
||||
} else {
|
||||
previewRoot.appendChild(element.cloneNode(true));
|
||||
}
|
||||
}
|
||||
|
||||
previewNode = document.createElement('div');
|
||||
|
||||
@@ -18,16 +18,20 @@ export async function activate(ctx: {
|
||||
link.rel = 'stylesheet';
|
||||
link.classList.add('markdown-style');
|
||||
link.href = styleHref;
|
||||
document.head.append(link);
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.classList.add('markdown-style');
|
||||
style.textContent = `
|
||||
.katex-error {
|
||||
color: var(--vscode-editorError-foreground);
|
||||
}
|
||||
`;
|
||||
document.head.append(style);
|
||||
|
||||
// Put Everything into a template
|
||||
const styleTemplate = document.createElement('template');
|
||||
styleTemplate.classList.add('markdown-style');
|
||||
styleTemplate.content.appendChild(style);
|
||||
styleTemplate.content.appendChild(link);
|
||||
document.head.appendChild(styleTemplate);
|
||||
|
||||
const katex = require('@iktakahiro/markdown-it-katex');
|
||||
markdownItRenderer.extendMarkdownIt((md: markdownIt.MarkdownIt) => {
|
||||
|
||||
@@ -137,7 +137,7 @@ class DiagnosticSettings {
|
||||
const currentSettings = this.get(language);
|
||||
const newSettings = f(currentSettings);
|
||||
this._languageSettings.set(language, newSettings);
|
||||
return areLanguageDiagnosticSettingsEqual(currentSettings, newSettings);
|
||||
return !areLanguageDiagnosticSettingsEqual(currentSettings, newSettings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -668,8 +668,7 @@ import { assertNoRpc } from '../utils';
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/119826
|
||||
suite.skip('environmentVariableCollection', () => {
|
||||
suite('environmentVariableCollection', () => {
|
||||
test('should have collection variables apply to terminals immediately after setting', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.58.0",
|
||||
"distro": "3f43781e788d694f33746808cc5182852222f935",
|
||||
"distro": "f9acd3d731fc630bf6b665d551d5fa12ce0560e6",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
@@ -46,7 +46,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
:: Tests in the extension host
|
||||
|
||||
set ALL_PLATFORMS_API_TESTS_EXTRA_ARGS=--disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-sandbox --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
set ALL_PLATFORMS_API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
|
||||
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests %ALL_PLATFORMS_API_TESTS_EXTRA_ARGS%
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
@@ -62,7 +62,7 @@ after_suite
|
||||
|
||||
# Tests in the extension host
|
||||
|
||||
ALL_PLATFORMS_API_TESTS_EXTRA_ARGS="--disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
|
||||
ALL_PLATFORMS_API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
|
||||
|
||||
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_EXTRA_ARGS $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests $ALL_PLATFORMS_API_TESTS_EXTRA_ARGS
|
||||
after_suite
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
/**
|
||||
* A helper that will execute a provided function when the provided HTMLElement receives
|
||||
@@ -70,7 +71,7 @@ export const DataTransfers = {
|
||||
/**
|
||||
* Typically transfer type for copy/paste transfers.
|
||||
*/
|
||||
TEXT: 'text/plain'
|
||||
TEXT: Mimes.text
|
||||
};
|
||||
|
||||
export function applyDragImage(event: DragEvent, label: string | null, clazz: string): void {
|
||||
|
||||
+13
-14
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { TimeoutTimer } from 'vs/base/common/async';
|
||||
@@ -975,8 +974,8 @@ class FocusTracker extends Disposable implements IFocusTracker {
|
||||
}
|
||||
};
|
||||
|
||||
this._register(domEvent(element, EventType.FOCUS, true)(onFocus));
|
||||
this._register(domEvent(element, EventType.BLUR, true)(onBlur));
|
||||
this._register(addDisposableListener(element, EventType.FOCUS, onFocus, true));
|
||||
this._register(addDisposableListener(element, EventType.BLUR, onBlur, true));
|
||||
}
|
||||
|
||||
refreshState() {
|
||||
@@ -1480,7 +1479,7 @@ export class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
|
||||
metaKey: false
|
||||
};
|
||||
|
||||
this._subscriptions.add(domEvent(window, 'keydown', true)(e => {
|
||||
this._subscriptions.add(addDisposableListener(window, 'keydown', e => {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
@@ -1515,9 +1514,9 @@ export class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
|
||||
this._keyStatus.event = e;
|
||||
this.fire(this._keyStatus);
|
||||
}
|
||||
}));
|
||||
}, true));
|
||||
|
||||
this._subscriptions.add(domEvent(window, 'keyup', true)(e => {
|
||||
this._subscriptions.add(addDisposableListener(window, 'keyup', e => {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
@@ -1547,23 +1546,23 @@ export class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
|
||||
this._keyStatus.event = e;
|
||||
this.fire(this._keyStatus);
|
||||
}
|
||||
}));
|
||||
}, true));
|
||||
|
||||
this._subscriptions.add(domEvent(document.body, 'mousedown', true)(e => {
|
||||
this._subscriptions.add(addDisposableListener(document.body, 'mousedown', () => {
|
||||
this._keyStatus.lastKeyPressed = undefined;
|
||||
}));
|
||||
}, true));
|
||||
|
||||
this._subscriptions.add(domEvent(document.body, 'mouseup', true)(e => {
|
||||
this._subscriptions.add(addDisposableListener(document.body, 'mouseup', () => {
|
||||
this._keyStatus.lastKeyPressed = undefined;
|
||||
}));
|
||||
}, true));
|
||||
|
||||
this._subscriptions.add(domEvent(document.body, 'mousemove', true)(e => {
|
||||
this._subscriptions.add(addDisposableListener(document.body, 'mousemove', e => {
|
||||
if (e.buttons) {
|
||||
this._keyStatus.lastKeyPressed = undefined;
|
||||
}
|
||||
}));
|
||||
}, true));
|
||||
|
||||
this._subscriptions.add(domEvent(window, 'blur')(e => {
|
||||
this._subscriptions.add(addDisposableListener(window, 'blur', () => {
|
||||
this.resetKeyStatus();
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -14,24 +14,7 @@ export interface IDomEvent {
|
||||
(element: EventHandler, type: string, useCapture?: boolean): BaseEvent<unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `DomEmitter` instead
|
||||
*/
|
||||
export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?: boolean) => {
|
||||
const fn = (e: Event) => emitter.fire(e);
|
||||
const emitter = new Emitter<Event>({
|
||||
onFirstListenerAdd: () => {
|
||||
element.addEventListener(type, fn, useCapture);
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
element.removeEventListener(type, fn, useCapture);
|
||||
}
|
||||
});
|
||||
|
||||
return emitter.event;
|
||||
};
|
||||
|
||||
export interface DOMEventMap extends HTMLElementEventMap {
|
||||
export interface DOMEventMap extends HTMLElementEventMap, DocumentEventMap {
|
||||
'-monaco-gesturetap': GestureEvent;
|
||||
'-monaco-gesturechange': GestureEvent;
|
||||
'-monaco-gesturestart': GestureEvent;
|
||||
@@ -47,6 +30,8 @@ export class DomEmitter<K extends keyof DOMEventMap> implements IDisposable {
|
||||
return this.emitter.event;
|
||||
}
|
||||
|
||||
constructor(element: Document, type: DocumentEventMap, useCapture?: boolean);
|
||||
constructor(element: EventHandler, type: K, useCapture?: boolean);
|
||||
constructor(element: EventHandler, type: K, useCapture?: boolean) {
|
||||
const fn = (e: Event) => this.emitter.fire(e as DOMEventMap[K]);
|
||||
this.emitter = new Emitter({
|
||||
|
||||
@@ -20,7 +20,7 @@ import { resolvePath } from 'vs/base/common/resources';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { renderLabelWithIcons } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
export interface MarkedOptions extends marked.MarkedOptions {
|
||||
baseUrl?: never;
|
||||
@@ -186,7 +186,9 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
}
|
||||
|
||||
if (options.actionHandler) {
|
||||
options.actionHandler.disposeables.add(Event.any<MouseEvent>(domEvent(element, 'click'), domEvent(element, 'auxclick'))(e => {
|
||||
const onClick = options.actionHandler.disposeables.add(new DomEmitter(element, 'click'));
|
||||
const onAuxClick = options.actionHandler.disposeables.add(new DomEmitter(element, 'auxclick'));
|
||||
options.actionHandler.disposeables.add(Event.any(onClick.event, onAuxClick.event)(e => {
|
||||
const mouseEvent = new StandardMouseEvent(e);
|
||||
if (!mouseEvent.leftButton && !mouseEvent.middleButton) {
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'vs/css!./dialog';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { $, hide, show, EventHelper, clearNode, isAncestor, addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
@@ -220,7 +219,7 @@ export class Dialog extends Disposable {
|
||||
});
|
||||
|
||||
// Handle keyboard events gloably: Tab, Arrow-Left/Right
|
||||
this._register(domEvent(window, 'keydown', true)((e: KeyboardEvent) => {
|
||||
this._register(addDisposableListener(window, 'keydown', e => {
|
||||
const evt = new StandardKeyboardEvent(e);
|
||||
|
||||
if (evt.equals(KeyMod.Alt)) {
|
||||
@@ -321,9 +320,9 @@ export class Dialog extends Disposable {
|
||||
} else if (this.options.keyEventProcessor) {
|
||||
this.options.keyEventProcessor(evt);
|
||||
}
|
||||
}));
|
||||
}, true));
|
||||
|
||||
this._register(domEvent(window, 'keyup', true)((e: KeyboardEvent) => {
|
||||
this._register(addDisposableListener(window, 'keyup', e => {
|
||||
EventHelper.stop(e, true);
|
||||
const evt = new StandardKeyboardEvent(e);
|
||||
|
||||
@@ -333,10 +332,10 @@ export class Dialog extends Disposable {
|
||||
checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
|
||||
});
|
||||
}
|
||||
}));
|
||||
}, true));
|
||||
|
||||
// Detect focus out
|
||||
this._register(domEvent(this.element, 'focusout', false)((e: FocusEvent) => {
|
||||
this._register(addDisposableListener(this.element, 'focusout', e => {
|
||||
if (!!e.relatedTarget && !!this.element) {
|
||||
if (!isAncestor(e.relatedTarget as HTMLElement, this.element)) {
|
||||
this.focusToReturn = e.relatedTarget as HTMLElement;
|
||||
@@ -347,7 +346,7 @@ export class Dialog extends Disposable {
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, false));
|
||||
|
||||
const spinModifierClassName = 'codicon-modifier-spin';
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
import { isFunction, isString } from 'vs/base/common/types';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IIconLabelMarkdownString } from 'vs/base/browser/ui/iconLabel/iconLabel';
|
||||
import { IHoverDelegate, IHoverDelegateOptions, IHoverDelegateTarget } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
|
||||
import { IHoverDelegate, IHoverDelegateTarget } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
|
||||
|
||||
export function setupNativeHover(htmlElement: HTMLElement, tooltip: string | IIconLabelMarkdownString | undefined): void {
|
||||
@@ -32,79 +32,90 @@ export function setupCustomHover(hoverDelegate: IHoverDelegate, htmlElement: HTM
|
||||
|
||||
const tooltip = getTooltipForCustom(markdownTooltip);
|
||||
|
||||
let hoverOptions: IHoverDelegateOptions | undefined;
|
||||
let mouseX: number | undefined;
|
||||
let isHovering = false;
|
||||
let tokenSource: CancellationTokenSource;
|
||||
let hoverDisposable: IDisposable | undefined;
|
||||
let hoverPreparation: IDisposable | undefined;
|
||||
|
||||
const mouseOverDomEmitter = new DomEmitter(htmlElement, dom.EventType.MOUSE_OVER, true);
|
||||
mouseOverDomEmitter.event((e: MouseEvent) => {
|
||||
if (isHovering) {
|
||||
let hoverWidget: IDisposable | undefined;
|
||||
|
||||
const mouseEnter = (e: MouseEvent) => {
|
||||
if (hoverPreparation) {
|
||||
return;
|
||||
}
|
||||
tokenSource = new CancellationTokenSource();
|
||||
function mouseLeaveOrDown(e: MouseEvent): void {
|
||||
|
||||
const tokenSource = new CancellationTokenSource();
|
||||
|
||||
const mouseLeaveOrDown = (e: MouseEvent) => {
|
||||
const isMouseDown = e.type === dom.EventType.MOUSE_DOWN;
|
||||
if (isMouseDown) {
|
||||
hoverDisposable?.dispose();
|
||||
hoverDisposable = undefined;
|
||||
hoverWidget?.dispose();
|
||||
hoverWidget = undefined;
|
||||
}
|
||||
if (isMouseDown || (<any>e).fromElement === htmlElement) {
|
||||
isHovering = false;
|
||||
hoverOptions = undefined;
|
||||
tokenSource.dispose(true);
|
||||
mouseLeaveDomEmitter.dispose();
|
||||
mouseDownDomEmitter.dispose();
|
||||
hoverPreparation?.dispose();
|
||||
hoverPreparation = undefined;
|
||||
}
|
||||
}
|
||||
const mouseLeaveDomEmitter = new DomEmitter(htmlElement, dom.EventType.MOUSE_LEAVE, true);
|
||||
mouseLeaveDomEmitter.event(mouseLeaveOrDown);
|
||||
const mouseDownDomEmitter = new DomEmitter(htmlElement, dom.EventType.MOUSE_DOWN, true);
|
||||
mouseDownDomEmitter.event(mouseLeaveOrDown);
|
||||
isHovering = true;
|
||||
};
|
||||
const mouseLeaveDomListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_LEAVE, mouseLeaveOrDown, true);
|
||||
const mouseDownDownListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_DOWN, mouseLeaveOrDown, true);
|
||||
|
||||
function mouseMove(e: MouseEvent): void {
|
||||
mouseX = e.x;
|
||||
const target: IHoverDelegateTarget = {
|
||||
targetElements: [htmlElement],
|
||||
dispose: () => { }
|
||||
};
|
||||
|
||||
let mouseMoveDomListener: IDisposable | undefined;
|
||||
if (hoverDelegate.placement === undefined || hoverDelegate.placement === 'mouse') {
|
||||
const mouseMove = (e: MouseEvent) => target.x = e.x + 10;
|
||||
mouseMoveDomListener = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_MOVE, mouseMove, true);
|
||||
}
|
||||
const mouseMoveDomEmitter = new DomEmitter(htmlElement, dom.EventType.MOUSE_MOVE, true);
|
||||
mouseMoveDomEmitter.event(mouseMove);
|
||||
setTimeout(async () => {
|
||||
if (isHovering && tooltip) {
|
||||
// Re-use the already computed hover options if they exist.
|
||||
if (!hoverOptions) {
|
||||
const target: IHoverDelegateTarget = {
|
||||
targetElements: [htmlElement],
|
||||
dispose: () => { }
|
||||
};
|
||||
hoverOptions = {
|
||||
text: localize('iconLabel.loading', "Loading..."),
|
||||
|
||||
const showHover = async () => {
|
||||
if (hoverPreparation) {
|
||||
|
||||
const hoverOptions = {
|
||||
text: localize('iconLabel.loading', "Loading..."),
|
||||
target,
|
||||
hoverPosition: HoverPosition.BELOW
|
||||
};
|
||||
hoverWidget?.dispose();
|
||||
hoverWidget = hoverDelegate.showHover(hoverOptions);
|
||||
|
||||
const resolvedTooltip = (await tooltip(tokenSource.token)) ?? (!isString(markdownTooltip) ? markdownTooltip.markdownNotSupportedFallback : undefined);
|
||||
|
||||
hoverWidget?.dispose();
|
||||
hoverWidget = undefined;
|
||||
|
||||
// awaiting the tooltip could take a while. Make sure we're still preparing to hover.
|
||||
if (resolvedTooltip && hoverPreparation) {
|
||||
const hoverOptions = {
|
||||
text: resolvedTooltip,
|
||||
target,
|
||||
showPointer: hoverDelegate.placement === 'element',
|
||||
hoverPosition: HoverPosition.BELOW
|
||||
};
|
||||
hoverDisposable = adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
|
||||
|
||||
const resolvedTooltip = (await tooltip(tokenSource.token)) ?? (!isString(markdownTooltip) ? markdownTooltip.markdownNotSupportedFallback : undefined);
|
||||
if (resolvedTooltip) {
|
||||
hoverOptions = {
|
||||
text: resolvedTooltip,
|
||||
target,
|
||||
showPointer: hoverDelegate.placement === 'element',
|
||||
hoverPosition: HoverPosition.BELOW
|
||||
};
|
||||
// awaiting the tooltip could take a while. Make sure we're still hovering.
|
||||
hoverDisposable = adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
|
||||
} else if (hoverDisposable) {
|
||||
hoverDisposable.dispose();
|
||||
hoverDisposable = undefined;
|
||||
}
|
||||
hoverWidget = hoverDelegate.showHover(hoverOptions);
|
||||
}
|
||||
|
||||
}
|
||||
mouseMoveDomEmitter.dispose();
|
||||
}, hoverDelegate.delay);
|
||||
mouseMoveDomListener?.dispose();
|
||||
};
|
||||
const timeout = new RunOnceScheduler(showHover, hoverDelegate.delay);
|
||||
timeout.schedule();
|
||||
|
||||
hoverPreparation = toDisposable(() => {
|
||||
timeout.dispose();
|
||||
mouseMoveDomListener?.dispose();
|
||||
mouseDownDownListener.dispose();
|
||||
mouseLeaveDomListener.dispose();
|
||||
tokenSource.dispose(true);
|
||||
});
|
||||
};
|
||||
const mouseOverDomEmitter = dom.addDisposableListener(htmlElement, dom.EventType.MOUSE_OVER, mouseEnter, true);
|
||||
return toDisposable(() => {
|
||||
mouseOverDomEmitter.dispose();
|
||||
hoverPreparation?.dispose();
|
||||
hoverWidget?.dispose();
|
||||
});
|
||||
return mouseOverDomEmitter;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,13 +129,3 @@ function getTooltipForCustom(markdownTooltip: string | IIconLabelMarkdownString)
|
||||
return async () => markdown;
|
||||
}
|
||||
}
|
||||
|
||||
function adjustXAndShowCustomHover(hoverOptions: IHoverDelegateOptions | undefined, mouseX: number | undefined, hoverDelegate: IHoverDelegate, isHovering: boolean): IDisposable | undefined {
|
||||
if (hoverOptions && isHovering) {
|
||||
if (mouseX !== undefined && (hoverDelegate.placement === undefined || hoverDelegate.placement === 'mouse')) {
|
||||
(<IHoverDelegateTarget>hoverOptions.target).x = mouseX + 10;
|
||||
}
|
||||
return hoverDelegate.showHover(hoverOptions);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import { HistoryNavigator } from 'vs/base/common/history';
|
||||
import { IHistoryNavigationWidget } from 'vs/base/browser/history';
|
||||
import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -189,13 +189,14 @@ export class InputBox extends Widget {
|
||||
// from ScrollableElement to DOM
|
||||
this._register(this.scrollableElement.onScroll(e => this.input.scrollTop = e.scrollTop));
|
||||
|
||||
const onSelectionChange = Event.filter(domEvent(document, 'selectionchange'), () => {
|
||||
const onSelectionChange = this._register(new DomEmitter(document, 'selectionchange'));
|
||||
const onAnchoredSelectionChange = Event.filter(onSelectionChange.event, () => {
|
||||
const selection = document.getSelection();
|
||||
return selection?.anchorNode === wrapper;
|
||||
});
|
||||
|
||||
// from DOM to ScrollableElement
|
||||
this._register(onSelectionChange(this.updateScrollDimensions, this));
|
||||
this._register(onAnchoredSelectionChange(this.updateScrollDimensions, this));
|
||||
this._register(this.onDidHeightChange(this.updateScrollDimensions, this));
|
||||
} else {
|
||||
this.input.type = this.options.type || 'text';
|
||||
|
||||
@@ -7,7 +7,6 @@ import { getOrDefault } from 'vs/base/common/objects';
|
||||
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Gesture, EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { ScrollEvent, ScrollbarVisibility, INewScrollDimensions, Scrollable } from 'vs/base/common/scrollable';
|
||||
import { RangeMap, shift } from './rangeMap';
|
||||
@@ -21,7 +20,8 @@ import { DataTransfers, StaticDND, IDragAndDropData } from 'vs/base/browser/dnd'
|
||||
import { disposableTimeout, Delayer } from 'vs/base/common/async';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { $, animate, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { $, addDisposableListener, animate, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
interface IItem<T> {
|
||||
readonly id: string;
|
||||
@@ -339,17 +339,16 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
container.appendChild(this.domNode);
|
||||
|
||||
this.scrollableElement.onScroll(this.onScroll, this, this.disposables);
|
||||
domEvent(this.rowsContainer, TouchEventType.Change)(e => this.onTouchChange(e as GestureEvent), this, this.disposables);
|
||||
this.disposables.add(addDisposableListener(this.rowsContainer, TouchEventType.Change, e => this.onTouchChange(e as GestureEvent)));
|
||||
|
||||
// Prevent the monaco-scrollable-element from scrolling
|
||||
// https://github.com/microsoft/vscode/issues/44181
|
||||
domEvent(this.scrollableElement.getDomNode(), 'scroll')
|
||||
(e => (e.target as HTMLElement).scrollTop = 0, null, this.disposables);
|
||||
this.disposables.add(addDisposableListener(this.scrollableElement.getDomNode(), 'scroll', e => (e.target as HTMLElement).scrollTop = 0));
|
||||
|
||||
Event.map(domEvent(this.domNode, 'dragover'), e => this.toDragEvent(e))(this.onDragOver, this, this.disposables);
|
||||
Event.map(domEvent(this.domNode, 'drop'), e => this.toDragEvent(e))(this.onDrop, this, this.disposables);
|
||||
domEvent(this.domNode, 'dragleave')(this.onDragLeave, this, this.disposables);
|
||||
domEvent(window, 'dragend')(this.onDragEnd, this, this.disposables);
|
||||
this.disposables.add(addDisposableListener(this.domNode, 'dragover', e => this.onDragOver(this.toDragEvent(e))));
|
||||
this.disposables.add(addDisposableListener(this.domNode, 'drop', e => this.onDrop(this.toDragEvent(e))));
|
||||
this.disposables.add(addDisposableListener(this.domNode, 'dragleave', _ => this.onDragLeave()));
|
||||
this.disposables.add(addDisposableListener(this.domNode, 'dragend', e => this.onDragEnd(e)));
|
||||
|
||||
this.setRowLineHeight = getOrDefault(options, o => o.setRowLineHeight, DefaultOptions.setRowLineHeight);
|
||||
this.setRowHeight = getOrDefault(options, o => o.setRowHeight, DefaultOptions.setRowHeight);
|
||||
@@ -775,8 +774,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
item.row.domNode.draggable = !!uri;
|
||||
|
||||
if (uri) {
|
||||
const onDragStart = domEvent(item.row.domNode, 'dragstart');
|
||||
item.dragStartDisposable = onDragStart(event => this.onDragStart(item.element, uri, event));
|
||||
item.dragStartDisposable = addDisposableListener(item.row.domNode, 'dragstart', event => this.onDragStart(item.element, uri, event));
|
||||
}
|
||||
|
||||
if (this.horizontalScrolling) {
|
||||
@@ -890,17 +888,17 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
|
||||
// Events
|
||||
|
||||
@memoize get onMouseClick(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'click'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseDblClick(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'dblclick'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseMiddleClick(): Event<IListMouseEvent<T>> { return Event.filter(Event.map(domEvent(this.domNode, 'auxclick'), e => this.toMouseEvent(e as MouseEvent)), e => e.browserEvent.button === 1); }
|
||||
@memoize get onMouseUp(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'mouseup'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseDown(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'mousedown'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseOver(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'mouseover'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseMove(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'mousemove'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseOut(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'mouseout'), e => this.toMouseEvent(e)); }
|
||||
@memoize get onContextMenu(): Event<IListMouseEvent<T> | IListGestureEvent<T>> { return Event.any(Event.map(domEvent(this.domNode, 'contextmenu'), e => this.toMouseEvent(e)), Event.map(domEvent(this.domNode, TouchEventType.Contextmenu) as Event<GestureEvent>, e => this.toGestureEvent(e))); }
|
||||
@memoize get onTouchStart(): Event<IListTouchEvent<T>> { return Event.map(domEvent(this.domNode, 'touchstart'), e => this.toTouchEvent(e)); }
|
||||
@memoize get onTap(): Event<IListGestureEvent<T>> { return Event.map(domEvent(this.rowsContainer, TouchEventType.Tap), e => this.toGestureEvent(e as GestureEvent)); }
|
||||
@memoize get onMouseClick(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'click')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseDblClick(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'dblclick')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseMiddleClick(): Event<IListMouseEvent<T>> { return Event.filter(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'auxclick')).event, e => this.toMouseEvent(e as MouseEvent)), e => e.browserEvent.button === 1); }
|
||||
@memoize get onMouseUp(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mouseup')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseDown(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mousedown')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseOver(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mouseover')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseMove(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mousemove')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onMouseOut(): Event<IListMouseEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mouseout')).event, e => this.toMouseEvent(e)); }
|
||||
@memoize get onContextMenu(): Event<IListMouseEvent<T> | IListGestureEvent<T>> { return Event.any(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'contextmenu')).event, e => this.toMouseEvent(e)), Event.map(this.disposables.add(new DomEmitter(this.domNode, TouchEventType.Contextmenu)).event as Event<GestureEvent>, e => this.toGestureEvent(e))); }
|
||||
@memoize get onTouchStart(): Event<IListTouchEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'touchstart')).event, e => this.toTouchEvent(e)); }
|
||||
@memoize get onTap(): Event<IListGestureEvent<T>> { return Event.map(this.disposables.add(new DomEmitter(this.rowsContainer, TouchEventType.Tap)).event, e => this.toGestureEvent(e as GestureEvent)); }
|
||||
|
||||
private toMouseEvent(browserEvent: MouseEvent): IListMouseEvent<T> {
|
||||
const index = this.getItemIndexFromEventTarget(browserEvent.target || null);
|
||||
|
||||
@@ -13,7 +13,7 @@ import { Gesture } from 'vs/base/browser/touch';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Event, Emitter, EventBufferer } from 'vs/base/common/event';
|
||||
import { domEvent, stopEvent } from 'vs/base/browser/event';
|
||||
import { DomEmitter, stopEvent } from 'vs/base/browser/event';
|
||||
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListError, IKeyboardNavigationDelegate } from './list';
|
||||
import { ListView, IListViewOptions, IListViewDragAndDrop, IListViewAccessibilityProvider, IListViewOptionsUpdate } from './listView';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
@@ -257,7 +257,7 @@ class KeyboardController<T> implements IDisposable {
|
||||
) {
|
||||
const multipleSelectionSupport = options.multipleSelectionSupport !== false;
|
||||
|
||||
const onKeyDown = Event.chain(domEvent(view.domNode, 'keydown'))
|
||||
const onKeyDown = Event.chain(this.disposables.add(new DomEmitter(view.domNode, 'keydown')).event)
|
||||
.filter(e => !isInputElement(e.target as HTMLElement))
|
||||
.map(e => new StandardKeyboardEvent(e));
|
||||
|
||||
@@ -394,7 +394,7 @@ class TypeLabelController<T> implements IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const onChar = Event.chain(domEvent(this.view.domNode, 'keydown'))
|
||||
const onChar = Event.chain(this.enabledDisposables.add(new DomEmitter(this.view.domNode, 'keydown')).event)
|
||||
.filter(e => !isInputElement(e.target as HTMLElement))
|
||||
.filter(() => this.automaticKeyboardNavigation || this.triggered)
|
||||
.map(event => new StandardKeyboardEvent(event))
|
||||
@@ -477,7 +477,7 @@ class DOMFocusController<T> implements IDisposable {
|
||||
private list: List<T>,
|
||||
private view: ListView<T>
|
||||
) {
|
||||
const onKeyDown = Event.chain(domEvent(view.domNode, 'keydown'))
|
||||
const onKeyDown = Event.chain(this.disposables.add(new DomEmitter(view.domNode, 'keydown')).event)
|
||||
.filter(e => !isInputElement(e.target as HTMLElement))
|
||||
.map(e => new StandardKeyboardEvent(e));
|
||||
|
||||
@@ -1184,14 +1184,14 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
@memoize get onContextMenu(): Event<IListContextMenuEvent<T>> {
|
||||
let didJustPressContextMenuKey = false;
|
||||
|
||||
const fromKeyDown = Event.chain(domEvent(this.view.domNode, 'keydown'))
|
||||
const fromKeyDown = Event.chain(this.disposables.add(new DomEmitter(this.view.domNode, 'keydown')).event)
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.filter(e => didJustPressContextMenuKey = e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))
|
||||
.map(stopEvent)
|
||||
.filter(() => false)
|
||||
.event as Event<any>;
|
||||
|
||||
const fromKeyUp = Event.chain(domEvent(this.view.domNode, 'keyup'))
|
||||
const fromKeyUp = Event.chain(this.disposables.add(new DomEmitter(this.view.domNode, 'keyup')).event)
|
||||
.forEach(() => didJustPressContextMenuKey = false)
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.filter(e => e.keyCode === KeyCode.ContextMenu || (e.shiftKey && e.keyCode === KeyCode.F10))
|
||||
@@ -1213,12 +1213,12 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
return Event.any<IListContextMenuEvent<T>>(fromKeyDown, fromKeyUp, fromMouse);
|
||||
}
|
||||
|
||||
get onKeyDown(): Event<KeyboardEvent> { return domEvent(this.view.domNode, 'keydown'); }
|
||||
get onKeyUp(): Event<KeyboardEvent> { return domEvent(this.view.domNode, 'keyup'); }
|
||||
get onKeyPress(): Event<KeyboardEvent> { return domEvent(this.view.domNode, 'keypress'); }
|
||||
@memoize get onKeyDown(): Event<KeyboardEvent> { return this.disposables.add(new DomEmitter(this.view.domNode, 'keydown')).event; }
|
||||
@memoize get onKeyUp(): Event<KeyboardEvent> { return this.disposables.add(new DomEmitter(this.view.domNode, 'keyup')).event; }
|
||||
@memoize get onKeyPress(): Event<KeyboardEvent> { return this.disposables.add(new DomEmitter(this.view.domNode, 'keypress')).event; }
|
||||
|
||||
readonly onDidFocus: Event<void>;
|
||||
readonly onDidBlur: Event<void>;
|
||||
@memoize get onDidFocus(): Event<void> { return Event.signal(this.disposables.add(new DomEmitter(this.view.domNode, 'focus', true)).event); }
|
||||
@memoize get onDidBlur(): Event<void> { return Event.signal(this.disposables.add(new DomEmitter(this.view.domNode, 'blur', true)).event); }
|
||||
|
||||
private readonly _onDidDispose = new Emitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
@@ -1277,9 +1277,6 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
|
||||
this.disposables.add(this.view);
|
||||
this.disposables.add(this._onDidDispose);
|
||||
|
||||
this.onDidFocus = Event.map(domEvent(this.view.domNode, 'focus', true), () => null!);
|
||||
this.onDidBlur = Event.map(domEvent(this.view.domNode, 'blur', true), () => null!);
|
||||
|
||||
this.disposables.add(new DOMFocusController(this, this.view));
|
||||
|
||||
if (typeof _options.keyboardSupport !== 'boolean' || _options.keyboardSupport) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import * as arrays from 'vs/base/common/arrays';
|
||||
import { IContextViewProvider, AnchorPosition } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IListVirtualDelegate, IListRenderer, IListEvent } from 'vs/base/browser/ui/list/list';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { ISelectBoxDelegate, ISelectOptionItem, ISelectBoxOptions, ISelectBoxStyles, ISelectData } from 'vs/base/browser/ui/selectBox/selectBox';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
@@ -736,7 +736,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
}
|
||||
|
||||
// SetUp list keyboard controller - control navigation, disabled items, focus
|
||||
const onSelectDropDownKeyDown = Event.chain(domEvent(this.selectDropDownListContainer, 'keydown'))
|
||||
const onKeyDown = this._register(new DomEmitter(this.selectDropDownListContainer, 'keydown'));
|
||||
const onSelectDropDownKeyDown = Event.chain(onKeyDown.event)
|
||||
.filter(() => this.selectList.length > 0)
|
||||
.map(e => new StandardKeyboardEvent(e));
|
||||
|
||||
@@ -752,7 +753,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
|
||||
|
||||
// SetUp list mouse controller - control navigation, disabled items, focus
|
||||
|
||||
this._register(Event.chain(domEvent(this.selectList.getHTMLElement(), 'mouseup'))
|
||||
const onMouseUp = this._register(new DomEmitter(this.selectList.getHTMLElement(), 'mouseup'));
|
||||
this._register(Event.chain(onMouseUp.event)
|
||||
.filter(() => this.selectList.length > 0)
|
||||
.on(e => this.onMouseUp(e), this));
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
import 'vs/css!./paneview';
|
||||
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { $, append, trackFocus, EventHelper, clearNode } from 'vs/base/browser/dom';
|
||||
import { $, append, trackFocus, EventHelper, clearNode, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { SplitView, IView } from './splitview';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
@@ -17,6 +16,7 @@ import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ScrollEvent } from 'vs/base/common/scrollable';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
export interface IPaneOptions {
|
||||
minimumBodySize?: number;
|
||||
@@ -220,8 +220,8 @@ export abstract class Pane extends Disposable implements IView {
|
||||
|
||||
this.updateHeader();
|
||||
|
||||
|
||||
const onHeaderKeyDown = Event.chain(domEvent(this.header, 'keydown'))
|
||||
const onKeyDown = this._register(new DomEmitter(this.header, 'keydown'));
|
||||
const onHeaderKeyDown = Event.chain(onKeyDown.event)
|
||||
.map(e => new StandardKeyboardEvent(e));
|
||||
|
||||
this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.Enter || e.keyCode === KeyCode.Space)
|
||||
@@ -233,12 +233,11 @@ export abstract class Pane extends Disposable implements IView {
|
||||
this._register(onHeaderKeyDown.filter(e => e.keyCode === KeyCode.RightArrow)
|
||||
.event(() => this.setExpanded(true), null));
|
||||
|
||||
this._register(domEvent(this.header, 'click')
|
||||
(e => {
|
||||
if (!e.defaultPrevented) {
|
||||
this.setExpanded(!this.isExpanded());
|
||||
}
|
||||
}, null));
|
||||
this._register(addDisposableListener(this.header, 'click', e => {
|
||||
if (!e.defaultPrevented) {
|
||||
this.setExpanded(!this.isExpanded());
|
||||
}
|
||||
}));
|
||||
|
||||
this.body = append(this.element, $('.pane-body'));
|
||||
this.renderBody(this.body);
|
||||
@@ -308,11 +307,11 @@ class PaneDraggable extends Disposable {
|
||||
super();
|
||||
|
||||
pane.draggableElement.draggable = true;
|
||||
this._register(domEvent(pane.draggableElement, 'dragstart')(this.onDragStart, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'dragenter')(this.onDragEnter, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'dragleave')(this.onDragLeave, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'dragend')(this.onDragEnd, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'drop')(this.onDrop, this));
|
||||
this._register(addDisposableListener(pane.draggableElement, 'dragstart', e => this.onDragStart(e)));
|
||||
this._register(addDisposableListener(pane.dropTargetElement, 'dragenter', e => this.onDragEnter(e)));
|
||||
this._register(addDisposableListener(pane.dropTargetElement, 'dragleave', e => this.onDragLeave(e)));
|
||||
this._register(addDisposableListener(pane.dropTargetElement, 'dragend', e => this.onDragEnd(e)));
|
||||
this._register(addDisposableListener(pane.dropTargetElement, 'drop', e => this.onDrop(e)));
|
||||
}
|
||||
|
||||
private onDragStart(e: DragEvent): void {
|
||||
|
||||
@@ -11,8 +11,7 @@ import { clamp } from 'vs/base/common/numbers';
|
||||
import { range, pushToStart, pushToEnd } from 'vs/base/common/arrays';
|
||||
import { Sash, Orientation, ISashEvent as IBaseSashEvent, SashState } from 'vs/base/browser/ui/sash/sash';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { $, append, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { $, addDisposableListener, append, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
|
||||
import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { Scrollable, ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
|
||||
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
@@ -488,8 +487,8 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
|
||||
// This way, we can press Alt while we resize a sash, macOS style!
|
||||
const disposable = combinedDisposable(
|
||||
domEvent(document.body, 'keydown')(e => resetSashDragState(this.sashDragState!.current, e.altKey)),
|
||||
domEvent(document.body, 'keyup')(() => resetSashDragState(this.sashDragState!.current, false))
|
||||
addDisposableListener(document.body, 'keydown', e => resetSashDragState(this.sashDragState!.current, e.altKey)),
|
||||
addDisposableListener(document.body, 'keyup', () => resetSashDragState(this.sashDragState!.current, false))
|
||||
);
|
||||
|
||||
const resetSashDragState = (start: number, alt: boolean) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'vs/css!./media/tree';
|
||||
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate, isInputElement, isMonacoEditor } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { append, $, getDomNodePagePosition, hasParentWithClass, createStyleSheet, clearNode } from 'vs/base/browser/dom';
|
||||
import { append, $, getDomNodePagePosition, hasParentWithClass, createStyleSheet, clearNode, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
@@ -16,7 +16,7 @@ import { ISpliceable } from 'vs/base/common/sequence';
|
||||
import { IDragAndDropData, StaticDND, DragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { range, equals, distinctES6, firstOrDefault } from 'vs/base/common/arrays';
|
||||
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';
|
||||
import { getVisibleState, isFilterResult } from 'vs/base/browser/ui/tree/indexTreeModel';
|
||||
import { localize } from 'vs/nls';
|
||||
@@ -648,7 +648,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
) {
|
||||
this.domNode = $(`.monaco-list-type-filter.${this.positionClassName}`);
|
||||
this.domNode.draggable = true;
|
||||
domEvent(this.domNode, 'dragstart')(this.onDragStart, this, this.disposables);
|
||||
this.disposables.add(addDisposableListener(this.domNode, 'dragstart', () => this.onDragStart()));
|
||||
|
||||
this.messageDomNode = append(view.getHTMLElement(), $(`.monaco-list-type-filter-message`));
|
||||
|
||||
@@ -661,7 +661,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
this.filterOnTypeDomNode.checked = this._filterOnType;
|
||||
this.filterOnTypeDomNode.tabIndex = -1;
|
||||
this.updateFilterOnTypeTitleAndIcon();
|
||||
domEvent(this.filterOnTypeDomNode, 'input')(this.onDidChangeFilterOnType, this, this.disposables);
|
||||
this.disposables.add(addDisposableListener(this.filterOnTypeDomNode, 'input', () => this.onDidChangeFilterOnType()));
|
||||
|
||||
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear' + treeFilterClearIcon.cssSelector));
|
||||
this.clearDomNode.tabIndex = -1;
|
||||
@@ -711,7 +711,8 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const onKeyDown = Event.chain(domEvent(this.view.getHTMLElement(), 'keydown'))
|
||||
const onRawKeyDown = this.enabledDisposables.add(new DomEmitter(this.view.getHTMLElement(), 'keydown'));
|
||||
const onKeyDown = Event.chain(onRawKeyDown.event)
|
||||
.filter(e => !isInputElement(e.target as HTMLElement) || e.target === this.filterOnTypeDomNode)
|
||||
.filter(e => e.key !== 'Dead' && !/^Media/.test(e.key))
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
@@ -721,9 +722,9 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
.forEach(e => { e.stopPropagation(); e.preventDefault(); })
|
||||
.event;
|
||||
|
||||
const onClear = domEvent(this.clearDomNode, 'click');
|
||||
const onClearClick = this.enabledDisposables.add(new DomEmitter(this.clearDomNode, 'click'));
|
||||
|
||||
Event.chain(Event.any<MouseEvent | StandardKeyboardEvent>(onKeyDown, onClear))
|
||||
Event.chain(Event.any<MouseEvent | StandardKeyboardEvent>(onKeyDown, onClearClick.event))
|
||||
.event(this.onEventOrInput, this, this.enabledDisposables);
|
||||
|
||||
this.filter.pattern = '';
|
||||
@@ -849,8 +850,8 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
this.domNode.classList.add('dragging');
|
||||
disposables.add(toDisposable(() => this.domNode.classList.remove('dragging')));
|
||||
|
||||
domEvent(document, 'dragover')(onDragOver, null, disposables);
|
||||
domEvent(this.domNode, 'dragend')(onDragEnd, null, disposables);
|
||||
disposables.add(addDisposableListener(document, 'dragover', e => onDragOver(e)));
|
||||
disposables.add(addDisposableListener(this.domNode, 'dragend', () => onDragEnd()));
|
||||
|
||||
StaticDND.CurrentDragAndDropData = new DragAndDropData('vscode-ui');
|
||||
disposables.add(toDisposable(() => StaticDND.CurrentDragAndDropData = undefined));
|
||||
|
||||
@@ -298,7 +298,7 @@ export class Delayer<T> implements IDisposable {
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.cancelTimeout();
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,12 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { DataUri } from 'vs/base/common/resources';
|
||||
|
||||
export const MIME_TEXT = 'text/plain';
|
||||
export const MIME_BINARY = 'application/octet-stream';
|
||||
export const MIME_UNKNOWN = 'application/unknown';
|
||||
export namespace Mimes {
|
||||
export const text = 'text/plain';
|
||||
export const binary = 'application/octet-stream';
|
||||
export const unknown = 'application/unknown';
|
||||
export const markdown = 'text/markdown';
|
||||
}
|
||||
|
||||
export interface ITextMimeAssociation {
|
||||
readonly id: string;
|
||||
@@ -125,7 +128,7 @@ export function guessMimeTypes(resource: URI | null, firstLine?: string): string
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
return [MIME_UNKNOWN];
|
||||
return [Mimes.unknown];
|
||||
}
|
||||
|
||||
path = path.toLowerCase();
|
||||
@@ -135,24 +138,24 @@ export function guessMimeTypes(resource: URI | null, firstLine?: string): string
|
||||
// 1.) User configured mappings have highest priority
|
||||
const configuredMime = guessMimeTypeByPath(path, filename, userRegisteredAssociations);
|
||||
if (configuredMime) {
|
||||
return [configuredMime, MIME_TEXT];
|
||||
return [configuredMime, Mimes.text];
|
||||
}
|
||||
|
||||
// 2.) Registered mappings have middle priority
|
||||
const registeredMime = guessMimeTypeByPath(path, filename, nonUserRegisteredAssociations);
|
||||
if (registeredMime) {
|
||||
return [registeredMime, MIME_TEXT];
|
||||
return [registeredMime, Mimes.text];
|
||||
}
|
||||
|
||||
// 3.) Firstline has lowest priority
|
||||
if (firstLine) {
|
||||
const firstlineMime = guessMimeTypeByFirstline(firstLine);
|
||||
if (firstlineMime) {
|
||||
return [firstlineMime, MIME_TEXT];
|
||||
return [firstlineMime, Mimes.text];
|
||||
}
|
||||
}
|
||||
|
||||
return [MIME_UNKNOWN];
|
||||
return [Mimes.unknown];
|
||||
}
|
||||
|
||||
function guessMimeTypeByPath(path: string, filename: string, associations: ITextMimeAssociationItem[]): string | null {
|
||||
@@ -240,7 +243,7 @@ export function isUnspecific(mime: string[] | string): boolean {
|
||||
}
|
||||
|
||||
if (typeof mime === 'string') {
|
||||
return mime === MIME_BINARY || mime === MIME_TEXT || mime === MIME_UNKNOWN;
|
||||
return mime === Mimes.binary || mime === Mimes.text || mime === Mimes.unknown;
|
||||
}
|
||||
|
||||
return mime.length === 1 && isUnspecific(mime[0]);
|
||||
|
||||
@@ -10,9 +10,54 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as process from 'vs/base/common/process';
|
||||
|
||||
export const enum SocketCloseEventType {
|
||||
NodeSocketCloseEvent = 0,
|
||||
WebSocketCloseEvent = 1
|
||||
}
|
||||
|
||||
export interface NodeSocketCloseEvent {
|
||||
/**
|
||||
* The type of the event
|
||||
*/
|
||||
readonly type: SocketCloseEventType.NodeSocketCloseEvent;
|
||||
/**
|
||||
* `true` if the socket had a transmission error.
|
||||
*/
|
||||
readonly hadError: boolean;
|
||||
/**
|
||||
* Underlying error.
|
||||
*/
|
||||
readonly error: Error | undefined
|
||||
}
|
||||
|
||||
export interface WebSocketCloseEvent {
|
||||
/**
|
||||
* The type of the event
|
||||
*/
|
||||
readonly type: SocketCloseEventType.WebSocketCloseEvent;
|
||||
/**
|
||||
* Returns the WebSocket connection close code provided by the server.
|
||||
*/
|
||||
readonly code: number;
|
||||
/**
|
||||
* Returns the WebSocket connection close reason provided by the server.
|
||||
*/
|
||||
readonly reason: string;
|
||||
/**
|
||||
* Returns true if the connection closed cleanly; false otherwise.
|
||||
*/
|
||||
readonly wasClean: boolean;
|
||||
/**
|
||||
* Underlying event.
|
||||
*/
|
||||
readonly event: any | undefined;
|
||||
}
|
||||
|
||||
export type SocketCloseEvent = NodeSocketCloseEvent | WebSocketCloseEvent | undefined;
|
||||
|
||||
export interface ISocket extends IDisposable {
|
||||
onData(listener: (e: VSBuffer) => void): IDisposable;
|
||||
onClose(listener: () => void): IDisposable;
|
||||
onClose(listener: (e: SocketCloseEvent) => void): IDisposable;
|
||||
onEnd(listener: () => void): IDisposable;
|
||||
write(buffer: VSBuffer): void;
|
||||
end(): void;
|
||||
@@ -624,8 +669,8 @@ export class PersistentProtocol implements IMessagePassingProtocol {
|
||||
private readonly _onDidDispose = new BufferedEmitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
|
||||
private readonly _onSocketClose = new BufferedEmitter<void>();
|
||||
readonly onSocketClose: Event<void> = this._onSocketClose.event;
|
||||
private readonly _onSocketClose = new BufferedEmitter<SocketCloseEvent>();
|
||||
readonly onSocketClose: Event<SocketCloseEvent> = this._onSocketClose.event;
|
||||
|
||||
private readonly _onSocketTimeout = new BufferedEmitter<void>();
|
||||
readonly onSocketTimeout: Event<void> = this._onSocketTimeout.event;
|
||||
@@ -658,7 +703,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
|
||||
this._socketReader = new ProtocolReader(this._socket);
|
||||
this._socketDisposables.push(this._socketReader);
|
||||
this._socketDisposables.push(this._socketReader.onMessage(msg => this._receiveMessage(msg)));
|
||||
this._socketDisposables.push(this._socket.onClose(() => this._onSocketClose.fire()));
|
||||
this._socketDisposables.push(this._socket.onClose((e) => this._onSocketClose.fire(e)));
|
||||
if (initialChunk) {
|
||||
this._socketReader.acceptChunk(initialChunk);
|
||||
}
|
||||
@@ -768,7 +813,7 @@ export class PersistentProtocol implements IMessagePassingProtocol {
|
||||
this._socketReader = new ProtocolReader(this._socket);
|
||||
this._socketDisposables.push(this._socketReader);
|
||||
this._socketDisposables.push(this._socketReader.onMessage(msg => this._receiveMessage(msg)));
|
||||
this._socketDisposables.push(this._socket.onClose(() => this._onSocketClose.fire()));
|
||||
this._socketDisposables.push(this._socket.onClose((e) => this._onSocketClose.fire(e)));
|
||||
this._socketReader.acceptChunk(initialDataChunk);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { tmpdir } from 'os';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { ISocket, Protocol, Client, ChunkStream } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { ISocket, Protocol, Client, ChunkStream, SocketCloseEvent, SocketCloseEventType } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Platform, platform } from 'vs/base/common/platform';
|
||||
|
||||
@@ -54,10 +54,17 @@ export class NodeSocket implements ISocket {
|
||||
};
|
||||
}
|
||||
|
||||
public onClose(listener: () => void): IDisposable {
|
||||
this.socket.on('close', listener);
|
||||
public onClose(listener: (e: SocketCloseEvent) => void): IDisposable {
|
||||
const adapter = (hadError: boolean) => {
|
||||
listener({
|
||||
type: SocketCloseEventType.NodeSocketCloseEvent,
|
||||
hadError: hadError,
|
||||
error: undefined
|
||||
});
|
||||
};
|
||||
this.socket.on('close', adapter);
|
||||
return {
|
||||
dispose: () => this.socket.off('close', listener)
|
||||
dispose: () => this.socket.off('close', adapter)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -167,7 +174,7 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
|
||||
private readonly _pendingDeflateData: Buffer[] = [];
|
||||
private readonly _incomingData: ChunkStream;
|
||||
private readonly _onData = this._register(new Emitter<VSBuffer>());
|
||||
private readonly _onClose = this._register(new Emitter<void>());
|
||||
private readonly _onClose = this._register(new Emitter<SocketCloseEvent>());
|
||||
private _isEnded: boolean = false;
|
||||
|
||||
private readonly _state = {
|
||||
@@ -232,7 +239,11 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
|
||||
// zlib errors are fatal, since we have no idea how to recover
|
||||
console.error(err);
|
||||
onUnexpectedError(err);
|
||||
this._onClose.fire();
|
||||
this._onClose.fire({
|
||||
type: SocketCloseEventType.NodeSocketCloseEvent,
|
||||
hadError: true,
|
||||
error: err
|
||||
});
|
||||
});
|
||||
this._zlibInflate.on('data', (data: Buffer) => {
|
||||
this._pendingInflateData.push(data);
|
||||
@@ -251,7 +262,11 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
|
||||
// zlib errors are fatal, since we have no idea how to recover
|
||||
console.error(err);
|
||||
onUnexpectedError(err);
|
||||
this._onClose.fire();
|
||||
this._onClose.fire({
|
||||
type: SocketCloseEventType.NodeSocketCloseEvent,
|
||||
hadError: true,
|
||||
error: err
|
||||
});
|
||||
});
|
||||
this._zlibDeflate.on('data', (data: Buffer) => {
|
||||
this._pendingDeflateData.push(data);
|
||||
@@ -263,7 +278,7 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
|
||||
this._zlibDeflateFlushWaitingCount = 0;
|
||||
this._incomingData = new ChunkStream();
|
||||
this._register(this.socket.onData(data => this._acceptChunk(data)));
|
||||
this._register(this.socket.onClose(() => this._onClose.fire()));
|
||||
this._register(this.socket.onClose((e) => this._onClose.fire(e)));
|
||||
}
|
||||
|
||||
public override dispose(): void {
|
||||
@@ -282,7 +297,7 @@ export class WebSocketNodeSocket extends Disposable implements ISocket {
|
||||
return this._onData.event(listener);
|
||||
}
|
||||
|
||||
public onClose(listener: () => void): IDisposable {
|
||||
public onClose(listener: (e: SocketCloseEvent) => void): IDisposable {
|
||||
return this._onClose.event(listener);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { ITextAreaWrapper, ITypeData, TextAreaState, _debugComposition } from 'vs/editor/browser/controller/textAreaState';
|
||||
@@ -653,7 +654,7 @@ class ClipboardEventUtils {
|
||||
if (e.clipboardData) {
|
||||
e.preventDefault();
|
||||
|
||||
const text = e.clipboardData.getData('text/plain');
|
||||
const text = e.clipboardData.getData(Mimes.text);
|
||||
let metadata: ClipboardStoredMetadata | null = null;
|
||||
const rawmetadata = e.clipboardData.getData('vscode-editor-data');
|
||||
if (typeof rawmetadata === 'string') {
|
||||
@@ -681,7 +682,7 @@ class ClipboardEventUtils {
|
||||
|
||||
public static setTextData(e: ClipboardEvent, text: string, html: string | null | undefined, metadata: ClipboardStoredMetadata): void {
|
||||
if (e.clipboardData) {
|
||||
e.clipboardData.setData('text/plain', text);
|
||||
e.clipboardData.setData(Mimes.text, text);
|
||||
if (typeof html === 'string') {
|
||||
e.clipboardData.setData('text/html', html);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageCo
|
||||
import { ILanguageExtensionPoint } from 'vs/editor/common/services/modeService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
// Define extension point ids
|
||||
export const Extensions = {
|
||||
@@ -65,7 +66,7 @@ ModesRegistry.registerLanguage({
|
||||
id: PLAINTEXT_MODE_ID,
|
||||
extensions: [PLAINTEXT_EXTENSION],
|
||||
aliases: [nls.localize('plainText.alias', "Plain Text"), 'text'],
|
||||
mimetypes: ['text/plain']
|
||||
mimetypes: [Mimes.text]
|
||||
});
|
||||
LanguageConfigurationRegistry.register(PLAINTEXT_LANGUAGE_IDENTIFIER, {
|
||||
brackets: [
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { domEvent, stop } from 'vs/base/browser/event';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
@@ -90,11 +89,15 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget {
|
||||
const overloads = dom.append(controls, $('.overloads'));
|
||||
const next = dom.append(controls, $('.button' + ThemeIcon.asCSSSelector(parameterHintsNextIcon)));
|
||||
|
||||
const onPreviousClick = stop(domEvent(previous, 'click'));
|
||||
this._register(onPreviousClick(this.previous, this));
|
||||
this._register(dom.addDisposableListener(previous, 'click', e => {
|
||||
dom.EventHelper.stop(e);
|
||||
this.previous();
|
||||
}));
|
||||
|
||||
const onNextClick = stop(domEvent(next, 'click'));
|
||||
this._register(onNextClick(this.next, this));
|
||||
this._register(dom.addDisposableListener(next, 'click', e => {
|
||||
dom.EventHelper.stop(e);
|
||||
this.next();
|
||||
}));
|
||||
|
||||
const body = $('.body');
|
||||
const scrollbar = new DomScrollableElement(body, {});
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/* See https://github.com/microsoft/monaco-editor/issues/2168#issuecomment-780078600 */
|
||||
.monaco-aria-container {
|
||||
position: absolute !important;
|
||||
top: 0; /* avoid being placed underneath a sibling element */
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
margin: -1px;
|
||||
|
||||
@@ -35,6 +35,7 @@ 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';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
/**
|
||||
* Description of an action contribution
|
||||
@@ -425,7 +426,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
|
||||
|
||||
let model: ITextModel | null;
|
||||
if (typeof _model === 'undefined') {
|
||||
model = createTextModel(modelService, modeService, options.value || '', options.language || 'text/plain', undefined);
|
||||
model = createTextModel(modelService, modeService, options.value || '', options.language || Mimes.text, undefined);
|
||||
this._ownsModel = true;
|
||||
} else {
|
||||
model = _model;
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./menuEntryActionViewItem';
|
||||
import { asCSSUrl, ModifierKeyEmitter } from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { addDisposableListener, asCSSUrl, ModifierKeyEmitter } from 'vs/base/browser/dom';
|
||||
import { IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { IDisposable, toDisposable, MutableDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
@@ -177,12 +176,12 @@ export class MenuEntryActionViewItem extends ActionViewItem {
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(domEvent(container, 'mouseleave')(_ => {
|
||||
this._register(addDisposableListener(container, 'mouseleave', _ => {
|
||||
mouseOver = false;
|
||||
updateAltState();
|
||||
}));
|
||||
|
||||
this._register(domEvent(container, 'mouseenter')(e => {
|
||||
this._register(addDisposableListener(container, 'mouseenter', _ => {
|
||||
mouseOver = true;
|
||||
updateAltState();
|
||||
}));
|
||||
|
||||
@@ -14,9 +14,8 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
|
||||
import { EventType, $, isHTMLElement } from 'vs/base/browser/dom';
|
||||
import { EventType, $, isHTMLElement, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { attachMenuStyler } from 'vs/platform/theme/common/styler';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
|
||||
@@ -75,7 +74,9 @@ export class ContextMenuHandler {
|
||||
this.block.style.width = '100%';
|
||||
this.block.style.height = '100%';
|
||||
this.block.style.zIndex = '-1';
|
||||
domEvent(this.block, EventType.MOUSE_DOWN)((e: MouseEvent) => e.stopPropagation());
|
||||
|
||||
// TODO@Steven: this is never getting disposed
|
||||
addDisposableListener(this.block, EventType.MOUSE_DOWN, e => e.stopPropagation());
|
||||
}
|
||||
|
||||
const menuDisposables = new DisposableStore();
|
||||
@@ -94,8 +95,8 @@ export class ContextMenuHandler {
|
||||
|
||||
menu.onDidCancel(() => this.contextViewService.hideContextView(true), null, menuDisposables);
|
||||
menu.onDidBlur(() => this.contextViewService.hideContextView(true), null, menuDisposables);
|
||||
domEvent(window, EventType.BLUR)(() => { this.contextViewService.hideContextView(true); }, null, menuDisposables);
|
||||
domEvent(window, EventType.MOUSE_DOWN)((e: MouseEvent) => {
|
||||
menuDisposables.add(addDisposableListener(window, EventType.BLUR, () => this.contextViewService.hideContextView(true)));
|
||||
menuDisposables.add(addDisposableListener(window, EventType.MOUSE_DOWN, (e: MouseEvent) => {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +118,7 @@ export class ContextMenuHandler {
|
||||
}
|
||||
|
||||
this.contextViewService.hideContextView(true);
|
||||
}, null, menuDisposables);
|
||||
}));
|
||||
|
||||
return combinedDisposable(menuDisposables, menu);
|
||||
},
|
||||
|
||||
@@ -60,6 +60,7 @@ export interface NativeParsedArgs {
|
||||
'enable-proposed-api'?: string[]; // undefined or array of 1 or more
|
||||
'open-url'?: boolean;
|
||||
'skip-release-notes'?: boolean;
|
||||
'skip-welcome'?: boolean;
|
||||
'disable-telemetry'?: boolean;
|
||||
'export-default-configuration'?: string;
|
||||
'install-source'?: string;
|
||||
|
||||
@@ -94,6 +94,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
|
||||
'driver': { type: 'string' },
|
||||
'logExtensionHostCommunication': { type: 'boolean' },
|
||||
'skip-release-notes': { type: 'boolean' },
|
||||
'skip-welcome': { type: 'boolean' },
|
||||
'disable-telemetry': { type: 'boolean' },
|
||||
'disable-updates': { type: 'boolean' },
|
||||
'disable-keytar': { type: 'boolean' },
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { $, EventHelper, EventLike } from 'vs/base/browser/dom';
|
||||
import { DomEmitter, domEvent } from 'vs/base/browser/event';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -67,7 +67,8 @@ export class Link extends Disposable {
|
||||
}, link.label);
|
||||
|
||||
const onClickEmitter = this._register(new DomEmitter(this.el, 'click'));
|
||||
const onEnterPress = Event.chain(domEvent(this.el, 'keypress'))
|
||||
const onKeyPress = this._register(new DomEmitter(this.el, 'keypress'));
|
||||
const onEnterPress = Event.chain(onKeyPress.event)
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.filter(e => e.keyCode === KeyCode.Enter)
|
||||
.event;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ISocketFactory, IConnectCallback } from 'vs/platform/remote/common/remoteAgentConnection';
|
||||
import { ISocket } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { ISocket, SocketCloseEvent, SocketCloseEventType } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
@@ -16,10 +16,29 @@ export interface IWebSocketFactory {
|
||||
create(url: string): IWebSocket;
|
||||
}
|
||||
|
||||
export interface IWebSocketCloseEvent {
|
||||
/**
|
||||
* Returns the WebSocket connection close code provided by the server.
|
||||
*/
|
||||
readonly code: number;
|
||||
/**
|
||||
* Returns the WebSocket connection close reason provided by the server.
|
||||
*/
|
||||
readonly reason: string;
|
||||
/**
|
||||
* Returns true if the connection closed cleanly; false otherwise.
|
||||
*/
|
||||
readonly wasClean: boolean;
|
||||
/**
|
||||
* Underlying event.
|
||||
*/
|
||||
readonly event: any | undefined;
|
||||
}
|
||||
|
||||
export interface IWebSocket {
|
||||
readonly onData: Event<ArrayBuffer>;
|
||||
readonly onOpen: Event<void>;
|
||||
readonly onClose: Event<void>;
|
||||
readonly onClose: Event<IWebSocketCloseEvent | void>;
|
||||
readonly onError: Event<any>;
|
||||
|
||||
send(data: ArrayBuffer | ArrayBufferView): void;
|
||||
@@ -33,7 +52,7 @@ class BrowserWebSocket extends Disposable implements IWebSocket {
|
||||
|
||||
public readonly onOpen: Event<void>;
|
||||
|
||||
private readonly _onClose = this._register(new Emitter<void>());
|
||||
private readonly _onClose = this._register(new Emitter<IWebSocketCloseEvent>());
|
||||
public readonly onClose = this._onClose.event;
|
||||
|
||||
private readonly _onError = this._register(new Emitter<any>());
|
||||
@@ -135,7 +154,7 @@ class BrowserWebSocket extends Disposable implements IWebSocket {
|
||||
}
|
||||
}
|
||||
|
||||
this._onClose.fire();
|
||||
this._onClose.fire({ code: e.code, reason: e.reason, wasClean: e.wasClean, event: e });
|
||||
}));
|
||||
|
||||
this._register(dom.addDisposableListener(this._socket, 'error', sendErrorSoon));
|
||||
@@ -178,8 +197,21 @@ class BrowserSocket implements ISocket {
|
||||
return this.socket.onData((data) => listener(VSBuffer.wrap(new Uint8Array(data))));
|
||||
}
|
||||
|
||||
public onClose(listener: () => void): IDisposable {
|
||||
return this.socket.onClose(listener);
|
||||
public onClose(listener: (e: SocketCloseEvent) => void): IDisposable {
|
||||
const adapter = (e: IWebSocketCloseEvent | void) => {
|
||||
if (typeof e === 'undefined') {
|
||||
listener(e);
|
||||
} else {
|
||||
listener({
|
||||
type: SocketCloseEventType.WebSocketCloseEvent,
|
||||
code: e.code,
|
||||
reason: e.reason,
|
||||
wasClean: e.wasClean,
|
||||
event: e.event
|
||||
});
|
||||
}
|
||||
};
|
||||
return this.socket.onClose(adapter);
|
||||
}
|
||||
|
||||
public onEnd(listener: () => void): IDisposable {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Client, PersistentProtocol, ISocket, ProtocolConstants } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { Client, PersistentProtocol, ISocket, ProtocolConstants, SocketCloseEventType } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { RemoteAgentConnectionContext } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
@@ -532,8 +532,28 @@ abstract class PersistentConnection extends Disposable {
|
||||
|
||||
this._onDidStateChange.fire(new ConnectionGainEvent(this.reconnectionToken, 0, 0));
|
||||
|
||||
this._register(protocol.onSocketClose(() => this._beginReconnecting()));
|
||||
this._register(protocol.onSocketTimeout(() => this._beginReconnecting()));
|
||||
this._register(protocol.onSocketClose((e) => {
|
||||
const logPrefix = commonLogPrefix(this._connectionType, this.reconnectionToken, true);
|
||||
if (!e) {
|
||||
this._options.logService.info(`${logPrefix} received socket close event.`);
|
||||
} else if (e.type === SocketCloseEventType.NodeSocketCloseEvent) {
|
||||
this._options.logService.info(`${logPrefix} received socket close event (hadError: ${e.hadError}).`);
|
||||
if (e.error) {
|
||||
this._options.logService.error(e.error);
|
||||
}
|
||||
} else {
|
||||
this._options.logService.info(`${logPrefix} received socket close event (wasClean: ${e.wasClean}, code: ${e.code}, reason: ${e.reason}).`);
|
||||
if (e.event) {
|
||||
this._options.logService.error(e.event);
|
||||
}
|
||||
}
|
||||
this._beginReconnecting();
|
||||
}));
|
||||
this._register(protocol.onSocketTimeout(() => {
|
||||
const logPrefix = commonLogPrefix(this._connectionType, this.reconnectionToken, true);
|
||||
this._options.logService.trace(`${logPrefix} received socket timeout event.`);
|
||||
this._beginReconnecting();
|
||||
}));
|
||||
|
||||
PersistentConnection._instances.push(this);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import { createCancelablePromise, timeout, CancelablePromise } from 'vs/base/com
|
||||
import { isString, isObject, isArray } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getErrorMessage, isPromiseCanceledError } from 'vs/base/common/errors';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
const SYNC_PREVIOUS_STORE = 'sync.previous.store';
|
||||
const DONOT_MAKE_REQUESTS_UNTIL_KEY = 'sync.donot-make-requests-until';
|
||||
@@ -304,7 +305,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync
|
||||
|
||||
const url = joinPath(this.userDataSyncStoreUrl, 'resource', resource).toString();
|
||||
headers = { ...headers };
|
||||
headers['Content-Type'] = 'text/plain';
|
||||
headers['Content-Type'] = Mimes.text;
|
||||
if (ref) {
|
||||
headers['If-Match'] = ref;
|
||||
}
|
||||
@@ -356,7 +357,7 @@ export class UserDataSyncStoreClient extends Disposable implements IUserDataSync
|
||||
}
|
||||
|
||||
const url = joinPath(this.userDataSyncStoreUrl, 'resource').toString();
|
||||
const headers: IHeaders = { 'Content-Type': 'text/plain' };
|
||||
const headers: IHeaders = { 'Content-Type': Mimes.text };
|
||||
|
||||
await this.request(url, { type: 'DELETE', headers }, [], CancellationToken.None);
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getMediaMime, MIME_UNKNOWN } from 'vs/base/common/mime';
|
||||
import { getMediaMime, Mimes } from 'vs/base/common/mime';
|
||||
import { extname } from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
const webviewMimeTypes = new Map([
|
||||
['.svg', 'image/svg+xml'],
|
||||
['.txt', 'text/plain'],
|
||||
['.txt', Mimes.text],
|
||||
['.css', 'text/css'],
|
||||
['.js', 'application/javascript'],
|
||||
['.json', 'application/json'],
|
||||
@@ -18,9 +18,10 @@ const webviewMimeTypes = new Map([
|
||||
['.xhtml', 'application/xhtml+xml'],
|
||||
['.oft', 'font/otf'],
|
||||
['.xml', 'application/xml'],
|
||||
['.wasm', 'application/wasm'],
|
||||
]);
|
||||
|
||||
export function getWebviewContentMimeType(resource: URI): string {
|
||||
const ext = extname(resource.fsPath).toLowerCase();
|
||||
return webviewMimeTypes.get(ext) || getMediaMime(resource.fsPath) || MIME_UNKNOWN;
|
||||
return webviewMimeTypes.get(ext) || getMediaMime(resource.fsPath) || Mimes.unknown;
|
||||
}
|
||||
|
||||
Vendored
+28
-10
@@ -9489,6 +9489,24 @@ declare module 'vscode' {
|
||||
*/
|
||||
onDidClose?: Event<void | number>;
|
||||
|
||||
/**
|
||||
* An event that when fired allows changing the name of the terminal.
|
||||
*
|
||||
* **Example:** Change the terminal name to "My new terminal".
|
||||
* ```typescript
|
||||
* const writeEmitter = new vscode.EventEmitter<string>();
|
||||
* const changeNameEmitter = new vscode.EventEmitter<string>();
|
||||
* const pty: vscode.Pseudoterminal = {
|
||||
* onDidWrite: writeEmitter.event,
|
||||
* onDidChangeName: changeNameEmitter.event,
|
||||
* open: () => changeNameEmitter.fire('My new terminal'),
|
||||
* close: () => {}
|
||||
* };
|
||||
* vscode.window.createTerminal({ name: 'My terminal', pty });
|
||||
* ```
|
||||
*/
|
||||
onDidChangeName?: Event<string>;
|
||||
|
||||
/**
|
||||
* Implement to handle when the pty is open and ready to start firing events.
|
||||
*
|
||||
@@ -9884,7 +9902,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* An event signaling when the active items have changed.
|
||||
*/
|
||||
readonly onDidChangeActive: Event<T[]>;
|
||||
readonly onDidChangeActive: Event<readonly T[]>;
|
||||
|
||||
/**
|
||||
* Selected items. This can be read and updated by the extension.
|
||||
@@ -9894,7 +9912,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* An event signaling when the selected items have changed.
|
||||
*/
|
||||
readonly onDidChangeSelection: Event<T[]>;
|
||||
readonly onDidChangeSelection: Event<readonly T[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -11409,7 +11427,7 @@ declare module 'vscode' {
|
||||
readonly outputs: readonly NotebookCellOutput[];
|
||||
|
||||
/**
|
||||
* The most recent {@link NotebookCellExecutionSummary excution summary} for this cell.
|
||||
* The most recent {@link NotebookCellExecutionSummary execution summary} for this cell.
|
||||
*/
|
||||
readonly executionSummary?: NotebookCellExecutionSummary;
|
||||
}
|
||||
@@ -11477,7 +11495,7 @@ declare module 'vscode' {
|
||||
|
||||
/**
|
||||
* Get the cells of this notebook. A subset can be retrieved by providing
|
||||
* a range. The range will be adjuset to the notebook.
|
||||
* a range. The range will be adjusted to the notebook.
|
||||
*
|
||||
* @param range A notebook range.
|
||||
* @returns The cells contained by the range or all cells.
|
||||
@@ -11515,7 +11533,7 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
/**
|
||||
* A notebook range represents an ordered pair of two cell indicies.
|
||||
* A notebook range represents an ordered pair of two cell indices.
|
||||
* It is guaranteed that start is less than or equal to end.
|
||||
*/
|
||||
export class NotebookRange {
|
||||
@@ -11626,7 +11644,7 @@ declare module 'vscode' {
|
||||
data: Uint8Array;
|
||||
|
||||
/**
|
||||
* Create a new notbook cell output item.
|
||||
* Create a new notebook cell output item.
|
||||
*
|
||||
* @param data The value of the output item.
|
||||
* @param mime The mime type of the output item.
|
||||
@@ -12122,7 +12140,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Namespace for notebooks.
|
||||
*
|
||||
* The notebooks functionality is composed of three loosly coupled components:
|
||||
* The notebooks functionality is composed of three loosely coupled components:
|
||||
*
|
||||
* 1. {@link NotebookSerializer} enable the editor to open, show, and save notebooks
|
||||
* 2. {@link NotebookController} own the execution of notebooks, e.g they create output from code cells.
|
||||
@@ -13512,17 +13530,17 @@ declare module 'vscode' {
|
||||
*/
|
||||
export interface AuthenticationProviderAuthenticationSessionsChangeEvent {
|
||||
/**
|
||||
* The {@link AuthenticationSession}s of the {@link AuthentiationProvider AuthenticationProvider} that have been added.
|
||||
* The {@link AuthenticationSession}s of the {@link AuthenticationProvider} that have been added.
|
||||
*/
|
||||
readonly added?: readonly AuthenticationSession[];
|
||||
|
||||
/**
|
||||
* The {@link AuthenticationSession}s of the {@link AuthentiationProvider AuthenticationProvider} that have been removed.
|
||||
* The {@link AuthenticationSession}s of the {@link AuthenticationProvider} that have been removed.
|
||||
*/
|
||||
readonly removed?: readonly AuthenticationSession[];
|
||||
|
||||
/**
|
||||
* The {@link AuthenticationSession}s of the {@link AuthentiationProvider AuthenticationProvider} that have been changed.
|
||||
* The {@link AuthenticationSession}s of the {@link AuthenticationProvider} that have been changed.
|
||||
* A session changes when its data excluding the id are updated. An example of this is a session refresh that results in a new
|
||||
* access token being set for the session.
|
||||
*/
|
||||
|
||||
Vendored
-24
@@ -874,30 +874,6 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Terminal name change event https://github.com/microsoft/vscode/issues/114898
|
||||
|
||||
export interface Pseudoterminal {
|
||||
/**
|
||||
* An event that when fired allows changing the name of the terminal.
|
||||
*
|
||||
* **Example:** Change the terminal name to "My new terminal".
|
||||
* ```typescript
|
||||
* const writeEmitter = new vscode.EventEmitter<string>();
|
||||
* const changeNameEmitter = new vscode.EventEmitter<string>();
|
||||
* const pty: vscode.Pseudoterminal = {
|
||||
* onDidWrite: writeEmitter.event,
|
||||
* onDidChangeName: changeNameEmitter.event,
|
||||
* open: () => changeNameEmitter.fire('My new terminal'),
|
||||
* close: () => {}
|
||||
* };
|
||||
* vscode.window.createTerminal({ name: 'My terminal', pty });
|
||||
* ```
|
||||
*/
|
||||
onDidChangeName?: Event<string>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Terminal icon https://github.com/microsoft/vscode/issues/120538
|
||||
|
||||
export interface TerminalOptions {
|
||||
|
||||
@@ -551,7 +551,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
||||
public async $extensionTestsExecute(): Promise<number> {
|
||||
await this._eagerExtensionsActivated.wait();
|
||||
try {
|
||||
return this._doHandleExtensionTests();
|
||||
return await this._doHandleExtensionTests();
|
||||
} catch (error) {
|
||||
console.error(error); // ensure any error message makes it onto the console
|
||||
throw error;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { illegalArgument } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { isMarkdownString, MarkdownString as BaseMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ReadonlyMapView, ResourceMap } from 'vs/base/common/map';
|
||||
import { normalizeMimeType } from 'vs/base/common/mime';
|
||||
import { Mimes, normalizeMimeType } from 'vs/base/common/mime';
|
||||
import { isArray, isStringArray } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
@@ -3072,7 +3072,7 @@ export class NotebookCellOutputItem {
|
||||
|
||||
static #encoder = new TextEncoder();
|
||||
|
||||
static text(value: string, mime: string = 'text/plain'): NotebookCellOutputItem {
|
||||
static text(value: string, mime: string = Mimes.text): NotebookCellOutputItem {
|
||||
const bytes = NotebookCellOutputItem.#encoder.encode(String(value));
|
||||
return new NotebookCellOutputItem(bytes, mime);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { FileAccess, Schemas } from 'vs/base/common/network';
|
||||
import { IBaseTextResourceEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { MIME_BINARY } from 'vs/base/common/mime';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -277,7 +277,7 @@ export function fillEditorsDragData(accessor: ServicesAccessor, resourcesOrEdito
|
||||
// TODO@sandbox this will no longer work when `vscode-file`
|
||||
// is enabled because we block loading resources that are not
|
||||
// inside installation dir
|
||||
event.dataTransfer.setData(DataTransfers.DOWNLOAD_URL, [MIME_BINARY, basename(firstFile.resource), FileAccess.asBrowserUri(firstFile.resource).toString()].join(':'));
|
||||
event.dataTransfer.setData(DataTransfers.DOWNLOAD_URL, [Mimes.binary, basename(firstFile.resource), FileAccess.asBrowserUri(firstFile.resource).toString()].join(':'));
|
||||
}
|
||||
|
||||
// Resource URLs: allows to drop multiple file resources to a target in VS Code
|
||||
|
||||
@@ -22,7 +22,6 @@ import { Color } from 'vs/base/common/color';
|
||||
import { IBaseActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
|
||||
@@ -395,15 +394,15 @@ export class ActivityActionViewItem extends BaseActionViewItem {
|
||||
|
||||
this.updateTitle();
|
||||
if (this.useCustomHover) {
|
||||
this.hoverDisposables.add(domEvent(this.container, EventType.MOUSE_OVER, true)(() => {
|
||||
this.hoverDisposables.add(addDisposableListener(this.container, EventType.MOUSE_OVER, () => {
|
||||
if (!this.showHoverScheduler.isScheduled()) {
|
||||
this.showHoverScheduler.schedule(this.options.hoverOptions!.delay() || 150);
|
||||
}
|
||||
}));
|
||||
this.hoverDisposables.add(domEvent(this.container, EventType.MOUSE_LEAVE, true)(() => {
|
||||
}, true));
|
||||
this.hoverDisposables.add(addDisposableListener(this.container, EventType.MOUSE_LEAVE, () => {
|
||||
this.hover.value = undefined;
|
||||
this.showHoverScheduler.cancel();
|
||||
}));
|
||||
}, true));
|
||||
this.hoverDisposables.add(toDisposable(() => {
|
||||
this.hover.value = undefined;
|
||||
this.showHoverScheduler.cancel();
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { MIME_BINARY } from 'vs/base/common/mime';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
/**
|
||||
* An editor model that just represents a resource that can be loaded.
|
||||
*/
|
||||
export class BinaryEditorModel extends EditorModel {
|
||||
|
||||
private readonly mime = MIME_BINARY;
|
||||
private readonly mime = Mimes.binary;
|
||||
|
||||
private size: number | undefined;
|
||||
private etag: string | undefined;
|
||||
|
||||
@@ -37,7 +37,6 @@ import { ITextModel } from 'vs/editor/common/model';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { ModesHoverController } from 'vs/editor/contrib/hover/hover';
|
||||
import { HoverStartMode } from 'vs/editor/contrib/hover/hoverOperation';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
@@ -47,6 +46,8 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
|
||||
import { Expression } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
|
||||
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
const LAUNCH_JSON_REGEX = /\.vscode\/launch\.json$/;
|
||||
const INLINE_VALUE_DECORATION_KEY = 'inlinevaluedecoration';
|
||||
@@ -284,7 +285,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
this.altListener.dispose();
|
||||
}
|
||||
// When the alt key is pressed show regular editor hover and hide the debug hover #84561
|
||||
this.altListener = domEvent(document, 'keydown')(keydownEvent => {
|
||||
this.altListener = addDisposableListener(document, 'keydown', keydownEvent => {
|
||||
const standardKeyboardEvent = new StandardKeyboardEvent(keydownEvent);
|
||||
if (standardKeyboardEvent.keyCode === KeyCode.Alt) {
|
||||
this.altPressed = true;
|
||||
@@ -297,7 +298,8 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
hoverController.showContentHover(this.hoverRange, HoverStartMode.Immediate, false);
|
||||
}
|
||||
|
||||
const listener = Event.any<KeyboardEvent | boolean>(this.hostService.onDidChangeFocus, domEvent(document, 'keyup'))(keyupEvent => {
|
||||
const onKeyUp = new DomEmitter(document, 'keyup');
|
||||
const listener = Event.any<KeyboardEvent | boolean>(this.hostService.onDidChangeFocus, onKeyUp.event)(keyupEvent => {
|
||||
let standardKeyboardEvent = undefined;
|
||||
if (keyupEvent instanceof KeyboardEvent) {
|
||||
standardKeyboardEvent = new StandardKeyboardEvent(keyupEvent);
|
||||
@@ -306,6 +308,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
this.altPressed = false;
|
||||
this.editor.updateOptions({ hover: { enabled: false } });
|
||||
listener.dispose();
|
||||
onKeyUp.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { URI as uri } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
import { guessMimeTypes, MIME_TEXT } from 'vs/base/common/mime';
|
||||
import { guessMimeTypes, Mimes } from 'vs/base/common/mime';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
@@ -94,7 +94,7 @@ export class DebugContentProvider implements IWorkbenchContribution, ITextModelC
|
||||
}
|
||||
const createErrModel = (errMsg?: string) => {
|
||||
this.debugService.sourceIsNotAvailable(resource);
|
||||
const languageSelection = this.modeService.create(MIME_TEXT);
|
||||
const languageSelection = this.modeService.create(Mimes.text);
|
||||
const message = errMsg
|
||||
? localize('canNotResolveSourceWithError', "Could not load source '{0}': {1}.", resource.path, errMsg)
|
||||
: localize('canNotResolveSource', "Could not load source '{0}'.", resource.path);
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IExtensionService, IExtensionsStatus, IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IListVirtualDelegate, IListRenderer } from 'vs/base/browser/ui/list/list';
|
||||
import { WorkbenchList } from 'vs/platform/list/browser/listService';
|
||||
import { append, $, reset, Dimension, clearNode } from 'vs/base/browser/dom';
|
||||
import { append, $, reset, Dimension, clearNode, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
@@ -22,7 +22,6 @@ import { EnablementState } from 'vs/workbench/services/extensionManagement/commo
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
@@ -32,7 +31,6 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput';
|
||||
@@ -267,8 +265,7 @@ export abstract class AbstractRuntimeExtensionsEditor extends EditorPane {
|
||||
|
||||
data.root.classList.toggle('odd', index % 2 === 1);
|
||||
|
||||
const onError = Event.once(domEvent(data.icon, 'error'));
|
||||
onError(() => data.icon.src = element.marketplaceInfo?.iconUrlFallback || DefaultIconPath, null, data.elementDisposables);
|
||||
data.elementDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = element.marketplaceInfo?.iconUrlFallback || DefaultIconPath, { once: true }));
|
||||
data.icon.src = element.marketplaceInfo?.iconUrl || DefaultIconPath;
|
||||
|
||||
if (!data.icon.complete) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import { Cache, CacheResult } from 'vs/base/common/cache';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { dispose, toDisposable, Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { append, $, finalHandler, join, hide, show, addDisposableListener, EventType, setParentFlowTo } from 'vs/base/browser/dom';
|
||||
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
@@ -349,8 +348,7 @@ export class ExtensionEditor extends EditorPane {
|
||||
this.extensionManifest = new Cache(() => createCancelablePromise(token => extension.getManifest(token)));
|
||||
|
||||
const remoteBadge = this.instantiationService.createInstance(RemoteBadgeWidget, template.iconContainer, true);
|
||||
const onError = Event.once(domEvent(template.icon, 'error'));
|
||||
onError(() => template.icon.src = extension.iconUrlFallback, null, this.transientDisposables);
|
||||
this.transientDisposables.add(addDisposableListener(template.icon, 'error', () => template.icon.src = extension.iconUrlFallback, { once: true }));
|
||||
template.icon.src = extension.iconUrl;
|
||||
|
||||
template.name.textContent = extension.displayName;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/extension';
|
||||
import { append, $ } from 'vs/base/browser/dom';
|
||||
import { append, $, addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
@@ -12,7 +12,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, ExtensionToolTipAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
@@ -190,8 +189,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
|
||||
updateEnablement();
|
||||
this.extensionService.onDidChangeExtensions(() => updateEnablement(), this, data.extensionDisposables);
|
||||
|
||||
const onError = Event.once(domEvent(data.icon, 'error'));
|
||||
onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables);
|
||||
data.extensionDisposables.push(addDisposableListener(data.icon, 'error', () => data.icon.src = extension.iconUrlFallback, { once: true }));
|
||||
data.icon.src = extension.iconUrl;
|
||||
|
||||
if (!data.icon.complete) {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { IDisposable, dispose, Disposable, DisposableStore, toDisposable } from
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IExtensionsWorkbenchService, IExtension } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IListService, WorkbenchAsyncDataTree } from 'vs/platform/list/browser/listService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -167,8 +166,7 @@ export class ExtensionRenderer implements IListRenderer<ITreeNode<IExtensionData
|
||||
|
||||
public renderElement(node: ITreeNode<IExtensionData>, index: number, data: IExtensionTemplateData): void {
|
||||
const extension = node.element.extension;
|
||||
const onError = Event.once(domEvent(data.icon, 'error'));
|
||||
onError(() => data.icon.src = extension.iconUrlFallback, null, data.extensionDisposables);
|
||||
data.extensionDisposables.push(dom.addDisposableListener(data.icon, 'error', () => data.icon.src = extension.iconUrlFallback, { once: true }));
|
||||
data.icon.src = extension.iconUrl;
|
||||
|
||||
if (!data.icon.complete) {
|
||||
|
||||
@@ -20,7 +20,7 @@ import { Schemas } from 'vs/base/common/network';
|
||||
import { basename, extname } from 'vs/base/common/resources';
|
||||
import { match } from 'vs/base/common/glob';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { MIME_UNKNOWN, guessMimeTypes } from 'vs/base/common/mime';
|
||||
import { Mimes, guessMimeTypes } from 'vs/base/common/mime';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
@@ -230,7 +230,7 @@ export class FileBasedRecommendations extends ExtensionRecommendations {
|
||||
}
|
||||
|
||||
const mimeTypes = guessMimeTypes(uri);
|
||||
if (mimeTypes.length !== 1 || mimeTypes[0] !== MIME_UNKNOWN) {
|
||||
if (mimeTypes.length !== 1 || mimeTypes[0] !== Mimes.unknown) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree';
|
||||
import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IEditableData } from 'vs/workbench/common/views';
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity';
|
||||
@@ -328,13 +327,13 @@ export class FilesRenderer implements ICompressibleTreeRenderer<ExplorerItem, Fu
|
||||
// accessibility
|
||||
disposables.add(this._onDidChangeActiveDescendant.add(compressedNavigationController.onDidChange));
|
||||
|
||||
domEvent(templateData.container, 'mousedown')(e => {
|
||||
disposables.add(DOM.addDisposableListener(templateData.container, 'mousedown', e => {
|
||||
const result = getIconLabelNameFromHTMLElement(e.target);
|
||||
|
||||
if (result) {
|
||||
compressedNavigationController.setIndex(result.index);
|
||||
}
|
||||
}, undefined, disposables);
|
||||
}));
|
||||
|
||||
disposables.add(toDisposable(() => this.compressedNavigationControllers.delete(stat)));
|
||||
|
||||
|
||||
@@ -48,13 +48,13 @@ import { textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { OS, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Progress } from 'vs/platform/progress/common/progress';
|
||||
import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
interface IResourceMarkersTemplateData {
|
||||
resourceLabel: IResourceLabel;
|
||||
@@ -417,10 +417,10 @@ class MarkerWidget extends Disposable {
|
||||
this._codeLink.setAttribute('href', codeLink);
|
||||
this._codeLink.tabIndex = 0;
|
||||
|
||||
const onClick = Event.chain(domEvent(this._codeLink, 'click'))
|
||||
const onClick = Event.chain(this._register(new DomEmitter(this._codeLink, 'click')).event)
|
||||
.filter(e => ((this._clickModifierKey === 'meta' && e.metaKey) || (this._clickModifierKey === 'ctrl' && e.ctrlKey) || (this._clickModifierKey === 'alt' && e.altKey)))
|
||||
.event;
|
||||
const onEnterPress = Event.chain(domEvent(this._codeLink, 'keydown'))
|
||||
const onEnterPress = Event.chain(this._register(new DomEmitter(this._codeLink, 'keydown')).event)
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.filter(e => e.keyCode === KeyCode.Enter)
|
||||
.event;
|
||||
|
||||
@@ -36,7 +36,6 @@ import { ActionBar, IActionViewItem } from 'vs/base/browser/ui/actionbar/actionb
|
||||
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { ResourceLabels } from 'vs/workbench/browser/labels';
|
||||
import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
@@ -443,7 +442,7 @@ export class MarkersView extends ViewPane implements IMarkersView {
|
||||
}));
|
||||
|
||||
// move focus to input, whenever a key is pressed in the panel container
|
||||
this._register(domEvent(parent, 'keydown')(e => {
|
||||
this._register(dom.addDisposableListener(parent, 'keydown', e => {
|
||||
if (this.keybindingService.mightProducePrintableCharacter(new StandardKeyboardEvent(e))) {
|
||||
this.focusFilter();
|
||||
}
|
||||
|
||||
@@ -263,6 +263,7 @@ export interface ICellViewModel extends IGenericCellViewModel {
|
||||
handle: number;
|
||||
uri: URI;
|
||||
language: string;
|
||||
readonly mime: string;
|
||||
cellKind: CellKind;
|
||||
lineNumbers: 'on' | 'off' | 'inherit';
|
||||
focusMode: CellFocusMode;
|
||||
|
||||
@@ -72,6 +72,7 @@ import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOp
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
import { NotebookEditorToolbar } from 'vs/workbench/contrib/notebook/browser/notebookEditorToolbar';
|
||||
import { INotebookRendererMessagingService } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService';
|
||||
import { IMarkupCellInitialization } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -1385,18 +1386,13 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
}
|
||||
}
|
||||
|
||||
await this._webview!.initializeMarkup(requests.map(request => ({
|
||||
mime: 'text/markdown',
|
||||
cellId: request[0].id,
|
||||
cellHandle: request[0].handle,
|
||||
content: request[0].getText(),
|
||||
offset: request[1],
|
||||
visible: false,
|
||||
})));
|
||||
await this._webview!.initializeMarkup(requests.map(([model, offset]) => this.createMarkupCellInitialization(model, offset)));
|
||||
} else {
|
||||
const initRequests = viewModel.viewCells.filter(cell => cell.cellKind === CellKind.Markup).slice(0, 5).map(cell => ({
|
||||
cellId: cell.id, cellHandle: cell.handle, content: cell.getText(), offset: -10000, visible: false, mime: 'text/markdown',
|
||||
}));
|
||||
const initRequests = viewModel.viewCells
|
||||
.filter(cell => cell.cellKind === CellKind.Markup)
|
||||
.slice(0, 5)
|
||||
.map(cell => this.createMarkupCellInitialization(cell, -10000));
|
||||
|
||||
await this._webview!.initializeMarkup(initRequests);
|
||||
|
||||
// no cached view state so we are rendering the first viewport
|
||||
@@ -1420,6 +1416,17 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
}
|
||||
}
|
||||
|
||||
private createMarkupCellInitialization(model: ICellViewModel, offset: number): IMarkupCellInitialization {
|
||||
return ({
|
||||
mime: model.mime,
|
||||
cellId: model.id,
|
||||
cellHandle: model.handle,
|
||||
content: model.getText(),
|
||||
offset: offset,
|
||||
visible: false,
|
||||
});
|
||||
}
|
||||
|
||||
restoreListViewState(viewState: INotebookEditorViewState | undefined): void {
|
||||
if (viewState?.scrollPosition !== undefined) {
|
||||
this._list.scrollTop = viewState!.scrollPosition.top;
|
||||
@@ -2264,7 +2271,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
||||
|
||||
const cellTop = this._list.getAbsoluteTopOfElement(cell);
|
||||
await this._webview.showMarkdownPreview({
|
||||
mime: 'text/markdown',
|
||||
mime: cell.mime,
|
||||
cellHandle: cell.handle,
|
||||
cellId: cell.id,
|
||||
content: cell.getText(),
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
|
||||
@@ -215,7 +216,7 @@ class PlainTextRendererContrib extends Disposable implements IOutputRendererCont
|
||||
}
|
||||
|
||||
getMimetypes() {
|
||||
return ['text/plain'];
|
||||
return [Mimes.text];
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -270,7 +271,7 @@ class MdRendererContrib extends Disposable implements IOutputRendererContributio
|
||||
}
|
||||
|
||||
getMimetypes() {
|
||||
return ['text/markdown'];
|
||||
return [Mimes.markdown];
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -525,17 +525,12 @@ var requirejs = (function() {
|
||||
}
|
||||
case 'focus-editor':
|
||||
{
|
||||
const resolvedResult = this.resolveOutputId(data.id);
|
||||
if (resolvedResult) {
|
||||
const latestCell = this.notebookEditor.getCellByInfo(resolvedResult.cellInfo);
|
||||
if (!latestCell) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cell = this.notebookEditor.getCellById(data.cellId);
|
||||
if (cell) {
|
||||
if (data.focusNext) {
|
||||
this.notebookEditor.focusNextNotebookCell(latestCell, 'editor');
|
||||
this.notebookEditor.focusNextNotebookCell(cell, 'editor');
|
||||
} else {
|
||||
this.notebookEditor.focusNotebookCell(latestCell, 'editor');
|
||||
this.notebookEditor.focusNotebookCell(cell, 'editor');
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -812,6 +807,7 @@ var requirejs = (function() {
|
||||
this.hiddenInsetMapping.delete(request.output);
|
||||
|
||||
return {
|
||||
cellId: request.cell.id,
|
||||
outputId: id,
|
||||
cellTop: request.cellTop,
|
||||
outputOffset: request.outputOffset,
|
||||
@@ -826,7 +822,7 @@ var requirejs = (function() {
|
||||
this._sendMessageToWebview({
|
||||
type: 'view-scroll',
|
||||
widgets: widgets,
|
||||
markdownPreviews,
|
||||
markupCells: markdownPreviews,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
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';
|
||||
@@ -49,8 +47,8 @@ export class CellDragAndDropController extends Disposable {
|
||||
|
||||
this.listInsertionIndicator = DOM.append(insertionIndicatorContainer, $('.cell-list-insertion-indicator'));
|
||||
|
||||
this._register(domEvent(document.body, DOM.EventType.DRAG_START, true)(this.onGlobalDragStart.bind(this)));
|
||||
this._register(domEvent(document.body, DOM.EventType.DRAG_END, true)(this.onGlobalDragEnd.bind(this)));
|
||||
this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_START, this.onGlobalDragStart.bind(this), true));
|
||||
this._register(DOM.addDisposableListener(document.body, DOM.EventType.DRAG_END, this.onGlobalDragEnd.bind(this), true));
|
||||
|
||||
const addCellDragListener = (eventType: string, handler: (e: CellDragEvent) => void) => {
|
||||
this._register(DOM.addDisposableListener(
|
||||
@@ -300,7 +298,7 @@ export class CellDragAndDropController extends Disposable {
|
||||
const container = templateData.container;
|
||||
dragHandle.setAttribute('draggable', 'true');
|
||||
|
||||
templateData.disposables.add(domEvent(dragHandle, DOM.EventType.DRAG_END)(() => {
|
||||
templateData.disposables.add(DOM.addDisposableListener(dragHandle, DOM.EventType.DRAG_END, () => {
|
||||
if (!this.notebookEditor.notebookOptions.getLayoutConfiguration().dragAndDropEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -310,7 +308,7 @@ export class CellDragAndDropController extends Disposable {
|
||||
this.dragCleanup();
|
||||
}));
|
||||
|
||||
templateData.disposables.add(domEvent(dragHandle, DOM.EventType.DRAG_START)(event => {
|
||||
templateData.disposables.add(DOM.addDisposableListener(dragHandle, DOM.EventType.DRAG_START, event => {
|
||||
if (!event.dataTransfer) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { getPixelRatio, getZoomLevel } from 'vs/base/browser/browser';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { renderIcon } from 'vs/base/browser/ui/iconLabel/iconLabels';
|
||||
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
@@ -261,7 +260,7 @@ abstract class AbstractCellRenderer {
|
||||
}
|
||||
|
||||
protected addExpandListener(templateData: BaseCellRenderTemplate): void {
|
||||
templateData.disposables.add(domEvent(templateData.expandButton, DOM.EventType.CLICK)(() => {
|
||||
templateData.disposables.add(DOM.addDisposableListener(templateData.expandButton, DOM.EventType.CLICK, () => {
|
||||
if (!templateData.currentRenderedCell) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ export interface IScrollAckMessage extends BaseToWebviewMessage {
|
||||
|
||||
export interface IBlurOutputMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'focus-editor';
|
||||
readonly id: string;
|
||||
readonly cellId: string;
|
||||
readonly focusNext?: boolean;
|
||||
}
|
||||
|
||||
@@ -174,6 +174,7 @@ export interface ICreationRequestMessage {
|
||||
}
|
||||
|
||||
export interface IContentWidgetTopRequest {
|
||||
readonly cellId: string;
|
||||
readonly outputId: string;
|
||||
readonly cellTop: number;
|
||||
readonly outputOffset: number;
|
||||
@@ -183,7 +184,7 @@ export interface IContentWidgetTopRequest {
|
||||
export interface IViewScrollTopRequestMessage {
|
||||
readonly type: 'view-scroll';
|
||||
readonly widgets: IContentWidgetTopRequest[];
|
||||
readonly markdownPreviews: { id: string; top: number; }[];
|
||||
readonly markupCells: { id: string; top: number; }[];
|
||||
}
|
||||
|
||||
export interface IScrollRequestMessage {
|
||||
|
||||
@@ -320,12 +320,12 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
}
|
||||
}
|
||||
|
||||
function createFocusSink(cellId: string, outputId: string, focusNext?: boolean) {
|
||||
function createFocusSink(cellId: string, focusNext?: boolean) {
|
||||
const element = document.createElement('div');
|
||||
element.tabIndex = 0;
|
||||
element.addEventListener('focus', () => {
|
||||
postNotebookMessage<webviewMessages.IBlurOutputMessage>('focus-editor', {
|
||||
id: outputId,
|
||||
cellId: cellId,
|
||||
focusNext
|
||||
});
|
||||
});
|
||||
@@ -357,7 +357,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
return false;
|
||||
}
|
||||
|
||||
class FocusTracker {
|
||||
class OutputFocusTracker {
|
||||
private _outputId: string;
|
||||
private _hasFocus: boolean = false;
|
||||
private _loosingFocus: boolean = false;
|
||||
@@ -405,14 +405,14 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
}
|
||||
}
|
||||
|
||||
const focusTrackers = new Map<string, FocusTracker>();
|
||||
const outputFocusTrackers = new Map<string, OutputFocusTracker>();
|
||||
|
||||
function addFocusTracker(element: HTMLElement, outputId: string): void {
|
||||
if (focusTrackers.has(outputId)) {
|
||||
focusTrackers.get(outputId)?.dispose();
|
||||
function addOutputFocusTracker(element: HTMLElement, outputId: string): void {
|
||||
if (outputFocusTrackers.has(outputId)) {
|
||||
outputFocusTrackers.get(outputId)?.dispose();
|
||||
}
|
||||
|
||||
focusTrackers.set(outputId, new FocusTracker(element, outputId));
|
||||
outputFocusTrackers.set(outputId, new OutputFocusTracker(element, outputId));
|
||||
}
|
||||
|
||||
function createEmitter<T>(listenerChange: (listeners: Set<Listener<T>>) => void = () => undefined): EmitterLike<T> {
|
||||
@@ -511,44 +511,46 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
|
||||
switch (event.data.type) {
|
||||
case 'initializeMarkup':
|
||||
await notebookDocument.ensureMarkupCells(event.data.cells);
|
||||
await viewModel.ensureMarkupCells(event.data.cells);
|
||||
dimensionUpdater.updateImmediately();
|
||||
postNotebookMessage('initializedMarkup', {});
|
||||
break;
|
||||
|
||||
case 'createMarkupCell':
|
||||
notebookDocument.ensureMarkupCells([event.data.cell]);
|
||||
viewModel.ensureMarkupCells([event.data.cell]);
|
||||
break;
|
||||
|
||||
case 'showMarkupCell':
|
||||
notebookDocument.showMarkupCell(event.data.id, event.data.top, event.data.content);
|
||||
viewModel.showMarkupCell(event.data.id, event.data.top, event.data.content);
|
||||
break;
|
||||
|
||||
case 'hideMarkupCells':
|
||||
for (const id of event.data.ids) {
|
||||
notebookDocument.hideMarkupCell(id);
|
||||
viewModel.hideMarkupCell(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'unhideMarkupCells':
|
||||
for (const id of event.data.ids) {
|
||||
notebookDocument.unhideMarkupCell(id);
|
||||
viewModel.unhideMarkupCell(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'deleteMarkupCell':
|
||||
for (const id of event.data.ids) {
|
||||
notebookDocument.deleteMarkupCell(id);
|
||||
viewModel.deleteMarkupCell(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'updateSelectedMarkupCells':
|
||||
notebookDocument.updateSelectedCells(event.data.selectedCellIds);
|
||||
viewModel.updateSelectedCells(event.data.selectedCellIds);
|
||||
break;
|
||||
|
||||
case 'html': {
|
||||
const data = event.data;
|
||||
outputs.enqueue(event.data.outputId, async (state) => {
|
||||
const outputId = data.outputId;
|
||||
|
||||
outputRunner.enqueue(event.data.outputId, async (state) => {
|
||||
const preloadsAndErrors = await Promise.all<unknown>([
|
||||
data.rendererId ? renderers.load(data.rendererId) : undefined,
|
||||
...data.requiredPreloads.map(p => kernelPreloads.waitFor(p.uri)),
|
||||
@@ -558,48 +560,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
return;
|
||||
}
|
||||
|
||||
let cellOutputContainer = document.getElementById(data.cellId);
|
||||
const outputId = data.outputId;
|
||||
if (!cellOutputContainer) {
|
||||
const container = document.getElementById('container')!;
|
||||
const cellOutput = viewModel.ensureOutputCell(data.cellId, data.cellTop);
|
||||
const outputNode = cellOutput.createOutputNode(outputId, data.outputOffset, data.left);
|
||||
|
||||
const upperWrapperElement = createFocusSink(data.cellId, outputId);
|
||||
container.appendChild(upperWrapperElement);
|
||||
|
||||
const newElement = document.createElement('div');
|
||||
|
||||
newElement.id = data.cellId;
|
||||
newElement.classList.add('cell_container');
|
||||
|
||||
container.appendChild(newElement);
|
||||
cellOutputContainer = newElement;
|
||||
|
||||
const lowerWrapperElement = createFocusSink(data.cellId, outputId, true);
|
||||
container.appendChild(lowerWrapperElement);
|
||||
}
|
||||
|
||||
cellOutputContainer.style.position = 'absolute';
|
||||
cellOutputContainer.style.top = data.cellTop + 'px';
|
||||
|
||||
const outputContainer = document.createElement('div');
|
||||
outputContainer.classList.add('output_container');
|
||||
outputContainer.style.position = 'absolute';
|
||||
outputContainer.style.overflow = 'hidden';
|
||||
outputContainer.style.maxHeight = '0px';
|
||||
outputContainer.style.top = `${data.outputOffset}px`;
|
||||
|
||||
const outputNode = document.createElement('div');
|
||||
outputNode.classList.add('output');
|
||||
outputNode.style.position = 'absolute';
|
||||
outputNode.style.top = `0px`;
|
||||
outputNode.style.left = data.left + 'px';
|
||||
// outputNode.style.width = 'calc(100% - ' + data.left + 'px)';
|
||||
// outputNode.style.minHeight = '32px';
|
||||
outputNode.style.padding = '0px';
|
||||
outputNode.id = outputId;
|
||||
|
||||
addMouseoverListeners(outputNode, outputId);
|
||||
addFocusTracker(outputNode, outputId);
|
||||
const content = data.content;
|
||||
if (content.type === RenderOutputType.Html) {
|
||||
const trustedHtml = ttPolicy?.createHTML(content.htmlContent) ?? content.htmlContent;
|
||||
@@ -636,8 +599,6 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
}
|
||||
}
|
||||
|
||||
cellOutputContainer.appendChild(outputContainer);
|
||||
outputContainer.appendChild(outputNode);
|
||||
resizeObserver.observe(outputNode, outputId, true);
|
||||
|
||||
if (content.type === RenderOutputType.Html) {
|
||||
@@ -663,7 +624,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
}
|
||||
|
||||
// don't hide until after this step so that the height is right
|
||||
cellOutputContainer.style.visibility = data.initiallyHidden ? 'hidden' : 'visible';
|
||||
cellOutput.element.style.visibility = data.initiallyHidden ? 'hidden' : 'visible';
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -672,84 +633,46 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
// const date = new Date();
|
||||
// console.log('----- will scroll ---- ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds());
|
||||
|
||||
for (const request of event.data.widgets) {
|
||||
const widget = document.getElementById(request.outputId);
|
||||
if (widget) {
|
||||
widget.parentElement!.parentElement!.style.top = `${request.cellTop}px`;
|
||||
widget.parentElement!.style.top = `${request.outputOffset}px`;
|
||||
if (request.forceDisplay) {
|
||||
widget.parentElement!.parentElement!.style.visibility = 'visible';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const cell of event.data.markdownPreviews) {
|
||||
const container = document.getElementById(cell.id);
|
||||
if (container) {
|
||||
container.style.top = `${cell.top}px`;
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.updateOutputsScroll(event.data.widgets);
|
||||
viewModel.updateMarkupScrolls(event.data.markupCells);
|
||||
break;
|
||||
}
|
||||
case 'clear':
|
||||
renderers.clearAll();
|
||||
viewModel.clearAll();
|
||||
document.getElementById('container')!.innerText = '';
|
||||
|
||||
focusTrackers.forEach(ft => {
|
||||
outputFocusTrackers.forEach(ft => {
|
||||
ft.dispose();
|
||||
});
|
||||
focusTrackers.clear();
|
||||
outputFocusTrackers.clear();
|
||||
break;
|
||||
|
||||
case 'clearOutput': {
|
||||
const output = document.getElementById(event.data.outputId);
|
||||
const { rendererId, outputId } = event.data;
|
||||
|
||||
outputs.cancelOutput(outputId);
|
||||
if (output && output.parentNode) {
|
||||
if (rendererId) {
|
||||
renderers.clearOutput(rendererId, outputId);
|
||||
}
|
||||
output.parentNode.removeChild(output);
|
||||
}
|
||||
|
||||
const { cellId, rendererId, outputId } = event.data;
|
||||
outputRunner.cancelOutput(outputId);
|
||||
viewModel.clearOutput(cellId, outputId, rendererId);
|
||||
break;
|
||||
}
|
||||
case 'hideOutput': {
|
||||
const { outputId } = event.data;
|
||||
outputs.enqueue(event.data.outputId, () => {
|
||||
const container = document.getElementById(outputId)?.parentElement?.parentElement;
|
||||
if (container) {
|
||||
container.style.visibility = 'hidden';
|
||||
}
|
||||
const { cellId, outputId } = event.data;
|
||||
outputRunner.enqueue(outputId, () => {
|
||||
viewModel.hideOutput(cellId);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'showOutput': {
|
||||
const { outputId, cellTop: top } = event.data;
|
||||
outputs.enqueue(event.data.outputId, () => {
|
||||
const output = document.getElementById(outputId);
|
||||
if (output) {
|
||||
output.parentElement!.parentElement!.style.visibility = 'visible';
|
||||
output.parentElement!.parentElement!.style.top = top + 'px';
|
||||
|
||||
dimensionUpdater.update(outputId, output.clientHeight, {
|
||||
isOutput: true,
|
||||
});
|
||||
}
|
||||
const { outputId, cellTop, cellId } = event.data;
|
||||
outputRunner.enqueue(outputId, () => {
|
||||
viewModel.showOutput(cellId, outputId, cellTop);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'ack-dimension':
|
||||
{
|
||||
const { outputId, height } = event.data;
|
||||
const output = document.getElementById(outputId);
|
||||
if (output) {
|
||||
output.parentElement!.style.maxHeight = `${height}px`;
|
||||
output.parentElement!.style.height = `${height}px`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'ack-dimension': {
|
||||
const { cellId, outputId, height } = event.data;
|
||||
viewModel.updateOutputHeight(cellId, outputId, height);
|
||||
break;
|
||||
}
|
||||
case 'preload':
|
||||
const resources = event.data.resources;
|
||||
for (const { uri, originalUri } of resources) {
|
||||
@@ -792,12 +715,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
break;
|
||||
case 'notebookOptions':
|
||||
currentOptions = event.data.options;
|
||||
|
||||
// Update markdown previews
|
||||
for (const markdownContainer of document.querySelectorAll('.preview')) {
|
||||
setMarkupContainerDraggable(markdownContainer, currentOptions.dragAndDropEnabled);
|
||||
}
|
||||
|
||||
viewModel.toggleDragDropEnabled(currentOptions.dragAndDropEnabled);
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -907,8 +825,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
}
|
||||
};
|
||||
|
||||
const outputs = new class {
|
||||
private outputs = new Map<string, { cancelled: boolean; queue: Promise<unknown> }>();
|
||||
const outputRunner = new class {
|
||||
private readonly outputs = new Map<string, { cancelled: boolean; queue: Promise<unknown> }>();
|
||||
|
||||
/**
|
||||
* Pushes the action onto the list of actions for the given output ID,
|
||||
* ensuring that it's run in-order.
|
||||
@@ -975,14 +894,14 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
|
||||
|
||||
public clearAll() {
|
||||
outputs.cancelAll();
|
||||
outputRunner.cancelAll();
|
||||
for (const renderer of this._renderers.values()) {
|
||||
renderer.api?.disposeOutputItem?.();
|
||||
}
|
||||
}
|
||||
|
||||
public clearOutput(rendererId: string, outputId: string) {
|
||||
outputs.cancelOutput(outputId);
|
||||
outputRunner.cancelOutput(outputId);
|
||||
this._renderers.get(rendererId)?.api?.disposeOutputItem?.(outputId);
|
||||
}
|
||||
|
||||
@@ -1003,9 +922,10 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
let hasPostedRenderedMathTelemetry = false;
|
||||
const unsupportedKatexTermsRegex = /(\\(?:abovewithdelims|array|Arrowvert|arrowvert|atopwithdelims|bbox|bracevert|buildrel|cancelto|cases|class|cssId|ddddot|dddot|DeclareMathOperator|definecolor|displaylines|enclose|eqalign|eqalignno|eqref|hfil|hfill|idotsint|iiiint|label|leftarrowtail|leftroot|leqalignno|lower|mathtip|matrix|mbox|mit|mmlToken|moveleft|moveright|mspace|newenvironment|Newextarrow|notag|oldstyle|overparen|overwithdelims|pmatrix|raise|ref|renewenvironment|require|root|Rule|scr|shoveleft|shoveright|sideset|skew|Space|strut|style|texttip|Tiny|toggle|underparen|unicode|uproot)\b)/gi;
|
||||
|
||||
const notebookDocument = new class {
|
||||
const viewModel = new class ViewModel {
|
||||
|
||||
private readonly _markupCells = new Map<string, MarkupCell>();
|
||||
private readonly _outputCells = new Map<string, OutputCell>();
|
||||
|
||||
private async createMarkupCell(init: webviewMessages.IMarkupCellInitialization, top: number): Promise<MarkupCell> {
|
||||
const existing = this._markupCells.get(init.cellId);
|
||||
@@ -1014,11 +934,11 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
return existing;
|
||||
}
|
||||
|
||||
const markdownCell = new MarkupCell(init.cellId, init.mime, init.content, top);
|
||||
this._markupCells.set(init.cellId, markdownCell);
|
||||
const cell = new MarkupCell(init.cellId, init.mime, init.content, top);
|
||||
this._markupCells.set(init.cellId, cell);
|
||||
|
||||
await markdownCell.ready;
|
||||
return markdownCell;
|
||||
await cell.ready;
|
||||
return cell;
|
||||
}
|
||||
|
||||
public async ensureMarkupCells(update: readonly webviewMessages.IMarkupCellInitialization[]): Promise<void> {
|
||||
@@ -1076,13 +996,71 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
cell.setSelected(selectedCellSet.has(cell.id));
|
||||
}
|
||||
}
|
||||
|
||||
public toggleDragDropEnabled(dragAndDropEnabled: boolean) {
|
||||
for (const cell of this._markupCells.values()) {
|
||||
cell.toggleDragDropEnabled(dragAndDropEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
public updateMarkupScrolls(markupCells: { id: string; top: number; }[]) {
|
||||
for (const { id, top } of markupCells) {
|
||||
const cell = this._markupCells.get(id);
|
||||
if (cell) {
|
||||
cell.element.style.top = `${top}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public clearAll() {
|
||||
this._markupCells.clear();
|
||||
this._outputCells.clear();
|
||||
}
|
||||
|
||||
public ensureOutputCell(cellId: string, cellTop: number): OutputCell {
|
||||
let cell = this._outputCells.get(cellId);
|
||||
if (!cell) {
|
||||
cell = new OutputCell(cellId);
|
||||
this._outputCells.set(cellId, cell);
|
||||
}
|
||||
|
||||
cell.element.style.top = cellTop + 'px';
|
||||
return cell;
|
||||
}
|
||||
|
||||
public clearOutput(cellId: string, outputId: string, rendererId: string | undefined) {
|
||||
const cell = this._outputCells.get(cellId);
|
||||
cell?.clearOutput(outputId, rendererId);
|
||||
}
|
||||
|
||||
public showOutput(cellId: string, outputId: string, top: number) {
|
||||
const cell = this._outputCells.get(cellId);
|
||||
cell?.show(outputId, top);
|
||||
}
|
||||
|
||||
public hideOutput(cellId: string) {
|
||||
const cell = this._outputCells.get(cellId);
|
||||
cell?.hide();
|
||||
}
|
||||
|
||||
public updateOutputHeight(cellId: string, outputId: string, height: number) {
|
||||
const cell = this._outputCells.get(cellId);
|
||||
cell?.updateOutputHeight(outputId, height);
|
||||
}
|
||||
|
||||
public updateOutputsScroll(updates: webviewMessages.IContentWidgetTopRequest[]) {
|
||||
for (const request of updates) {
|
||||
const cell = this._outputCells.get(request.cellId);
|
||||
cell?.updateScroll(request);
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
class MarkupCell implements IOutputItem {
|
||||
|
||||
public readonly ready: Promise<void>;
|
||||
|
||||
/// Internal field that holds markdown text
|
||||
/// Internal field that holds text content
|
||||
private _content: string;
|
||||
|
||||
constructor(id: string, mime: string, content: string, top: number) {
|
||||
@@ -1100,6 +1078,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
this.element.classList.add('preview');
|
||||
this.element.style.position = 'absolute';
|
||||
this.element.style.top = top + 'px';
|
||||
this.toggleDragDropEnabled(currentOptions.dragAndDropEnabled);
|
||||
root.appendChild(this.element);
|
||||
|
||||
this.addEventListeners();
|
||||
@@ -1158,18 +1137,16 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
postNotebookMessage<webviewMessages.IMouseLeaveMarkupCellMessage>('mouseLeaveMarkupCell', { cellId: this.id });
|
||||
});
|
||||
|
||||
setMarkupContainerDraggable(this.element, currentOptions.dragAndDropEnabled);
|
||||
|
||||
this.element.addEventListener('dragstart', e => {
|
||||
markdownPreviewDragManager.startDrag(e, this.id);
|
||||
markupCellDragManager.startDrag(e, this.id);
|
||||
});
|
||||
|
||||
this.element.addEventListener('drag', e => {
|
||||
markdownPreviewDragManager.updateDrag(e, this.id);
|
||||
markupCellDragManager.updateDrag(e, this.id);
|
||||
});
|
||||
|
||||
this.element.addEventListener('dragend', e => {
|
||||
markdownPreviewDragManager.endDrag(e, this.id);
|
||||
markupCellDragManager.endDrag(e, this.id);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1226,6 +1203,125 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
public setSelected(selected: boolean) {
|
||||
this.element.classList.toggle('selected', selected);
|
||||
}
|
||||
|
||||
public toggleDragDropEnabled(enabled: boolean) {
|
||||
if (enabled) {
|
||||
this.element.classList.add('draggable');
|
||||
this.element.setAttribute('draggable', 'true');
|
||||
} else {
|
||||
this.element.classList.remove('draggable');
|
||||
this.element.removeAttribute('draggable');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OutputCell {
|
||||
|
||||
public readonly element: HTMLElement;
|
||||
|
||||
public readonly outputElements = new Map</*outputId*/ string, HTMLElement>();
|
||||
|
||||
constructor(cellId: string) {
|
||||
const container = document.getElementById('container')!;
|
||||
|
||||
const upperWrapperElement = createFocusSink(cellId);
|
||||
container.appendChild(upperWrapperElement);
|
||||
|
||||
this.element = document.createElement('div');
|
||||
this.element.style.position = 'absolute';
|
||||
|
||||
this.element.id = cellId;
|
||||
this.element.classList.add('cell_container');
|
||||
|
||||
container.appendChild(this.element);
|
||||
this.element = this.element;
|
||||
|
||||
const lowerWrapperElement = createFocusSink(cellId, true);
|
||||
container.appendChild(lowerWrapperElement);
|
||||
}
|
||||
|
||||
public createOutputNode(outputId: string, outputOffset: number, left: number): HTMLElement {
|
||||
let outputContainer = this.outputElements.get(outputId);
|
||||
if (!outputContainer) {
|
||||
outputContainer = document.createElement('div');
|
||||
outputContainer.classList.add('output_container');
|
||||
outputContainer.style.position = 'absolute';
|
||||
outputContainer.style.overflow = 'hidden';
|
||||
this.element.appendChild(outputContainer);
|
||||
this.outputElements.set(outputId, outputContainer);
|
||||
}
|
||||
outputContainer.innerText = '';
|
||||
outputContainer.style.maxHeight = '0px';
|
||||
outputContainer.style.top = `${outputOffset}px`;
|
||||
|
||||
const outputNode = document.createElement('div');
|
||||
outputNode.id = outputId;
|
||||
outputNode.classList.add('output');
|
||||
outputNode.style.position = 'absolute';
|
||||
outputNode.style.top = `0px`;
|
||||
outputNode.style.left = left + 'px';
|
||||
outputNode.style.padding = '0px';
|
||||
outputContainer.appendChild(outputNode);
|
||||
|
||||
addMouseoverListeners(outputNode, outputId);
|
||||
addOutputFocusTracker(outputNode, outputId);
|
||||
|
||||
return outputNode;
|
||||
}
|
||||
|
||||
public clearOutput(outputId: string, rendererId: string | undefined) {
|
||||
const outputContainer = this.outputElements.get(outputId);
|
||||
if (!outputContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rendererId) {
|
||||
renderers.clearOutput(rendererId, outputId);
|
||||
}
|
||||
outputContainer.remove();
|
||||
this.outputElements.delete(outputId);
|
||||
}
|
||||
|
||||
public show(outputId: string, top: number) {
|
||||
const outputContainer = this.outputElements.get(outputId);
|
||||
if (!outputContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.element.style.visibility = 'visible';
|
||||
this.element.style.top = `${top}px`;
|
||||
|
||||
dimensionUpdater.update(outputId, outputContainer.clientHeight, {
|
||||
isOutput: true,
|
||||
});
|
||||
}
|
||||
|
||||
public hide() {
|
||||
this.element.style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
public updateOutputHeight(outputId: string, height: number) {
|
||||
const outputContainer = this.outputElements.get(outputId);
|
||||
if (!outputContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
outputContainer.style.maxHeight = `${height}px`;
|
||||
outputContainer.style.height = `${height}px`;
|
||||
}
|
||||
|
||||
public updateScroll(request: webviewMessages.IContentWidgetTopRequest) {
|
||||
this.element.style.top = `${request.cellTop}px`;
|
||||
|
||||
const outputContainer = this.outputElements.get(request.outputId);
|
||||
if (outputContainer) {
|
||||
outputContainer.style.top = `${request.outputOffset}px`;
|
||||
}
|
||||
|
||||
if (request.forceDisplay) {
|
||||
this.element.style.visibility = 'visible';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vscode.postMessage({
|
||||
@@ -1233,16 +1329,6 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
type: 'initialized'
|
||||
});
|
||||
|
||||
function setMarkupContainerDraggable(element: Element, isDraggable: boolean) {
|
||||
if (isDraggable) {
|
||||
element.classList.add('draggable');
|
||||
element.setAttribute('draggable', 'true');
|
||||
} else {
|
||||
element.classList.remove('draggable');
|
||||
element.removeAttribute('draggable');
|
||||
}
|
||||
}
|
||||
|
||||
function postNotebookMessage<T extends webviewMessages.FromWebviewMessage>(
|
||||
type: T['type'],
|
||||
properties: Omit<T, '__vscode_notebook_message' | 'type'>
|
||||
@@ -1254,13 +1340,13 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
||||
});
|
||||
}
|
||||
|
||||
const markdownPreviewDragManager = new class MarkdownPreviewDragManager {
|
||||
const markupCellDragManager = new class MarkupCellDragManager {
|
||||
|
||||
private currentDrag: { cellId: string, clientY: number } | undefined;
|
||||
|
||||
constructor() {
|
||||
document.addEventListener('dragover', e => {
|
||||
// Allow dropping dragged markdown cells
|
||||
// Allow dropping dragged markup cells
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode
|
||||
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';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
export abstract class BaseCellViewModel extends Disposable {
|
||||
|
||||
@@ -46,6 +47,16 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
return this.model.language;
|
||||
}
|
||||
|
||||
get mime(): string {
|
||||
switch (this.language) {
|
||||
case 'markdown':
|
||||
return Mimes.markdown;
|
||||
|
||||
default:
|
||||
return Mimes.text;
|
||||
}
|
||||
}
|
||||
|
||||
abstract cellKind: CellKind;
|
||||
|
||||
private _editState: CellEditState = CellEditState.Preview;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IDiffResult, ISequence } from 'vs/base/common/diff/diff';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import * as glob from 'vs/base/common/glob';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
@@ -34,16 +35,16 @@ export const NOTEBOOK_DISPLAY_ORDER = [
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
];
|
||||
|
||||
export const ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER = [
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'application/json',
|
||||
'text/plain',
|
||||
Mimes.text,
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'image/png',
|
||||
@@ -586,8 +587,8 @@ const _mimeTypeInfo = new Map<string, MimeTypeInfo>([
|
||||
['image/git', { alwaysSecure: true, supportedByCore: true }],
|
||||
['image/svg+xml', { supportedByCore: true }],
|
||||
['application/json', { alwaysSecure: true, supportedByCore: true }],
|
||||
['text/markdown', { alwaysSecure: true, supportedByCore: true }],
|
||||
['text/plain', { alwaysSecure: true, supportedByCore: true }],
|
||||
[Mimes.markdown, { alwaysSecure: true, supportedByCore: true }],
|
||||
[Mimes.text, { alwaysSecure: true, supportedByCore: true }],
|
||||
['text/html', { supportedByCore: true }],
|
||||
['text/x-javascript', { alwaysSecure: true, supportedByCore: true }], // secure because rendered as text, not executed
|
||||
['application/vnd.code.notebook.error', { alwaysSecure: true, supportedByCore: true }],
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { NOTEBOOK_DISPLAY_ORDER, sortMimeTypes, CellKind, diff, CellUri, NotebookWorkingCopyTypeIdentifier } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { cellRangesToIndexes, cellIndexesToRanges } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { TestCell, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { CellKind, CellUri, diff, NotebookWorkingCopyTypeIdentifier, NOTEBOOK_DISPLAY_ORDER, sortMimeTypes } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { cellIndexesToRanges, cellRangesToIndexes } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { setupInstantiationService, TestCell } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
|
||||
suite('NotebookCommon', () => {
|
||||
const instantiationService = setupInstantiationService();
|
||||
@@ -23,30 +24,30 @@ suite('NotebookCommon', () => {
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
], [], defaultDisplayOrder),
|
||||
[
|
||||
'application/json',
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
]
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(sortMimeTypes(
|
||||
[
|
||||
'application/json',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'text/plain',
|
||||
Mimes.text,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'image/svg+xml'
|
||||
@@ -56,18 +57,18 @@ suite('NotebookCommon', () => {
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
]
|
||||
);
|
||||
|
||||
assert.deepStrictEqual(sortMimeTypes(
|
||||
[
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'application/json',
|
||||
'text/plain',
|
||||
Mimes.text,
|
||||
'image/jpeg',
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
@@ -79,10 +80,10 @@ suite('NotebookCommon', () => {
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
]
|
||||
);
|
||||
});
|
||||
@@ -97,22 +98,22 @@ suite('NotebookCommon', () => {
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
],
|
||||
[
|
||||
'image/png',
|
||||
'text/plain',
|
||||
'text/markdown',
|
||||
Mimes.text,
|
||||
Mimes.markdown,
|
||||
'text/html',
|
||||
'application/json'
|
||||
], defaultDisplayOrder),
|
||||
[
|
||||
'image/png',
|
||||
'text/plain',
|
||||
'text/markdown',
|
||||
Mimes.text,
|
||||
Mimes.markdown,
|
||||
'text/html',
|
||||
'application/json',
|
||||
'application/javascript',
|
||||
@@ -123,9 +124,9 @@ suite('NotebookCommon', () => {
|
||||
|
||||
assert.deepStrictEqual(sortMimeTypes(
|
||||
[
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'application/json',
|
||||
'text/plain',
|
||||
Mimes.text,
|
||||
'application/javascript',
|
||||
'text/html',
|
||||
'image/svg+xml',
|
||||
@@ -136,18 +137,18 @@ suite('NotebookCommon', () => {
|
||||
'application/json',
|
||||
'text/html',
|
||||
'text/html',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'application/json'
|
||||
], defaultDisplayOrder),
|
||||
[
|
||||
'application/json',
|
||||
'text/html',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'application/javascript',
|
||||
'image/svg+xml',
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'text/plain'
|
||||
Mimes.text
|
||||
]
|
||||
);
|
||||
});
|
||||
@@ -165,7 +166,7 @@ suite('NotebookCommon', () => {
|
||||
'text/html'
|
||||
],
|
||||
[
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'text/html',
|
||||
'application/json'
|
||||
], defaultDisplayOrder),
|
||||
@@ -189,7 +190,7 @@ suite('NotebookCommon', () => {
|
||||
],
|
||||
[
|
||||
'application/vnd-vega*',
|
||||
'text/markdown',
|
||||
Mimes.markdown,
|
||||
'text/html',
|
||||
'application/json'
|
||||
], defaultDisplayOrder),
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { LcsDiff } from 'vs/base/common/diff/diff';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { NotebookDiffEditorEventDispatcher } from 'vs/workbench/contrib/notebook/browser/diff/eventDispatcher';
|
||||
import { NotebookTextDiffEditor } from 'vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor';
|
||||
import { CellKind, CellSequence } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
@@ -14,9 +15,9 @@ suite('NotebookCommon', () => {
|
||||
|
||||
test('diff different source', async () => {
|
||||
await withTestNotebookDiffModel([
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someOtherId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 3 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someOtherId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 3 }],
|
||||
], [
|
||||
['y', 'javascript', CellKind.Code, [{ outputId: 'someOtherId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 3 }],
|
||||
['y', 'javascript', CellKind.Code, [{ outputId: 'someOtherId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 3 }],
|
||||
], (model, accessor) => {
|
||||
const diff = new LcsDiff(new CellSequence(model.original.notebook), new CellSequence(model.modified.notebook));
|
||||
const diffResult = diff.ComputeDiff(false);
|
||||
@@ -44,10 +45,10 @@ suite('NotebookCommon', () => {
|
||||
|
||||
test('diff different output', async () => {
|
||||
await withTestNotebookDiffModel([
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [5] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 5 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [5] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 5 }],
|
||||
['', 'javascript', CellKind.Code, [], {}]
|
||||
], [
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someOtherId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 3 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someOtherId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 3 }],
|
||||
['', 'javascript', CellKind.Code, [], {}]
|
||||
], (model, accessor) => {
|
||||
const diff = new LcsDiff(new CellSequence(model.original.notebook), new CellSequence(model.modified.notebook));
|
||||
@@ -145,12 +146,12 @@ suite('NotebookCommon', () => {
|
||||
|
||||
test('diff foo/foe', async () => {
|
||||
await withTestNotebookDiffModel([
|
||||
[['def foe(x, y):\n', ' return x + y\n', 'foe(3, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [6] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 5 }],
|
||||
[['def foo(x, y):\n', ' return x * y\n', 'foo(1, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [2] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 6 }],
|
||||
[['def foe(x, y):\n', ' return x + y\n', 'foe(3, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [6] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 5 }],
|
||||
[['def foo(x, y):\n', ' return x * y\n', 'foo(1, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [2] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 6 }],
|
||||
['', 'javascript', CellKind.Code, [], {}]
|
||||
], [
|
||||
[['def foo(x, y):\n', ' return x * y\n', 'foo(1, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [6] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 5 }],
|
||||
[['def foe(x, y):\n', ' return x + y\n', 'foe(3, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [2] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 6 }],
|
||||
[['def foo(x, y):\n', ' return x * y\n', 'foo(1, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [6] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 5 }],
|
||||
[['def foe(x, y):\n', ' return x + y\n', 'foe(3, 2)'].join(''), 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [2] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 6 }],
|
||||
['', 'javascript', CellKind.Code, [], {}]
|
||||
], (model, accessor) => {
|
||||
const diff = new LcsDiff(new CellSequence(model.original.notebook), new CellSequence(model.modified.notebook));
|
||||
@@ -272,13 +273,13 @@ suite('NotebookCommon', () => {
|
||||
await withTestNotebookDiffModel([
|
||||
['# Description', 'markdown', CellKind.Markup, [], { custom: { metadata: {} } }],
|
||||
['x = 3', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: true } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: false } } }]
|
||||
], [
|
||||
['# Description', 'markdown', CellKind.Markup, [], { custom: { metadata: {} } }],
|
||||
['x = 3', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: true } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: false } } }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }]
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }]
|
||||
], async (model) => {
|
||||
const diff = new LcsDiff(new CellSequence(model.original.notebook), new CellSequence(model.modified.notebook));
|
||||
const diffResult = diff.ComputeDiff(false);
|
||||
@@ -305,18 +306,18 @@ suite('NotebookCommon', () => {
|
||||
await withTestNotebookDiffModel([
|
||||
['# Description', 'markdown', CellKind.Markup, [], { custom: { metadata: {} } }],
|
||||
['x = 3', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: true } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: false } } }],
|
||||
['x = 5', 'javascript', CellKind.Code, [], {}],
|
||||
['x', 'javascript', CellKind.Code, [], {}],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [5] }] }], {}],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [5] }] }], {}],
|
||||
], [
|
||||
['# Description', 'markdown', CellKind.Markup, [], { custom: { metadata: {} } }],
|
||||
['x = 3', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: true } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [], { custom: { metadata: { collapsed: false } } }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [3] }] }], { custom: { metadata: { collapsed: false } }, executionOrder: 1 }],
|
||||
['x = 5', 'javascript', CellKind.Code, [], {}],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: 'text/plain', valueBytes: [5] }] }], {}],
|
||||
['x', 'javascript', CellKind.Code, [{ outputId: 'someId', outputs: [{ mime: Mimes.text, valueBytes: [5] }] }], {}],
|
||||
['x', 'javascript', CellKind.Code, [], {}],
|
||||
], async (model) => {
|
||||
const diff = new LcsDiff(new CellSequence(model.original.notebook), new CellSequence(model.modified.notebook));
|
||||
|
||||
@@ -20,6 +20,7 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookS
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
suite('NotebookEditorKernelManager', () => {
|
||||
|
||||
@@ -151,6 +152,6 @@ class TestNotebookKernel implements INotebookKernel {
|
||||
}
|
||||
|
||||
constructor(opts?: { languages: string[] }) {
|
||||
this.supportedLanguages = opts?.languages ?? ['text/plain'];
|
||||
this.supportedLanguages = opts?.languages ?? [Mimes.text];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import { CellKind, NotebookDataDto, TransientOptions } from 'vs/workbench/contri
|
||||
import { setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
suite('NotebookFileWorkingCopyModel', function () {
|
||||
|
||||
@@ -35,7 +36,7 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
const notebook = instantiationService.createInstance(NotebookTextModel,
|
||||
'notebook',
|
||||
URI.file('test'),
|
||||
[{ cellKind: CellKind.Code, language: 'foo', source: 'foo', outputs: [{ outputId: 'id', outputs: [{ mime: 'text/plain', value: 'Hello Out' }] }] }],
|
||||
[{ cellKind: CellKind.Code, language: 'foo', source: 'foo', outputs: [{ outputId: 'id', outputs: [{ mime: Mimes.text, value: 'Hello Out' }] }] }],
|
||||
{},
|
||||
{ transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ import { mock } from 'vs/base/test/common/mock';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
suite('NotebookKernelService', () => {
|
||||
|
||||
@@ -176,7 +177,7 @@ class TestNotebookKernel implements INotebookKernel {
|
||||
}
|
||||
|
||||
constructor(opts?: { languages?: string[], label?: string, viewType?: string }) {
|
||||
this.supportedLanguages = opts?.languages ?? ['text/plain'];
|
||||
this.supportedLanguages = opts?.languages ?? [Mimes.text];
|
||||
this.label = opts?.label ?? this.label;
|
||||
this.viewType = opts?.viewType ?? this.viewType;
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { CellKind, CellEditType, NotebookTextModelChangedEvent, SelectionStateType, ICellEditOperation } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { withTestNotebook, TestCell, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { CellEditType, CellKind, ICellEditOperation, NotebookTextModelChangedEvent, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { setupInstantiationService, TestCell, withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
|
||||
suite('NotebookTextModel', () => {
|
||||
|
||||
@@ -189,7 +190,7 @@ suite('NotebookTextModel', () => {
|
||||
editType: CellEditType.Output,
|
||||
outputs: [{
|
||||
outputId: 'someId',
|
||||
outputs: [{ mime: 'text/markdown', valueBytes: valueBytesFromString('_Hello_') }]
|
||||
outputs: [{ mime: Mimes.markdown, valueBytes: valueBytesFromString('_Hello_') }]
|
||||
}]
|
||||
}], true, undefined, () => undefined, undefined);
|
||||
|
||||
@@ -203,7 +204,7 @@ suite('NotebookTextModel', () => {
|
||||
append: true,
|
||||
outputs: [{
|
||||
outputId: 'someId2',
|
||||
outputs: [{ mime: 'text/markdown', valueBytes: valueBytesFromString('_Hello2_') }]
|
||||
outputs: [{ mime: Mimes.markdown, valueBytes: valueBytesFromString('_Hello2_') }]
|
||||
}]
|
||||
}], true, undefined, () => undefined, undefined);
|
||||
|
||||
@@ -219,7 +220,7 @@ suite('NotebookTextModel', () => {
|
||||
editType: CellEditType.Output,
|
||||
outputs: [{
|
||||
outputId: 'someId3',
|
||||
outputs: [{ mime: 'text/plain', valueBytes: valueBytesFromString('Last, replaced output') }]
|
||||
outputs: [{ mime: Mimes.text, valueBytes: valueBytesFromString('Last, replaced output') }]
|
||||
}]
|
||||
}], true, undefined, () => undefined, undefined);
|
||||
|
||||
@@ -247,7 +248,7 @@ suite('NotebookTextModel', () => {
|
||||
append: true,
|
||||
outputs: [{
|
||||
outputId: 'append1',
|
||||
outputs: [{ mime: 'text/markdown', valueBytes: valueBytesFromString('append 1') }]
|
||||
outputs: [{ mime: Mimes.markdown, valueBytes: valueBytesFromString('append 1') }]
|
||||
}]
|
||||
},
|
||||
{
|
||||
@@ -256,7 +257,7 @@ suite('NotebookTextModel', () => {
|
||||
append: true,
|
||||
outputs: [{
|
||||
outputId: 'append2',
|
||||
outputs: [{ mime: 'text/markdown', valueBytes: valueBytesFromString('append 2') }]
|
||||
outputs: [{ mime: Mimes.markdown, valueBytes: valueBytesFromString('append 2') }]
|
||||
}]
|
||||
}
|
||||
], true, undefined, () => undefined, undefined);
|
||||
@@ -584,7 +585,7 @@ suite('NotebookTextModel', () => {
|
||||
{
|
||||
editType: CellEditType.Output, handle: 0, append: true, outputs: [{
|
||||
outputId: 'newOutput',
|
||||
outputs: [{ mime: 'text/plain', valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
outputs: [{ mime: Mimes.text, valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
}]
|
||||
}
|
||||
];
|
||||
@@ -614,7 +615,7 @@ suite('NotebookTextModel', () => {
|
||||
{
|
||||
editType: CellEditType.Output, index: 2, append: true, outputs: [{
|
||||
outputId: 'newOutput',
|
||||
outputs: [{ mime: 'text/plain', valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
outputs: [{ mime: Mimes.text, valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
}]
|
||||
}
|
||||
];
|
||||
@@ -641,7 +642,7 @@ suite('NotebookTextModel', () => {
|
||||
{
|
||||
editType: CellEditType.Output, index: 1, append: true, outputs: [{
|
||||
outputId: 'newOutput',
|
||||
outputs: [{ mime: 'text/plain', valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
outputs: [{ mime: Mimes.text, valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
}]
|
||||
},
|
||||
{
|
||||
@@ -650,7 +651,7 @@ suite('NotebookTextModel', () => {
|
||||
{
|
||||
editType: CellEditType.Output, index: 1, append: true, outputs: [{
|
||||
outputId: 'newOutput2',
|
||||
outputs: [{ mime: 'text/plain', valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
outputs: [{ mime: Mimes.text, valueBytes: valueBytesFromString('cba') }, { mime: 'application/foo', valueBytes: valueBytesFromString('cba') }]
|
||||
}]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-outer-container,
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-groups-container,
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group {
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group,
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-split-pane {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -314,14 +315,21 @@
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0; /* hidden initially */
|
||||
transition: left 70ms ease-out, right 70ms ease-out, opacity 150ms ease-out;
|
||||
transition: left 70ms ease-out, right 70ms ease-out, top 70ms ease-out, bottom 70ms ease-out, opacity 150ms ease-out;
|
||||
}
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-drop-overlay.drop-left {
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.horizontal .terminal-drop-overlay.drop-before {
|
||||
right: 50%;
|
||||
}
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-drop-overlay.drop-right {
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.horizontal .terminal-drop-overlay.drop-after {
|
||||
left: 50%
|
||||
}
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.vertical .terminal-drop-overlay.drop-before {
|
||||
bottom: 50%;
|
||||
}
|
||||
.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.vertical .terminal-drop-overlay.drop-after {
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ export interface ITerminalService {
|
||||
* Moves a terminal instance's group to the target instance group's position.
|
||||
*/
|
||||
moveGroup(source: ITerminalInstance, target: ITerminalInstance): void;
|
||||
moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'left' | 'right'): void;
|
||||
moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'before' | 'after'): void;
|
||||
|
||||
/**
|
||||
* Perform an action with the active terminal instance, if the terminal does
|
||||
@@ -631,7 +631,7 @@ export interface ITerminalInstance {
|
||||
|
||||
export interface IRequestAddInstanceToGroupEvent {
|
||||
uri: URI;
|
||||
side: 'left' | 'right'
|
||||
side: 'before' | 'after'
|
||||
}
|
||||
|
||||
export const enum LinuxDistro {
|
||||
|
||||
@@ -15,10 +15,10 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
|
||||
import { EndOfLinePreference } from 'vs/editor/common/model';
|
||||
import { localize } from 'vs/nls';
|
||||
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { Action2, ICommandActionTitle, ILocalizedString, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { Action2, ICommandActionTitle, ILocalizedString, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
@@ -32,8 +32,9 @@ import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/w
|
||||
import { FindInFilesCommand, IFindInFilesArgs } from 'vs/workbench/contrib/search/browser/searchActions';
|
||||
import { Direction, IRemoteTerminalService, ITerminalInstance, ITerminalInstanceService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess';
|
||||
import { IRemoteTerminalAttachTarget, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_ACTION_CATEGORY, TerminalCommandId, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IRemoteTerminalAttachTarget, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_ACTION_CATEGORY, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import { IHistoryService } from 'vs/workbench/services/history/common/history';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
@@ -342,38 +343,10 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TerminalCommandId.Focus,
|
||||
title: { value: localize('workbench.action.terminal.focus', "Focus Terminal"), original: 'Focus Terminal' },
|
||||
title: terminalStrings.focus,
|
||||
f1: true,
|
||||
category,
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED,
|
||||
// This command is used to show instead of tabs when there is only a single terminal
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
order: 0,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID),
|
||||
ContextKeyExpr.has(`config.${TerminalSettingId.TabsEnabled}`),
|
||||
ContextKeyExpr.or(
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleTerminal'),
|
||||
ContextKeyExpr.equals('terminalCount', 1)
|
||||
),
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleTerminalOrNarrow'),
|
||||
ContextKeyExpr.or(
|
||||
ContextKeyExpr.equals('terminalCount', 1),
|
||||
ContextKeyExpr.has('isTerminalTabsNarrow')
|
||||
)
|
||||
),
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleGroup'),
|
||||
ContextKeyExpr.equals('terminalGroupCount', 1)
|
||||
),
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'always')
|
||||
)
|
||||
]),
|
||||
}
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
@@ -1339,7 +1312,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TerminalCommandId.Split,
|
||||
title: { value: localize('workbench.action.terminal.split', "Split Terminal"), original: 'Split Terminal' },
|
||||
title: terminalStrings.split,
|
||||
f1: true,
|
||||
category,
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED,
|
||||
@@ -1361,15 +1334,6 @@ export function registerTerminalActions() {
|
||||
type: 'object'
|
||||
}
|
||||
}]
|
||||
},
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
order: 2,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID),
|
||||
ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`)
|
||||
])
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1389,7 +1353,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TerminalCommandId.SplitInstance,
|
||||
title: { value: localize('workbench.action.terminal.splitInstance', "Split Terminal"), original: 'Split Terminal' },
|
||||
title: terminalStrings.split,
|
||||
f1: false,
|
||||
category,
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED,
|
||||
@@ -1423,7 +1387,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TerminalCommandId.Unsplit,
|
||||
title: { value: localize('workbench.action.terminal.unsplit', "Unsplit Terminal"), original: 'Unsplit Terminal' },
|
||||
title: terminalStrings.unsplit,
|
||||
f1: true,
|
||||
category,
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
|
||||
@@ -1438,7 +1402,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TerminalCommandId.UnsplitInstance,
|
||||
title: { value: localize('workbench.action.terminal.unsplit', "Unsplit Terminal"), original: 'Unsplit Terminal' },
|
||||
title: terminalStrings.unsplit,
|
||||
f1: true,
|
||||
category,
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
|
||||
@@ -1578,16 +1542,7 @@ export function registerTerminalActions() {
|
||||
f1: true,
|
||||
category,
|
||||
precondition: ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN),
|
||||
icon: Codicon.trash,
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
order: 3,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID),
|
||||
ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`)
|
||||
])
|
||||
}
|
||||
icon: Codicon.trash
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
@@ -1605,9 +1560,7 @@ export function registerTerminalActions() {
|
||||
constructor() {
|
||||
super({
|
||||
id: TerminalCommandId.KillInstance,
|
||||
title: {
|
||||
value: localize('workbench.action.terminal.kill.short', "Kill Terminal"), original: 'Kill Terminal'
|
||||
},
|
||||
title: terminalStrings.kill,
|
||||
f1: false,
|
||||
category,
|
||||
precondition: ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN),
|
||||
@@ -1656,10 +1609,7 @@ export function registerTerminalActions() {
|
||||
});
|
||||
}
|
||||
run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalService).doWithActiveInstance(t => {
|
||||
t.clear();
|
||||
t.focus();
|
||||
});
|
||||
accessor.get(ITerminalService).doWithActiveInstance(t => t.clear());
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
@@ -1684,15 +1634,7 @@ export function registerTerminalActions() {
|
||||
title: TerminalCommandId.CreateWithProfileButton,
|
||||
f1: false,
|
||||
category,
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED,
|
||||
menu: [{
|
||||
id: MenuId.ViewTitle,
|
||||
group: 'navigation',
|
||||
order: 0,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID)
|
||||
]),
|
||||
}]
|
||||
precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
|
||||
@@ -58,8 +58,10 @@ import { isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/plat
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { DragAndDropObserver, IDragAndDropObserverCallbacks } from 'vs/workbench/browser/dnd';
|
||||
import { containsDragType, DragAndDropObserver, IDragAndDropObserverCallbacks } from 'vs/workbench/browser/dnd';
|
||||
import { getColorClass } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
|
||||
import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||
|
||||
// How long in milliseconds should an average frame take to render for a notification to appear
|
||||
// which suggests the fallback DOM-based renderer
|
||||
@@ -832,14 +834,14 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
private _initDragAndDrop(container: HTMLElement) {
|
||||
this._dndObserver?.dispose();
|
||||
const dndController = new TerminalInstanceDragAndDropController(container);
|
||||
const dndController = this._instantiationService.createInstance(TerminalInstanceDragAndDropController, container);
|
||||
dndController.onDropTerminal(e => this._onRequestAddInstanceToGroup.fire(e));
|
||||
dndController.onDropFile(async path => {
|
||||
const preparedPath = await this._terminalInstanceService.preparePathForTerminalAsync(path, this.shellLaunchConfig.executable, this.title, this.shellType, this.isRemote);
|
||||
this.sendText(preparedPath, false);
|
||||
this.focus();
|
||||
});
|
||||
this._dndObserver = new DragAndDropObserver(container.parentElement!, dndController);
|
||||
this._dndObserver = new DragAndDropObserver(container, dndController);
|
||||
}
|
||||
|
||||
private async _measureRenderTime(): Promise<void> {
|
||||
@@ -1936,7 +1938,9 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA
|
||||
get onDropTerminal(): Event<IRequestAddInstanceToGroupEvent> { return this._onDropTerminal.event; }
|
||||
|
||||
constructor(
|
||||
private readonly _container: HTMLElement
|
||||
private readonly _container: HTMLElement,
|
||||
@IWorkbenchLayoutService private readonly _layoutService: IWorkbenchLayoutService,
|
||||
@IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService,
|
||||
) {
|
||||
super();
|
||||
this._register(toDisposable(() => this._clearDropOverlay()));
|
||||
@@ -1950,6 +1954,10 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA
|
||||
}
|
||||
|
||||
onDragEnter(e: DragEvent) {
|
||||
if (!containsDragType(e, DataTransfers.FILES, DataTransfers.RESOURCES, 'terminals')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._dropOverlay) {
|
||||
this._dropOverlay = document.createElement('div');
|
||||
this._dropOverlay.classList.add('terminal-drop-overlay');
|
||||
@@ -1960,8 +1968,8 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA
|
||||
// Dragging terminals
|
||||
if (types.includes('terminals')) {
|
||||
const side = this._getDropSide(e);
|
||||
this._dropOverlay.classList.toggle('drop-left', side === 'left');
|
||||
this._dropOverlay.classList.toggle('drop-right', side === 'right');
|
||||
this._dropOverlay.classList.toggle('drop-before', side === 'before');
|
||||
this._dropOverlay.classList.toggle('drop-after', side === 'after');
|
||||
}
|
||||
|
||||
if (!this._dropOverlay.parentElement) {
|
||||
@@ -1986,8 +1994,8 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA
|
||||
// Dragging terminals
|
||||
if (types.includes('terminals')) {
|
||||
const side = this._getDropSide(e);
|
||||
this._dropOverlay.classList.toggle('drop-left', side === 'left');
|
||||
this._dropOverlay.classList.toggle('drop-right', side === 'right');
|
||||
this._dropOverlay.classList.toggle('drop-before', side === 'before');
|
||||
this._dropOverlay.classList.toggle('drop-after', side === 'after');
|
||||
}
|
||||
|
||||
this._dropOverlay.style.opacity = '1';
|
||||
@@ -2026,13 +2034,24 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA
|
||||
this._onDropFile.fire(path);
|
||||
}
|
||||
|
||||
private _getDropSide(e: DragEvent): 'left' | 'right' {
|
||||
private _getDropSide(e: DragEvent): 'before' | 'after' {
|
||||
const target = this._container;
|
||||
if (!target) {
|
||||
return 'right';
|
||||
return 'after';
|
||||
}
|
||||
|
||||
const rect = target.getBoundingClientRect();
|
||||
return e.clientX - rect.left < rect.width / 2 ? 'left' : 'right';
|
||||
return this._getViewOrientation() === Orientation.HORIZONTAL
|
||||
? (e.clientX - rect.left < rect.width / 2 ? 'before' : 'after')
|
||||
: (e.clientY - rect.top < rect.height / 2 ? 'before' : 'after');
|
||||
}
|
||||
|
||||
private _getViewOrientation(): Orientation {
|
||||
const panelPosition = this._layoutService.getPanelPosition();
|
||||
const terminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID);
|
||||
return terminalLocation === ViewContainerLocation.Panel && panelPosition === Position.BOTTOM
|
||||
? Orientation.HORIZONTAL
|
||||
: Orientation.VERTICAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { localize } from 'vs/nls';
|
||||
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
import { IS_SPLIT_TERMINAL_CONTEXT_KEY, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, TerminalCommandId, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
|
||||
const enum ContextMenuGroup {
|
||||
Create = '1_create',
|
||||
@@ -34,7 +36,8 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.MenubarTerminalMenu, item: {
|
||||
id: MenuId.MenubarTerminalMenu,
|
||||
item: {
|
||||
group: TerminalMenuBarGroup.Create,
|
||||
command: {
|
||||
id: TerminalCommandId.New,
|
||||
@@ -44,7 +47,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.MenubarTerminalMenu, item: {
|
||||
id: MenuId.MenubarTerminalMenu,
|
||||
item: {
|
||||
group: TerminalMenuBarGroup.Create,
|
||||
command: {
|
||||
id: TerminalCommandId.Split,
|
||||
@@ -56,7 +60,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.MenubarTerminalMenu, item: {
|
||||
id: MenuId.MenubarTerminalMenu,
|
||||
item: {
|
||||
group: TerminalMenuBarGroup.Run,
|
||||
command: {
|
||||
id: TerminalCommandId.RunActiveFile,
|
||||
@@ -67,7 +72,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.MenubarTerminalMenu, item: {
|
||||
id: MenuId.MenubarTerminalMenu,
|
||||
item: {
|
||||
group: TerminalMenuBarGroup.Run,
|
||||
command: {
|
||||
id: TerminalCommandId.RunSelectedText,
|
||||
@@ -83,16 +89,18 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
group: ContextMenuGroup.Create,
|
||||
command: {
|
||||
id: TerminalCommandId.Split,
|
||||
title: localize('workbench.action.terminal.split', "Split Terminal")
|
||||
title: terminalStrings.split.value
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.New,
|
||||
title: localize('workbench.action.terminal.new.short', "New Terminal")
|
||||
@@ -101,16 +109,18 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Kill,
|
||||
title: localize('workbench.action.terminal.kill.short', "Kill Terminal")
|
||||
title: terminalStrings.kill.value
|
||||
},
|
||||
group: ContextMenuGroup.Kill
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.CopySelection,
|
||||
title: localize('workbench.action.terminal.copySelection.short', "Copy")
|
||||
@@ -120,7 +130,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Paste,
|
||||
title: localize('workbench.action.terminal.paste.short', "Paste")
|
||||
@@ -130,7 +141,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Clear,
|
||||
title: localize('workbench.action.terminal.clear', "Clear")
|
||||
@@ -139,7 +151,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.ShowTabs,
|
||||
title: localize('workbench.action.terminal.showsTabs', "Show Tabs")
|
||||
@@ -149,7 +162,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInstanceContext, item: {
|
||||
id: MenuId.TerminalInstanceContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.SelectAll,
|
||||
title: localize('workbench.action.terminal.selectAll', "Select All"),
|
||||
@@ -164,7 +178,8 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.TerminalTabEmptyAreaContext, item: {
|
||||
id: MenuId.TerminalTabEmptyAreaContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.NewWithProfile,
|
||||
title: localize('workbench.action.terminal.newWithProfile.short', "New Terminal With Profile")
|
||||
@@ -173,7 +188,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabEmptyAreaContext, item: {
|
||||
id: MenuId.TerminalTabEmptyAreaContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.New,
|
||||
title: localize('workbench.action.terminal.new.short', "New Terminal")
|
||||
@@ -187,7 +203,8 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.TerminalNewDropdownContext, item: {
|
||||
id: MenuId.TerminalNewDropdownContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.SelectDefaultProfile,
|
||||
title: { value: localize('workbench.action.terminal.selectDefaultProfile', "Select Default Profile"), original: 'Select Default Profile' }
|
||||
@@ -196,7 +213,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalNewDropdownContext, item: {
|
||||
id: MenuId.TerminalNewDropdownContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.ConfigureTerminalSettings,
|
||||
title: localize('workbench.action.terminal.openSettings', "Configure Terminal Settings")
|
||||
@@ -210,7 +228,8 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.ViewTitle, item: {
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.SwitchTerminal,
|
||||
title: { value: localize('workbench.action.terminal.switchTerminal', "Switch Terminal"), original: 'Switch Terminal' }
|
||||
@@ -222,6 +241,86 @@ export function setupTerminalMenus(): void {
|
||||
ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`)
|
||||
]),
|
||||
}
|
||||
},
|
||||
{
|
||||
// This is used to show instead of tabs when there is only a single terminal
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Focus,
|
||||
title: terminalStrings.focus
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 0,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID),
|
||||
ContextKeyExpr.has(`config.${TerminalSettingId.TabsEnabled}`),
|
||||
ContextKeyExpr.or(
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleTerminal'),
|
||||
ContextKeyExpr.equals('terminalCount', 1)
|
||||
),
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleTerminalOrNarrow'),
|
||||
ContextKeyExpr.or(
|
||||
ContextKeyExpr.equals('terminalCount', 1),
|
||||
ContextKeyExpr.has('isTerminalTabsNarrow')
|
||||
)
|
||||
),
|
||||
ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleGroup'),
|
||||
ContextKeyExpr.equals('terminalGroupCount', 1)
|
||||
),
|
||||
ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'always')
|
||||
)
|
||||
]),
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Split,
|
||||
title: terminalStrings.split,
|
||||
icon: Codicon.splitHorizontal
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 2,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID),
|
||||
ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`)
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Kill,
|
||||
title: terminalStrings.kill,
|
||||
icon: Codicon.trash
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 3,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID),
|
||||
ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`)
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.CreateWithProfileButton,
|
||||
title: TerminalCommandId.CreateWithProfileButton
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 0,
|
||||
when: ContextKeyAndExpr.create([
|
||||
ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID)
|
||||
])
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
@@ -229,16 +328,18 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.TerminalInlineTabContext, item: {
|
||||
id: MenuId.TerminalInlineTabContext,
|
||||
item: {
|
||||
group: ContextMenuGroup.Create,
|
||||
command: {
|
||||
id: TerminalCommandId.Split,
|
||||
title: localize('workbench.action.terminal.split', "Split Terminal")
|
||||
title: terminalStrings.split.value
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInlineTabContext, item: {
|
||||
id: MenuId.TerminalInlineTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.ChangeIcon,
|
||||
title: localize('workbench.action.terminal.changeIcon', "Change Icon...")
|
||||
@@ -248,7 +349,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInlineTabContext, item: {
|
||||
id: MenuId.TerminalInlineTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.ChangeColor,
|
||||
title: localize('workbench.action.terminal.changeColor', "Change Color...")
|
||||
@@ -258,7 +360,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInlineTabContext, item: {
|
||||
id: MenuId.TerminalInlineTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Rename,
|
||||
title: localize('workbench.action.terminal.rename', "Rename...")
|
||||
@@ -267,10 +370,11 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalInlineTabContext, item: {
|
||||
id: MenuId.TerminalInlineTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Kill,
|
||||
title: localize('workbench.action.terminal.kill.short', "Kill Terminal")
|
||||
title: terminalStrings.kill.value
|
||||
},
|
||||
group: ContextMenuGroup.Kill
|
||||
}
|
||||
@@ -281,16 +385,18 @@ export function setupTerminalMenus(): void {
|
||||
MenuRegistry.appendMenuItems(
|
||||
[
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.SplitInstance,
|
||||
title: localize('workbench.action.terminal.splitInstance', "Split Terminal"),
|
||||
title: terminalStrings.split.value,
|
||||
},
|
||||
group: ContextMenuGroup.Create
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.RenameInstance,
|
||||
title: localize('workbench.action.terminal.renameInstance', "Rename...")
|
||||
@@ -299,7 +405,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.ChangeIconInstance,
|
||||
title: localize('workbench.action.terminal.changeIcon', "Change Icon...")
|
||||
@@ -308,7 +415,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.ChangeColorInstance,
|
||||
title: localize('workbench.action.terminal.changeColor', "Change Color...")
|
||||
@@ -317,7 +425,8 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
group: ContextMenuGroup.Config,
|
||||
command: {
|
||||
id: TerminalCommandId.JoinInstance,
|
||||
@@ -327,20 +436,22 @@ export function setupTerminalMenus(): void {
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
group: ContextMenuGroup.Config,
|
||||
command: {
|
||||
id: TerminalCommandId.UnsplitInstance,
|
||||
title: localize('workbench.action.terminal.unsplitInstance', "Unsplit Terminal")
|
||||
title: terminalStrings.unsplit.value
|
||||
},
|
||||
when: ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, IS_SPLIT_TERMINAL_CONTEXT_KEY)
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.TerminalTabContext, item: {
|
||||
id: MenuId.TerminalTabContext,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.KillInstance,
|
||||
title: localize('workbench.action.terminal.killInstance', "Kill Terminal")
|
||||
title: terminalStrings.kill.value
|
||||
},
|
||||
group: ContextMenuGroup.Kill,
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal
|
||||
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { killTerminalIcon, renameTerminalIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons';
|
||||
import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
|
||||
export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPickerQuickAccessItem> {
|
||||
|
||||
@@ -57,7 +58,7 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider<IPick
|
||||
},
|
||||
{
|
||||
iconClass: ThemeIcon.asClassName(killTerminalIcon),
|
||||
tooltip: localize('killTerminal', "Kill Terminal Instance")
|
||||
tooltip: terminalStrings.kill.value
|
||||
}
|
||||
],
|
||||
iconClasses,
|
||||
|
||||
@@ -63,7 +63,7 @@ export class TerminalService implements ITerminalService {
|
||||
private _linkProviderDisposables: Map<ITerminalExternalLinkProvider, IDisposable[]> = new Map();
|
||||
private _processSupportContextKey: IContextKey<boolean>;
|
||||
private readonly _localTerminalService?: ILocalTerminalService;
|
||||
private readonly _offProcessTerminalService?: IOffProcessTerminalService;
|
||||
private readonly _primaryOffProcessTerminalService?: IOffProcessTerminalService;
|
||||
private _profilesReadyBarrier: AutoOpenBarrier;
|
||||
private _availableProfiles: ITerminalProfile[] | undefined;
|
||||
private _configHelper: TerminalConfigHelper;
|
||||
@@ -210,7 +210,7 @@ export class TerminalService implements ITerminalService {
|
||||
: enableTerminalReconnection
|
||||
? this._localTerminalsInitPromise = this._reconnectToLocalTerminals()
|
||||
: Promise.resolve();
|
||||
this._offProcessTerminalService = !!this._environmentService.remoteAuthority ? this._remoteTerminalService : this._localTerminalService;
|
||||
this._primaryOffProcessTerminalService = !!this._environmentService.remoteAuthority ? this._remoteTerminalService : this._localTerminalService;
|
||||
initPromise.then(() => this._setConnected());
|
||||
|
||||
// Wait up to 5 seconds for profiles to be ready so it's assured that we know the actual
|
||||
@@ -376,12 +376,11 @@ export class TerminalService implements ITerminalService {
|
||||
}
|
||||
|
||||
private async _detectProfiles(includeDetectedProfiles?: boolean): Promise<ITerminalProfile[]> {
|
||||
const offProcService = this._offProcessTerminalService;
|
||||
if (!offProcService) {
|
||||
if (!this._primaryOffProcessTerminalService) {
|
||||
return this._availableProfiles || [];
|
||||
}
|
||||
const platform = await this._getPlatformKey();
|
||||
return offProcService?.getProfiles(this._configurationService.getValue(`${TerminalSettingPrefix.Profiles}${platform}`), this._configurationService.getValue(`${TerminalSettingPrefix.DefaultProfile}${platform}`), includeDetectedProfiles);
|
||||
return this._primaryOffProcessTerminalService?.getProfiles(this._configurationService.getValue(`${TerminalSettingPrefix.Profiles}${platform}`), this._configurationService.getValue(`${TerminalSettingPrefix.DefaultProfile}${platform}`), includeDetectedProfiles);
|
||||
}
|
||||
|
||||
private _onBeforeShutdown(reason: ShutdownReason): boolean | Promise<boolean> {
|
||||
@@ -441,7 +440,7 @@ export class TerminalService implements ITerminalService {
|
||||
const state: ITerminalsLayoutInfoById = {
|
||||
tabs: this.terminalGroups.map(g => g.getLayoutInfo(g === this.getActiveGroup()))
|
||||
};
|
||||
this._offProcessTerminalService?.setTerminalLayoutInfo(state);
|
||||
this._primaryOffProcessTerminalService?.setTerminalLayoutInfo(state);
|
||||
}
|
||||
|
||||
@debounce(500)
|
||||
@@ -449,7 +448,7 @@ export class TerminalService implements ITerminalService {
|
||||
if (!this.configHelper.config.enablePersistentSessions || !instance || !instance.persistentProcessId || !instance.title) {
|
||||
return;
|
||||
}
|
||||
this._offProcessTerminalService?.updateTitle(instance.persistentProcessId, instance.title, instance.titleSource);
|
||||
this._primaryOffProcessTerminalService?.updateTitle(instance.persistentProcessId, instance.title, instance.titleSource);
|
||||
}
|
||||
|
||||
@debounce(500)
|
||||
@@ -457,7 +456,7 @@ export class TerminalService implements ITerminalService {
|
||||
if (!this.configHelper.config.enablePersistentSessions || !instance || !instance.persistentProcessId || !instance.icon) {
|
||||
return;
|
||||
}
|
||||
this._offProcessTerminalService?.updateIcon(instance.persistentProcessId, instance.icon, instance.color);
|
||||
this._primaryOffProcessTerminalService?.updateIcon(instance.persistentProcessId, instance.icon, instance.color);
|
||||
}
|
||||
|
||||
private _removeGroup(group: ITerminalGroup): void {
|
||||
@@ -743,7 +742,7 @@ export class TerminalService implements ITerminalService {
|
||||
this._onInstancesChanged.fire();
|
||||
}
|
||||
|
||||
moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'left' | 'right'): void {
|
||||
moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'before' | 'after'): void {
|
||||
const sourceGroup = this.getGroupForInstance(source);
|
||||
const targetGroup = this.getGroupForInstance(target);
|
||||
if (!sourceGroup || !targetGroup) {
|
||||
@@ -758,7 +757,7 @@ export class TerminalService implements ITerminalService {
|
||||
}
|
||||
|
||||
// Rearrange within the target group
|
||||
const index = targetGroup.terminalInstances.indexOf(target) + (side === 'right' ? 1 : 0);
|
||||
const index = targetGroup.terminalInstances.indexOf(target) + (side === 'after' ? 1 : 0);
|
||||
targetGroup.moveInstance(source, index);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from
|
||||
import { IListDragAndDrop, IListDragOverReaction, IListRenderer, ListDragOverEffect } from 'vs/base/browser/ui/list/list';
|
||||
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { disposableTimeout } from 'vs/base/common/async';
|
||||
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
|
||||
import { ElementsDragAndDropData, NativeDragAndDropData } from 'vs/base/browser/ui/list/listView';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -41,6 +41,8 @@ import { once } from 'vs/base/common/functional';
|
||||
import { attachInputBoxStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { containsDragType } from 'vs/workbench/browser/dnd';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -436,10 +438,10 @@ class TerminalTabsRenderer implements IListRenderer<ITerminalInstance, ITerminal
|
||||
fillActionBar(instance: ITerminalInstance, template: ITerminalTabEntryTemplate): void {
|
||||
// If the instance is within the selection, split all selected
|
||||
const actions = [
|
||||
new Action(TerminalCommandId.SplitInstance, localize('terminal.split', "Split"), ThemeIcon.asClassName(Codicon.splitHorizontal), true, async () => {
|
||||
new Action(TerminalCommandId.SplitInstance, terminalStrings.split.short, ThemeIcon.asClassName(Codicon.splitHorizontal), true, async () => {
|
||||
this._runForSelectionOrInstance(instance, e => this._terminalService.splitInstance(e));
|
||||
}),
|
||||
new Action(TerminalCommandId.KillInstance, localize('terminal.kill', "Kill"), ThemeIcon.asClassName(Codicon.trashcan), true, async () => {
|
||||
new Action(TerminalCommandId.KillInstance, terminalStrings.kill.short, ThemeIcon.asClassName(Codicon.trashcan), true, async () => {
|
||||
this._runForSelectionOrInstance(instance, e => e.dispose());
|
||||
})
|
||||
];
|
||||
@@ -547,7 +549,11 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
|
||||
}
|
||||
|
||||
onDragOver(data: IDragAndDropData, targetInstance: ITerminalInstance | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | IListDragOverReaction {
|
||||
let result = true;
|
||||
if (data instanceof NativeDragAndDropData) {
|
||||
if (!containsDragType(originalEvent, DataTransfers.FILES, DataTransfers.RESOURCES)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const didChangeAutoFocusInstance = this._autoFocusInstance !== targetInstance;
|
||||
if (didChangeAutoFocusInstance) {
|
||||
@@ -556,7 +562,7 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
|
||||
}
|
||||
|
||||
if (!targetInstance) {
|
||||
return result;
|
||||
return data instanceof ElementsDragAndDropData;
|
||||
}
|
||||
|
||||
if (didChangeAutoFocusInstance) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import { dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ColorScheme } from 'vs/platform/theme/common/theme';
|
||||
import { getColorClass, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
|
||||
export class TerminalViewPane extends ViewPane {
|
||||
private _actions: IAction[] | undefined;
|
||||
@@ -257,7 +258,7 @@ export class TerminalViewPane extends ViewPane {
|
||||
},
|
||||
{
|
||||
id: TerminalCommandId.Split,
|
||||
title: nls.localize('terminal.split', "Split Terminal"),
|
||||
title: terminalStrings.split.value,
|
||||
icon: Codicon.splitHorizontal
|
||||
},
|
||||
undefined);
|
||||
@@ -385,7 +386,7 @@ class SingleTerminalTabActionViewItem extends MenuEntryActionViewItem {
|
||||
},
|
||||
{
|
||||
id: TerminalCommandId.Split,
|
||||
title: nls.localize('workbench.action.terminal.split', "Split Terminal"),
|
||||
title: terminalStrings.split.value,
|
||||
icon: Codicon.splitHorizontal
|
||||
},
|
||||
undefined,
|
||||
|
||||
@@ -248,7 +248,12 @@ const terminalConfiguration: IConfigurationNode = {
|
||||
default: false
|
||||
},
|
||||
[TerminalSettingId.CommandsToSkipShell]: {
|
||||
markdownDescription: localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell but instead always be handled by VS Code. This allows keybindings that would normally be consumed by the shell to act instead the same as when the terminal is not focused, for example `Ctrl+P` to launch Quick Open.\n\n \n\nMany commands are skipped by default. To override a default and pass that command's keybinding to the shell instead, add the command prefixed with the `-` character. For example add `-workbench.action.quickOpen` to allow `Ctrl+P` to reach the shell.\n\n \n\nThe following list of default skipped commands is truncated when viewed in Settings Editor. To see the full list, [open the default settings JSON](command:workbench.action.openRawDefaultSettings 'Open Default Settings (JSON)') and search for the first command from the list below.\n\n \n\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')),
|
||||
markdownDescription: localize(
|
||||
'terminal.integrated.commandsToSkipShell',
|
||||
"A set of command IDs whose keybindings will not be sent to the shell but instead always be handled by VS Code. This allows keybindings that would normally be consumed by the shell to act instead the same as when the terminal is not focused, for example `Ctrl+P` to launch Quick Open.\n\n \n\nMany commands are skipped by default. To override a default and pass that command's keybinding to the shell instead, add the command prefixed with the `-` character. For example add `-workbench.action.quickOpen` to allow `Ctrl+P` to reach the shell.\n\n \n\nThe following list of default skipped commands is truncated when viewed in Settings Editor. To see the full list, {1} and search for the first command from the list below.\n\n \n\nDefault Skipped Commands:\n\n{0}",
|
||||
DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n'),
|
||||
`[${localize('openDefaultSettingsJson', "open the default settings JSON")}](command:workbench.action.openRawDefaultSettings '${localize('openDefaultSettingsJson.capitalized', "Open Default Settings (JSON)")}')`
|
||||
),
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string'
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
/**
|
||||
* Formats a message from the product to be written to the terminal.
|
||||
*/
|
||||
@@ -10,3 +12,27 @@ export function formatMessageForTerminal(message: string, excludeLeadingNewLine:
|
||||
// Wrap in bold and ensure it's on a new line
|
||||
return `${excludeLeadingNewLine ? '' : '\r\n'}\x1b[1m${message}\x1b[0m\n\r`;
|
||||
}
|
||||
|
||||
/**
|
||||
* An object holding strings shared by multiple parts of the terminal
|
||||
*/
|
||||
export const terminalStrings = {
|
||||
focus: {
|
||||
value: localize('workbench.action.terminal.focus', "Focus Terminal"),
|
||||
original: 'Focus Terminal'
|
||||
},
|
||||
kill: {
|
||||
value: localize('killTerminal', "Kill Terminal"),
|
||||
original: 'Kill Terminal',
|
||||
short: localize('killTerminal.short', "Kill"),
|
||||
},
|
||||
split: {
|
||||
value: localize('splitTerminal', "Split Terminal"),
|
||||
original: 'Split Terminal',
|
||||
short: localize('splitTerminal.short', "Split"),
|
||||
},
|
||||
unsplit: {
|
||||
value: localize('unsplitTerminal', "Unsplit Terminal"),
|
||||
original: 'Unsplit Terminal'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action2, IAction2Options, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyFalseExpr, ContextKeyTrueExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyFalseExpr, ContextKeyGreaterExpr, ContextKeyTrueExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
@@ -59,13 +59,14 @@ const enum ActionOrder {
|
||||
Refresh,
|
||||
}
|
||||
|
||||
const hasAnyTestProvider = ContextKeyGreaterExpr.create(TestingContextKeys.providerCount.key, 0);
|
||||
|
||||
export class HideTestAction extends Action2 {
|
||||
public static readonly ID = 'testing.hideTest';
|
||||
constructor() {
|
||||
super({
|
||||
id: HideTestAction.ID,
|
||||
title: localize('hideTest', 'Hide Test'),
|
||||
f1: false,
|
||||
menu: {
|
||||
id: MenuId.TestItem,
|
||||
when: TestingContextKeys.testItemIsHidden.isEqualTo(false)
|
||||
@@ -90,7 +91,6 @@ export class UnhideTestAction extends Action2 {
|
||||
super({
|
||||
id: UnhideTestAction.ID,
|
||||
title: localize('unhideTest', 'Unhide Test'),
|
||||
f1: false,
|
||||
menu: {
|
||||
id: MenuId.TestItem,
|
||||
when: TestingContextKeys.testItemIsHidden.isEqualTo(true)
|
||||
@@ -116,7 +116,6 @@ export class DebugAction extends Action2 {
|
||||
id: DebugAction.ID,
|
||||
title: localize('debug test', 'Debug Test'),
|
||||
icon: icons.testingDebugIcon,
|
||||
f1: false,
|
||||
menu: {
|
||||
id: MenuId.TestItem,
|
||||
group: 'inline',
|
||||
@@ -142,7 +141,6 @@ export class RunAction extends Action2 {
|
||||
id: RunAction.ID,
|
||||
title: localize('run test', 'Run Test'),
|
||||
icon: icons.testingRunIcon,
|
||||
f1: false,
|
||||
menu: {
|
||||
id: MenuId.TestItem,
|
||||
group: 'inline',
|
||||
@@ -268,10 +266,9 @@ abstract class RunOrDebugAllAllAction extends Action2 {
|
||||
id,
|
||||
title,
|
||||
icon,
|
||||
f1: true,
|
||||
category,
|
||||
keybinding,
|
||||
menu: {
|
||||
menu: [{
|
||||
id: MenuId.ViewTitle,
|
||||
order: debug ? ActionOrder.Debug : ActionOrder.Run,
|
||||
group: 'navigation',
|
||||
@@ -282,7 +279,10 @@ abstract class RunOrDebugAllAllAction extends Action2 {
|
||||
? TestingContextKeys.hasDebuggableTests.isEqualTo(true)
|
||||
: TestingContextKeys.hasRunnableTests.isEqualTo(true),
|
||||
])
|
||||
}
|
||||
}, {
|
||||
id: MenuId.CommandPalette,
|
||||
when: hasAnyTestProvider,
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -394,7 +394,6 @@ export class TestingViewAsListAction extends ViewAction<TestingExplorerView> {
|
||||
id: TestingViewAsListAction.ID,
|
||||
viewId: Testing.ExplorerViewId,
|
||||
title: localize('testing.viewAsList', "View as List"),
|
||||
f1: false,
|
||||
toggled: TestingContextKeys.viewMode.isEqualTo(TestExplorerViewMode.List),
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
@@ -420,7 +419,6 @@ export class TestingViewAsTreeAction extends ViewAction<TestingExplorerView> {
|
||||
id: TestingViewAsTreeAction.ID,
|
||||
viewId: Testing.ExplorerViewId,
|
||||
title: localize('testing.viewAsTree', "View as Tree"),
|
||||
f1: false,
|
||||
toggled: TestingContextKeys.viewMode.isEqualTo(TestExplorerViewMode.Tree),
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
@@ -447,7 +445,6 @@ export class TestingSortByNameAction extends ViewAction<TestingExplorerView> {
|
||||
id: TestingSortByNameAction.ID,
|
||||
viewId: Testing.ExplorerViewId,
|
||||
title: localize('testing.sortByName', "Sort by Name"),
|
||||
f1: false,
|
||||
toggled: TestingContextKeys.viewSorting.isEqualTo(TestExplorerViewSorting.ByName),
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
@@ -473,7 +470,6 @@ export class TestingSortByLocationAction extends ViewAction<TestingExplorerView>
|
||||
id: TestingSortByLocationAction.ID,
|
||||
viewId: Testing.ExplorerViewId,
|
||||
title: localize('testing.sortByLocation', "Sort by Location"),
|
||||
f1: false,
|
||||
toggled: TestingContextKeys.viewSorting.isEqualTo(TestExplorerViewSorting.ByLocation),
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
@@ -498,19 +494,22 @@ export class ShowMostRecentOutputAction extends Action2 {
|
||||
super({
|
||||
id: ShowMostRecentOutputAction.ID,
|
||||
title: localize('testing.showMostRecentOutput', "Show Output"),
|
||||
f1: true,
|
||||
category,
|
||||
icon: Codicon.terminal,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyMod.CtrlCmd | KeyCode.KEY_O),
|
||||
},
|
||||
menu: {
|
||||
precondition: TestingContextKeys.hasAnyResults.isEqualTo(true),
|
||||
menu: [{
|
||||
id: MenuId.ViewTitle,
|
||||
order: ActionOrder.Collapse,
|
||||
group: 'navigation',
|
||||
when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId)
|
||||
}
|
||||
when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId),
|
||||
}, {
|
||||
id: MenuId.CommandPalette,
|
||||
when: TestingContextKeys.hasAnyResults.isEqualTo(true)
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -527,7 +526,6 @@ export class CollapseAllAction extends ViewAction<TestingExplorerView> {
|
||||
id: CollapseAllAction.ID,
|
||||
viewId: Testing.ExplorerViewId,
|
||||
title: localize('testing.collapseAll', "Collapse All Tests"),
|
||||
f1: false,
|
||||
icon: Codicon.collapseAll,
|
||||
menu: {
|
||||
id: MenuId.ViewTitle,
|
||||
@@ -553,13 +551,15 @@ export class RefreshTestsAction extends Action2 {
|
||||
id: RefreshTestsAction.ID,
|
||||
title: localize('testing.refresh', "Refresh Tests"),
|
||||
category,
|
||||
f1: true,
|
||||
menu: {
|
||||
menu: [{
|
||||
id: MenuId.ViewTitle,
|
||||
order: ActionOrder.Refresh,
|
||||
group: 'refresh',
|
||||
when: ContextKeyEqualsExpr.create('view', Testing.ExplorerViewId)
|
||||
}
|
||||
}, {
|
||||
id: MenuId.CommandPalette,
|
||||
when: TestingContextKeys.providerCount.isEqualTo(true),
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -578,11 +578,13 @@ export class ClearTestResultsAction extends Action2 {
|
||||
id: ClearTestResultsAction.ID,
|
||||
title: localize('testing.clearResults', "Clear All Results"),
|
||||
category,
|
||||
f1: true,
|
||||
icon: Codicon.trash,
|
||||
menu: {
|
||||
menu: [{
|
||||
id: MenuId.TestPeekTitle,
|
||||
},
|
||||
}, {
|
||||
id: MenuId.CommandPalette,
|
||||
when: TestingContextKeys.hasAnyResults.isEqualTo(true),
|
||||
},],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -600,7 +602,6 @@ export class GoToTest extends Action2 {
|
||||
super({
|
||||
id: GoToTest.ID,
|
||||
title: localize('testing.editFocusedTest', "Go to Test"),
|
||||
f1: false,
|
||||
menu: {
|
||||
id: MenuId.TestItem,
|
||||
when: TestingContextKeys.testItemHasUri.isEqualTo(true),
|
||||
@@ -709,7 +710,6 @@ abstract class ToggleAutoRun extends Action2 {
|
||||
super({
|
||||
id: ToggleAutoRun.ID,
|
||||
title,
|
||||
f1: true,
|
||||
icon: icons.testingAutorunIcon,
|
||||
toggled: whenToggleIs === true ? ContextKeyTrueExpr.INSTANCE : ContextKeyFalseExpr.INSTANCE,
|
||||
menu: {
|
||||
@@ -746,6 +746,16 @@ export class AutoRunOffAction extends ToggleAutoRun {
|
||||
|
||||
|
||||
abstract class RunOrDebugAtCursor extends Action2 {
|
||||
constructor(options: IAction2Options) {
|
||||
super({
|
||||
...options,
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: hasAnyTestProvider,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -801,7 +811,6 @@ export class RunAtCursor extends RunOrDebugAtCursor {
|
||||
super({
|
||||
id: RunAtCursor.ID,
|
||||
title: localize('testing.runAtCursor', "Run Test at Cursor"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -829,7 +838,6 @@ export class DebugAtCursor extends RunOrDebugAtCursor {
|
||||
super({
|
||||
id: DebugAtCursor.ID,
|
||||
title: localize('testing.debugAtCursor', "Debug Test at Cursor"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -852,6 +860,16 @@ export class DebugAtCursor extends RunOrDebugAtCursor {
|
||||
}
|
||||
|
||||
abstract class RunOrDebugCurrentFile extends Action2 {
|
||||
constructor(options: IAction2Options) {
|
||||
super({
|
||||
...options,
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: hasAnyTestProvider,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -893,13 +911,16 @@ export class RunCurrentFile extends RunOrDebugCurrentFile {
|
||||
super({
|
||||
id: RunCurrentFile.ID,
|
||||
title: localize('testing.runCurrentFile', "Run Tests in Current File"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: EditorContextKeys.editorTextFocus,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_F),
|
||||
},
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: hasAnyTestProvider,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -921,7 +942,6 @@ export class DebugCurrentFile extends RunOrDebugCurrentFile {
|
||||
super({
|
||||
id: DebugCurrentFile.ID,
|
||||
title: localize('testing.debugCurrentFile', "Debug Tests in Current File"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -984,6 +1004,15 @@ abstract class RunOrDebugExtsByPath extends Action2 {
|
||||
}
|
||||
|
||||
abstract class RunOrDebugFailedTests extends RunOrDebugExtsByPath {
|
||||
constructor(options: IAction2Options) {
|
||||
super({
|
||||
...options,
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: hasAnyTestProvider,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@@ -1008,6 +1037,19 @@ abstract class RunOrDebugFailedTests extends RunOrDebugExtsByPath {
|
||||
}
|
||||
|
||||
abstract class RunOrDebugLastRun extends RunOrDebugExtsByPath {
|
||||
constructor(options: IAction2Options) {
|
||||
super({
|
||||
...options,
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: ContextKeyAndExpr.create([
|
||||
hasAnyTestProvider,
|
||||
TestingContextKeys.hasAnyResults.isEqualTo(true),
|
||||
]),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@@ -1032,7 +1074,6 @@ export class ReRunFailedTests extends RunOrDebugFailedTests {
|
||||
super({
|
||||
id: ReRunFailedTests.ID,
|
||||
title: localize('testing.reRunFailTests', "Rerun Failed Tests"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -1059,7 +1100,6 @@ export class DebugFailedTests extends RunOrDebugFailedTests {
|
||||
super({
|
||||
id: DebugFailedTests.ID,
|
||||
title: localize('testing.debugFailTests', "Debug Failed Tests"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -1086,7 +1126,6 @@ export class ReRunLastRun extends RunOrDebugLastRun {
|
||||
super({
|
||||
id: ReRunLastRun.ID,
|
||||
title: localize('testing.reRunLastRun', "Rerun Last Run"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -1113,7 +1152,6 @@ export class DebugLastRun extends RunOrDebugLastRun {
|
||||
super({
|
||||
id: DebugLastRun.ID,
|
||||
title: localize('testing.debugLastRun', "Debug Last Run"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
@@ -1140,7 +1178,6 @@ export class SearchForTestExtension extends Action2 {
|
||||
super({
|
||||
id: SearchForTestExtension.ID,
|
||||
title: localize('testing.searchForTestExtension', "Search for Test Extension"),
|
||||
f1: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1158,12 +1195,15 @@ export class OpenOutputPeek extends Action2 {
|
||||
super({
|
||||
id: OpenOutputPeek.ID,
|
||||
title: localize('testing.openOutputPeek', "Peek Output"),
|
||||
f1: true,
|
||||
category,
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.US_SEMICOLON, KeyCode.KEY_M),
|
||||
},
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: TestingContextKeys.hasAnyResults.isEqualTo(true),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/t
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { IMainThreadTestCollection, ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
||||
function isInDiffEditor(codeEditorService: ICodeEditorService, codeEditor: ICodeEditor): boolean {
|
||||
function isOriginalInDiffEditor(codeEditorService: ICodeEditorService, codeEditor: ICodeEditor): boolean {
|
||||
const diffEditors = codeEditorService.listDiffEditors();
|
||||
|
||||
for (const diffEditor of diffEditors) {
|
||||
if (diffEditor.getModifiedEditor() === codeEditor || diffEditor.getOriginalEditor() === codeEditor) {
|
||||
if (diffEditor.getOriginalEditor() === codeEditor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -130,7 +130,7 @@ export class TestingDecorations extends Disposable implements IEditorContributio
|
||||
}
|
||||
|
||||
private attachModel(uri?: URI) {
|
||||
if (isInDiffEditor(this.codeEditorService, this.editor)) {
|
||||
if (isOriginalInDiffEditor(this.codeEditorService, this.editor)) {
|
||||
uri = undefined;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ export class TestResultService implements ITestResultService {
|
||||
public readonly onTestChanged = this.testChangeEmitter.event;
|
||||
|
||||
private readonly isRunning: IContextKey<boolean>;
|
||||
private readonly hasAnyResults: IContextKey<boolean>;
|
||||
private readonly loadResults = once(() => this.storage.read().then(loaded => {
|
||||
for (let i = loaded.length - 1; i >= 0; i--) {
|
||||
this.push(loaded[i]);
|
||||
@@ -108,6 +109,7 @@ export class TestResultService implements ITestResultService {
|
||||
@ITestResultStorage private readonly storage: ITestResultStorage,
|
||||
) {
|
||||
this.isRunning = TestingContextKeys.isRunning.bindTo(contextKeyService);
|
||||
this.hasAnyResults = TestingContextKeys.hasAnyResults.bindTo(contextKeyService);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +150,7 @@ export class TestResultService implements ITestResultService {
|
||||
this.persistScheduler.schedule();
|
||||
}
|
||||
|
||||
this.hasAnyResults.set(true);
|
||||
if (this.results.length > RETAIN_MAX_RESULTS) {
|
||||
this.results.pop();
|
||||
}
|
||||
@@ -200,6 +203,7 @@ export class TestResultService implements ITestResultService {
|
||||
|
||||
this._results = keep;
|
||||
this.persistScheduler.schedule();
|
||||
this.hasAnyResults.set(false);
|
||||
this.changeResultEmitter.fire({ removed });
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ export namespace TestingContextKeys {
|
||||
export const providerCount = new RawContextKey('testing.providerCount', 0);
|
||||
export const hasDebuggableTests = new RawContextKey('testing.hasDebuggableTests', false);
|
||||
export const hasRunnableTests = new RawContextKey('testing.hasRunnableTests', false);
|
||||
export const hasAnyResults = new RawContextKey('testing.hasAnyResults', false);
|
||||
export const viewMode = new RawContextKey('testing.explorerViewMode', TestExplorerViewMode.List);
|
||||
export const viewSorting = new RawContextKey('testing.explorerViewSorting', TestExplorerViewSorting.ByLocation);
|
||||
export const isRunning = new RawContextKey('testing.isRunning', false);
|
||||
|
||||
@@ -515,6 +515,7 @@
|
||||
color: inherit;
|
||||
text-align: left;
|
||||
padding: 16px;
|
||||
font-size: 13px;
|
||||
margin: 1px 0; /* makes room for focus border */
|
||||
font-family: inherit;
|
||||
}
|
||||
@@ -524,6 +525,7 @@
|
||||
|
||||
.monaco-workbench .part.editor > .content .gettingStartedContainer button:focus {
|
||||
outline-style: solid;
|
||||
outline-width: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .gettingStartedContainer .prev-button.button-link {
|
||||
|
||||
@@ -49,6 +49,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { GettingStartedInput, gettingStartedInputTypeId } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedInput';
|
||||
import { welcomeButtonBackground, welcomeButtonHoverBackground, welcomePageBackground } from 'vs/workbench/contrib/welcome/page/browser/welcomePageColors';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
|
||||
const configurationKey = 'workbench.startupEditor';
|
||||
@@ -68,6 +69,7 @@ export class WelcomePageContribution implements IWorkbenchContribution {
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
|
||||
// Run immediately to minimize time spent waiting for exp service.
|
||||
@@ -84,7 +86,7 @@ export class WelcomePageContribution implements IWorkbenchContribution {
|
||||
}
|
||||
|
||||
private async run() {
|
||||
const enabled = isWelcomePageEnabled(this.configurationService, this.contextService);
|
||||
const enabled = isWelcomePageEnabled(this.configurationService, this.contextService, this.environmentService);
|
||||
if (enabled && this.lifecycleService.startupKind !== StartupKind.ReloadedWindow) {
|
||||
const hasBackups = await this.workingCopyBackupService.hasBackups();
|
||||
if (hasBackups) { return; }
|
||||
@@ -152,7 +154,11 @@ export class WelcomePageContribution implements IWorkbenchContribution {
|
||||
}
|
||||
}
|
||||
|
||||
function isWelcomePageEnabled(configurationService: IConfigurationService, contextService: IWorkspaceContextService) {
|
||||
function isWelcomePageEnabled(configurationService: IConfigurationService, contextService: IWorkspaceContextService, environmentService: IWorkbenchEnvironmentService) {
|
||||
if (environmentService.skipWelcome) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const startupEditor = configurationService.inspect<string>(configurationKey);
|
||||
if (!startupEditor.userValue && !startupEditor.workspaceValue) {
|
||||
const welcomeEnabled = configurationService.inspect(oldConfigurationKey);
|
||||
|
||||
@@ -34,10 +34,9 @@ import { UILabelProvider } from 'vs/base/common/keybindingLabels';
|
||||
import { OS, OperatingSystem } from 'vs/base/common/platform';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { Dimension, safeInnerHtml, size } from 'vs/base/browser/dom';
|
||||
import { addDisposableListener, Dimension, safeInnerHtml, size } from 'vs/base/browser/dom';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
|
||||
@@ -417,7 +416,7 @@ export class WalkThroughPart extends EditorPane {
|
||||
this.loadTextEditorViewState(input);
|
||||
this.updatedScrollPosition();
|
||||
this.contentDisposables.push(Gesture.addTarget(innerContent));
|
||||
this.contentDisposables.push(domEvent(innerContent, TouchEventType.Change)(e => this.onTouchChange(e as GestureEvent), this, this.disposables));
|
||||
this.contentDisposables.push(addDisposableListener(innerContent, TouchEventType.Change, e => this.onTouchChange(e as GestureEvent)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,8 @@ export function globMatchesResource(globPattern: string | glob.IRelativePattern,
|
||||
const excludedSchemes = new Set([
|
||||
Schemas.extension,
|
||||
Schemas.webviewPanel,
|
||||
Schemas.vscodeWorkspaceTrust,
|
||||
Schemas.walkThrough
|
||||
]);
|
||||
// We want to say that the above schemes match no glob patterns
|
||||
if (excludedSchemes.has(resource.scheme)) {
|
||||
|
||||
@@ -245,6 +245,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
|
||||
get logExtensionHostCommunication(): boolean { return this.payload?.get('logExtensionHostCommunication') === 'true'; }
|
||||
|
||||
get skipReleaseNotes(): boolean { return false; }
|
||||
get skipWelcome(): boolean { return false; }
|
||||
|
||||
@memoize
|
||||
get disableWorkspaceTrust(): boolean { return true; }
|
||||
|
||||
@@ -38,6 +38,7 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService {
|
||||
readonly webviewExternalEndpoint: string;
|
||||
|
||||
readonly skipReleaseNotes: boolean;
|
||||
readonly skipWelcome: boolean;
|
||||
|
||||
readonly debugRenderer: boolean;
|
||||
|
||||
|
||||
@@ -71,6 +71,9 @@ export class NativeWorkbenchEnvironmentService extends AbstractNativeEnvironment
|
||||
@memoize
|
||||
get skipReleaseNotes(): boolean { return !!this.args['skip-release-notes']; }
|
||||
|
||||
@memoize
|
||||
get skipWelcome(): boolean { return !!this.args['skip-welcome']; }
|
||||
|
||||
@memoize
|
||||
get logExtensionHostCommunication(): boolean { return !!this.args.logExtensionHostCommunication; }
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import { IModifierKeyStatus, ModifierKeyEmitter, trackFocus } from 'vs/base/brow
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { parseLineAndColumnAware } from 'vs/base/common/extpath';
|
||||
import { IWorkspaceFolderCreationData } from 'vs/platform/workspaces/common/workspaces';
|
||||
@@ -30,6 +29,7 @@ import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser
|
||||
import { localize } from 'vs/nls';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
|
||||
/**
|
||||
* A workspace to open in the workbench can either be:
|
||||
@@ -170,11 +170,12 @@ export class BrowserHostService extends Disposable implements IHostService {
|
||||
@memoize
|
||||
get onDidChangeFocus(): Event<boolean> {
|
||||
const focusTracker = this._register(trackFocus(window));
|
||||
const onVisibilityChange = this._register(new DomEmitter(window.document, 'visibilitychange'));
|
||||
|
||||
return Event.latch(Event.any(
|
||||
Event.map(focusTracker.onDidFocus, () => this.hasFocus),
|
||||
Event.map(focusTracker.onDidBlur, () => this.hasFocus),
|
||||
Event.map(domEvent(window.document, 'visibilitychange'), () => this.hasFocus)
|
||||
Event.map(onVisibilityChange.event, () => this.hasFocus)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { assertType } from 'vs/base/common/types';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
function assertToJSON(a: any, expected: any) {
|
||||
const raw = JSON.stringify(a);
|
||||
@@ -683,7 +684,7 @@ suite('ExtHostTypes', function () {
|
||||
// --- text
|
||||
|
||||
item = types.NotebookCellOutputItem.text('Hęłlö');
|
||||
assert.strictEqual(item.mime, 'text/plain');
|
||||
assert.strictEqual(item.mime, Mimes.text);
|
||||
assert.deepStrictEqual(item.data, new TextEncoder().encode('Hęłlö'));
|
||||
|
||||
item = types.NotebookCellOutputItem.text('Hęłlö', 'foo/bar');
|
||||
|
||||
@@ -26,6 +26,7 @@ import { TestTextResourcePropertiesService } from 'vs/workbench/test/common/work
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
|
||||
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
|
||||
suite('EditorModel', () => {
|
||||
|
||||
@@ -86,7 +87,7 @@ suite('EditorModel', () => {
|
||||
const model = new MyTextEditorModel(modelService, modeService);
|
||||
await model.resolve();
|
||||
|
||||
model.createTextEditorModel(createTextBufferFactory('foo'), null!, 'text/plain');
|
||||
model.createTextEditorModel(createTextBufferFactory('foo'), null!, Mimes.text);
|
||||
assert.strictEqual(model.isResolved(), true);
|
||||
model.dispose();
|
||||
});
|
||||
|
||||
@@ -135,6 +135,7 @@ export async function spawn(options: SpawnOptions): Promise<Code> {
|
||||
const args = [
|
||||
options.workspacePath,
|
||||
'--skip-release-notes',
|
||||
'--skip-welcome',
|
||||
'--disable-telemetry',
|
||||
'--no-cached-data',
|
||||
'--disable-updates',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user