mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge branch 'main' into merogge/select
This commit is contained in:
+5
-5
@@ -21,16 +21,16 @@ fsevents/test/**
|
||||
@vscode/sqlite3/src/**
|
||||
!@vscode/sqlite3/build/Release/*.node
|
||||
|
||||
@vscode/windows-mutex/binding.gyp
|
||||
@vscode/windows-mutex/build/**
|
||||
@vscode/windows-mutex/src/**
|
||||
!@vscode/windows-mutex/**/*.node
|
||||
|
||||
@vscode/windows-registry/binding.gyp
|
||||
@vscode/windows-registry/src/**
|
||||
@vscode/windows-registry/build/**
|
||||
!@vscode/windows-registry/build/Release/*.node
|
||||
|
||||
windows-mutex/binding.gyp
|
||||
windows-mutex/build/**
|
||||
windows-mutex/src/**
|
||||
!windows-mutex/**/*.node
|
||||
|
||||
native-keymap/binding.gyp
|
||||
native-keymap/build/**
|
||||
native-keymap/src/**
|
||||
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
- job: Windowsx64UnitTests
|
||||
displayName: Windows (Unit Tests)
|
||||
pool: 1es-oss-windows-2022-x64
|
||||
pool: 1es-oss-windows-2019-x64
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
|
||||
- job: Windowsx64IntegrationTests
|
||||
displayName: Windows (Integration Tests)
|
||||
pool: 1es-oss-windows-2022-x64
|
||||
pool: 1es-oss-windows-2019-x64
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
|
||||
# - job: Windowsx64SmokeTests
|
||||
# displayName: Windows (Smoke Tests)
|
||||
# pool: 1es-oss-windows-2022-x64
|
||||
# pool: 1es-oss-windows-2019-x64
|
||||
# timeoutInMinutes: 30
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
|
||||
- job: Windowsx64MaintainNodeModulesCache
|
||||
displayName: Windows (Maintain node_modules cache)
|
||||
pool: 1es-oss-windows-2022-x64
|
||||
pool: 1es-oss-windows-2019-x64
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Manage Built-in Extensions</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="browser-main.js"></script>
|
||||
@@ -43,4 +42,4 @@
|
||||
<div id="extensions"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -2360,7 +2360,12 @@ export class Repository implements Disposable {
|
||||
|
||||
private updateBranchProtectionMatcher(): void {
|
||||
const scopedConfig = workspace.getConfiguration('git', Uri.file(this.repository.root));
|
||||
const branchProtectionGlobs = scopedConfig.get<string[]>('branchProtection')!.map(bp => bp.trim()).filter(bp => bp !== '');
|
||||
const branchProtectionConfig = scopedConfig.get<unknown>('branchProtection') ?? [];
|
||||
const branchProtectionValues = Array.isArray(branchProtectionConfig) ? branchProtectionConfig : [branchProtectionConfig];
|
||||
|
||||
const branchProtectionGlobs = branchProtectionValues
|
||||
.map(bp => typeof bp === 'string' ? bp.trim() : '')
|
||||
.filter(bp => bp !== '');
|
||||
|
||||
if (branchProtectionGlobs.length === 0) {
|
||||
this.isBranchProtectedMatcher = undefined;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
},
|
||||
"enabledApiProposals": [
|
||||
"contribShareMenu",
|
||||
"contribEditorLineNumberMenu",
|
||||
"contribEditSessions"
|
||||
],
|
||||
"contributes": {
|
||||
|
||||
@@ -17,7 +17,7 @@ async function copyVscodeDevLink(gitAPI: GitAPI, useSelection: boolean, context:
|
||||
try {
|
||||
const permalink = getLink(gitAPI, useSelection, getVscodeDevHost(), 'headlink', context, includeRange);
|
||||
if (permalink) {
|
||||
return vscode.env.clipboard.writeText(permalink);
|
||||
return vscode.env.clipboard.writeText(encodeURI(permalink));
|
||||
}
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(err.message);
|
||||
|
||||
+1
-2
@@ -120,7 +120,6 @@
|
||||
"@types/webpack": "^5.28.1",
|
||||
"@types/wicg-file-system-access": "^2020.9.5",
|
||||
"@types/windows-foreground-love": "^0.3.0",
|
||||
"@types/windows-mutex": "^0.4.0",
|
||||
"@types/windows-process-tree": "^0.2.0",
|
||||
"@types/winreg": "^1.2.30",
|
||||
"@types/yauzl": "^2.9.1",
|
||||
@@ -230,9 +229,9 @@
|
||||
"url": "https://github.com/microsoft/vscode/issues"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@vscode/windows-mutex": "0.4.2",
|
||||
"@vscode/windows-registry": "1.0.6",
|
||||
"windows-foreground-love": "0.5.0",
|
||||
"windows-mutex": "0.4.1",
|
||||
"windows-process-tree": "0.4.0"
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
Vendored
+8
-2
@@ -3,6 +3,12 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
// empty placeholder declaration for the `editor/lineNumber/context` menu contribution point
|
||||
declare module '@vscode/windows-mutex' {
|
||||
export class Mutex {
|
||||
constructor(name: string);
|
||||
isActive(): boolean;
|
||||
release(): void;
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/175945 @joyceerhl
|
||||
export function isActive(name: string): boolean;
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head id='headID'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Strada </title>
|
||||
<link href="site.css" rel="stylesheet" type="text/css" />
|
||||
<script src="jquery-1.4.1.js"></script>
|
||||
|
||||
@@ -1221,7 +1221,7 @@ export class CodeApplication extends Disposable {
|
||||
const win32MutexName = this.productService.win32MutexName;
|
||||
if (isWindows && win32MutexName) {
|
||||
try {
|
||||
const WindowsMutex = await import('windows-mutex');
|
||||
const WindowsMutex = await import('@vscode/windows-mutex');
|
||||
const mutex = new WindowsMutex.Mutex(win32MutexName);
|
||||
once(this.lifecycleMainService.onWillShutdown)(() => mutex.release());
|
||||
} catch (error) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import { MarkerHoverParticipant } from 'vs/editor/contrib/hover/browser/markerHo
|
||||
import 'vs/css!./hover';
|
||||
import { InlineSuggestionHintsContentWidget } from 'vs/editor/contrib/inlineCompletions/browser/inlineSuggestionHintsWidget';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
|
||||
export class ModesHoverController implements IEditorContribution {
|
||||
|
||||
@@ -205,7 +206,7 @@ export class ModesHoverController implements IEditorContribution {
|
||||
|
||||
const resolvedKeyboardEvent = this._keybindingService.softDispatch(e, this._editor.getDomNode());
|
||||
// If the beginning of a multi-chord keybinding is pressed, or the command aims to focus the hover, set the variable to true, otherwise false
|
||||
const mightTriggerFocus = (resolvedKeyboardEvent?.enterMultiChord || (resolvedKeyboardEvent?.commandId === 'editor.action.showHover' && this._contentWidget?.isVisible()));
|
||||
const mightTriggerFocus = (resolvedKeyboardEvent?.kind === ResultKind.MoreChordsNeeded || (resolvedKeyboardEvent && resolvedKeyboardEvent.kind === ResultKind.KbFound && resolvedKeyboardEvent.commandId === 'editor.action.showHover' && this._contentWidget?.isVisible()));
|
||||
|
||||
if (e.keyCode !== KeyCode.Ctrl && e.keyCode !== KeyCode.Alt && e.keyCode !== KeyCode.Meta && e.keyCode !== KeyCode.Shift
|
||||
&& !mightTriggerFocus) {
|
||||
|
||||
@@ -109,10 +109,10 @@ flakySuite('Native Modules (all platforms)', () => {
|
||||
|
||||
(!isWindows ? suite.skip : suite)('Native Modules (Windows)', () => {
|
||||
|
||||
(process.type === 'renderer' ? test.skip /* TODO@electron module is not context aware yet and thus cannot load in Electron renderer used by tests */ : test)('windows-mutex', async () => {
|
||||
const mutex = await import('windows-mutex');
|
||||
assert.ok(mutex && typeof mutex.isActive === 'function', testErrorMessage('windows-mutex'));
|
||||
assert.ok(typeof mutex.isActive === 'function', testErrorMessage('windows-mutex'));
|
||||
(process.type === 'renderer' ? test.skip /* TODO@electron module is not context aware yet and thus cannot load in Electron renderer used by tests */ : test)('@vscode/windows-mutex', async () => {
|
||||
const mutex = await import('@vscode/windows-mutex');
|
||||
assert.ok(mutex && typeof mutex.isActive === 'function', testErrorMessage('@vscode/windows-mutex'));
|
||||
assert.ok(typeof mutex.isActive === 'function', testErrorMessage('@vscode/windows-mutex'));
|
||||
});
|
||||
|
||||
test('windows-foreground-love', async () => {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head id='headID'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Strada </title>
|
||||
<link href="site.css" rel="stylesheet" type="text/css" />
|
||||
<script src="jquery-1.4.1.js"></script>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head id='headID'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Strada </title>
|
||||
<link href="site.css" rel="stylesheet" type="text/css" />
|
||||
<script src="jquery-1.4.1.js"></script>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IntervalTimer, TimeoutTimer } from 'vs/base/common/async';
|
||||
import { illegalState } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IME } from 'vs/base/common/ime';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
@@ -16,7 +17,7 @@ import * as nls from 'vs/nls';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IKeybindingService, IKeyboardEvent, KeybindingsSchemaContribution } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IResolveResult, KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolutionResult, KeybindingResolver, ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -30,6 +31,7 @@ interface CurrentChord {
|
||||
const HIGH_FREQ_COMMANDS = /^(cursor|delete|undo|redo|tab|editor\.action\.clipboard)/;
|
||||
|
||||
export abstract class AbstractKeybindingService extends Disposable implements IKeybindingService {
|
||||
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
protected readonly _onDidUpdateKeybindings: Emitter<void> = this._register(new Emitter<void>());
|
||||
@@ -44,7 +46,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
* "cmd+k" would be stored in this array, when on pressing "cmd+i", the service
|
||||
* would invoke the command bound by the keybinding
|
||||
*/
|
||||
private _currentChords: CurrentChord[] | null;
|
||||
private _currentChords: CurrentChord[];
|
||||
|
||||
private _currentChordChecker: IntervalTimer;
|
||||
private _currentChordStatusMessage: IDisposable | null;
|
||||
@@ -55,7 +57,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
protected _logging: boolean;
|
||||
|
||||
public get inChordMode(): boolean {
|
||||
return !!this._currentChords;
|
||||
return this._currentChords.length > 0;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -67,7 +69,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
) {
|
||||
super();
|
||||
|
||||
this._currentChords = null;
|
||||
this._currentChords = [];
|
||||
this._currentChordChecker = new IntervalTimer();
|
||||
this._currentChordStatusMessage = null;
|
||||
this._ignoreSingleModifiers = KeybindingModifierSet.EMPTY;
|
||||
@@ -134,7 +136,9 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
return this._dispatch(e, target);
|
||||
}
|
||||
|
||||
public softDispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null {
|
||||
// TODO@ulugbekna: update namings to align with `_doDispatch`
|
||||
// TODO@ulugbekna: this fn doesn't seem to take into account single-modifier keybindings, eg `shift shift`
|
||||
public softDispatch(e: IKeyboardEvent, target: IContextKeyServiceTarget): ResolutionResult | null {
|
||||
this._log(`/ Soft dispatching keyboard event`);
|
||||
const keybinding = this.resolveKeyboardEvent(e);
|
||||
if (keybinding.hasMultipleChords()) {
|
||||
@@ -149,7 +153,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
}
|
||||
|
||||
const contextValue = this._contextKeyService.getContext(target);
|
||||
const currentChords = this._currentChords ? this._currentChords.map((({ keypress }) => keypress)) : null;
|
||||
const currentChords = this._currentChords.map((({ keypress }) => keypress));
|
||||
return this._getResolver().resolve(contextValue, currentChords, firstChord);
|
||||
}
|
||||
|
||||
@@ -171,25 +175,28 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private _enterMultiChordMode(firstChord: string, keypressLabel: string | null): void {
|
||||
this._currentChords = [{
|
||||
keypress: firstChord,
|
||||
label: keypressLabel
|
||||
}];
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize('first.chord', "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
|
||||
this._scheduleLeaveChordMode();
|
||||
IME.disable();
|
||||
}
|
||||
private _expectAnotherChord(firstChord: string, keypressLabel: string | null): void {
|
||||
|
||||
this._currentChords.push({ keypress: firstChord, label: keypressLabel });
|
||||
|
||||
switch (this._currentChords.length) {
|
||||
case 0:
|
||||
throw illegalState('impossible');
|
||||
case 1:
|
||||
// TODO@ulugbekna: revise this message and the one below (at least, fix terminology)
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize('first.chord', "({0}) was pressed. Waiting for second key of chord...", keypressLabel));
|
||||
break;
|
||||
default: {
|
||||
const fullKeypressLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize('next.chord', "({0}) was pressed. Waiting for next key of chord...", fullKeypressLabel));
|
||||
}
|
||||
}
|
||||
|
||||
private _continueMultiChordMode(nextChord: string, keypressLabel: string | null): void {
|
||||
this._currentChords = this._currentChords ? this._currentChords : [];
|
||||
this._currentChords.push({
|
||||
keypress: nextChord,
|
||||
label: keypressLabel
|
||||
});
|
||||
const fullKeypressLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._currentChordStatusMessage = this._notificationService.status(nls.localize('next.chord', "({0}) was pressed. Waiting for next key of chord...", fullKeypressLabel));
|
||||
this._scheduleLeaveChordMode();
|
||||
|
||||
if (IME.enabled) {
|
||||
IME.disable();
|
||||
}
|
||||
}
|
||||
|
||||
private _leaveChordMode(): void {
|
||||
@@ -198,7 +205,7 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
this._currentChordStatusMessage = null;
|
||||
}
|
||||
this._currentChordChecker.cancel();
|
||||
this._currentChords = null;
|
||||
this._currentChords = [];
|
||||
IME.enable();
|
||||
}
|
||||
|
||||
@@ -287,10 +294,10 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
// hence we disregard `_currentChord` and use the same modifier instead.
|
||||
const [dispatchKeyname,] = userKeypress.getSingleModifierDispatchChords();
|
||||
userPressedChord = dispatchKeyname;
|
||||
currentChords = dispatchKeyname ? [dispatchKeyname] : [];
|
||||
currentChords = dispatchKeyname ? [dispatchKeyname] : []; // TODO@ulugbekna: in the `else` case we assign an empty array - make sure `resolve` can handle an empty array well
|
||||
} else {
|
||||
[userPressedChord,] = userKeypress.getDispatchChords();
|
||||
currentChords = this._currentChords ? this._currentChords.map(({ keypress }) => keypress) : null;
|
||||
currentChords = this._currentChords.map(({ keypress }) => keypress);
|
||||
}
|
||||
|
||||
if (userPressedChord === null) {
|
||||
@@ -304,47 +311,72 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
||||
|
||||
const resolveResult = this._getResolver().resolve(contextValue, currentChords, userPressedChord);
|
||||
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, resolveResult?.commandId);
|
||||
switch (resolveResult.kind) {
|
||||
|
||||
if (resolveResult && resolveResult.enterMultiChord) {
|
||||
shouldPreventDefault = true;
|
||||
this._enterMultiChordMode(userPressedChord, keypressLabel);
|
||||
this._log(`+ Entering chord mode...`);
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
case ResultKind.NoMatchingKb: {
|
||||
|
||||
if (this._currentChords) {
|
||||
if (resolveResult && !resolveResult.leaveMultiChord) {
|
||||
shouldPreventDefault = true;
|
||||
this._continueMultiChordMode(userPressedChord, keypressLabel);
|
||||
this._log(`+ Continuing chord mode...`);
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, `[ No matching keybinding ]`);
|
||||
|
||||
if (this.inChordMode) {
|
||||
const currentChordsLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._log(`+ Leaving multi-chord mode: Nothing bound to "${currentChordsLabel}, ${keypressLabel}".`);
|
||||
this._notificationService.status(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", currentChordsLabel, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
|
||||
this._leaveChordMode();
|
||||
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
return shouldPreventDefault;
|
||||
} else if (!resolveResult || !resolveResult.commandId) {
|
||||
const currentChordsLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._log(`+ Leaving chord mode: Nothing bound to "${currentChordsLabel}, ${keypressLabel}".`);
|
||||
this._notificationService.status(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", currentChordsLabel, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
|
||||
}
|
||||
|
||||
case ResultKind.MoreChordsNeeded: {
|
||||
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, `[ Several keybindings match - more chords needed ]`);
|
||||
|
||||
shouldPreventDefault = true;
|
||||
this._expectAnotherChord(userPressedChord, keypressLabel);
|
||||
this._log(this._currentChords.length === 1 ? `+ Entering multi-chord mode...` : `+ Continuing multi-chord mode...`);
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
|
||||
case ResultKind.KbFound: {
|
||||
|
||||
this._logService.trace('KeybindingService#dispatch', keypressLabel, `[ Will dispatch command ${resolveResult.commandId} ]`);
|
||||
|
||||
if (resolveResult.commandId === null) {
|
||||
|
||||
if (this.inChordMode) {
|
||||
const currentChordsLabel = this._currentChords.map(({ label }) => label).join(', ');
|
||||
this._log(`+ Leaving chord mode: Nothing bound to "${currentChordsLabel}, ${keypressLabel}".`);
|
||||
this._notificationService.status(nls.localize('missing.chord', "The key combination ({0}, {1}) is not a command.", currentChordsLabel, keypressLabel), { hideAfter: 10 * 1000 /* 10s */ });
|
||||
this._leaveChordMode();
|
||||
}
|
||||
|
||||
shouldPreventDefault = true;
|
||||
|
||||
} else {
|
||||
if (this.inChordMode) {
|
||||
this._leaveChordMode();
|
||||
}
|
||||
|
||||
if (!resolveResult.isBubble) {
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
|
||||
this._log(`+ Invoking command ${resolveResult.commandId}.`);
|
||||
if (typeof resolveResult.commandArgs === 'undefined') {
|
||||
this._commandService.executeCommand(resolveResult.commandId).then(undefined, err => this._notificationService.warn(err));
|
||||
} else {
|
||||
this._commandService.executeCommand(resolveResult.commandId, resolveResult.commandArgs).then(undefined, err => this._notificationService.warn(err));
|
||||
}
|
||||
|
||||
if (!HIGH_FREQ_COMMANDS.test(resolveResult.commandId)) {
|
||||
this._telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding', detail: userKeypress.getUserSettingsLabel() ?? undefined });
|
||||
}
|
||||
}
|
||||
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
}
|
||||
|
||||
this._leaveChordMode();
|
||||
|
||||
if (resolveResult && resolveResult.commandId) {
|
||||
if (!resolveResult.bubble) {
|
||||
shouldPreventDefault = true;
|
||||
}
|
||||
this._log(`+ Invoking command ${resolveResult.commandId}.`);
|
||||
if (typeof resolveResult.commandArgs === 'undefined') {
|
||||
this._commandService.executeCommand(resolveResult.commandId).then(undefined, err => this._notificationService.warn(err));
|
||||
} else {
|
||||
this._commandService.executeCommand(resolveResult.commandId, resolveResult.commandArgs).then(undefined, err => this._notificationService.warn(err));
|
||||
}
|
||||
if (!HIGH_FREQ_COMMANDS.test(resolveResult.commandId)) {
|
||||
this._telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding', detail: userKeypress.getUserSettingsLabel() ?? undefined });
|
||||
}
|
||||
}
|
||||
|
||||
return shouldPreventDefault;
|
||||
}
|
||||
|
||||
mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ResolvedKeybinding, Keybinding } from 'vs/base/common/keybindings';
|
||||
import { IContextKeyService, IContextKeyServiceTarget } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolutionResult } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
|
||||
export interface IUserFriendlyKeybinding {
|
||||
@@ -63,7 +63,7 @@ export interface IKeybindingService {
|
||||
/**
|
||||
* Resolve and dispatch `keyboardEvent`, but do not invoke the command or change inner state.
|
||||
*/
|
||||
softDispatch(keyboardEvent: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null;
|
||||
softDispatch(keyboardEvent: IKeyboardEvent, target: IContextKeyServiceTarget): ResolutionResult | null;
|
||||
|
||||
dispatchByUserSettingsLabel(userSettingsLabel: string, target: IContextKeyServiceTarget): void;
|
||||
|
||||
|
||||
@@ -6,16 +6,35 @@
|
||||
import { implies, ContextKeyExpression, ContextKeyExprType, IContext, IContextKeyService, expressionsAreEqualWithConstantSubstitution } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
|
||||
export interface IResolveResult {
|
||||
/** Whether the resolved keybinding is entering a multi chord */
|
||||
enterMultiChord: boolean;
|
||||
/** Whether the resolved keybinding is leaving (and executing) a multi chord keybinding */
|
||||
leaveMultiChord: boolean;
|
||||
commandId: string | null;
|
||||
commandArgs: any;
|
||||
bubble: boolean;
|
||||
//#region resolution-result
|
||||
|
||||
export const enum ResultKind {
|
||||
/** No keybinding found this sequence of chords */
|
||||
NoMatchingKb,
|
||||
|
||||
/** There're several keybindings that have the given sequence of chords as a prefix */
|
||||
MoreChordsNeeded,
|
||||
|
||||
/** A single keybinding found to be dispatched/invoked */
|
||||
KbFound
|
||||
}
|
||||
|
||||
export type ResolutionResult =
|
||||
| { kind: ResultKind.NoMatchingKb }
|
||||
| { kind: ResultKind.MoreChordsNeeded }
|
||||
| { kind: ResultKind.KbFound; commandId: string | null; commandArgs: any; isBubble: boolean };
|
||||
|
||||
|
||||
// util definitions to make working with the above types easier within this module:
|
||||
|
||||
const NoMatchingKb: ResolutionResult = { kind: ResultKind.NoMatchingKb };
|
||||
const MoreChordsNeeded: ResolutionResult = { kind: ResultKind.MoreChordsNeeded };
|
||||
function KbFound(commandId: string | null, commandArgs: any, isBubble: boolean): ResolutionResult {
|
||||
return { kind: ResultKind.KbFound, commandId, commandArgs, isBubble };
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* Stores mappings from keybindings to commands and from commands to keybindings.
|
||||
* Given a sequence of chords, `resolve`s which keybinding it matches
|
||||
@@ -281,82 +300,70 @@ export class KeybindingResolver {
|
||||
return items[items.length - 1];
|
||||
}
|
||||
|
||||
public resolve(context: IContext, currentChords: string[] | null, keypress: string): IResolveResult | null {
|
||||
this._log(`| Resolving ${keypress}${currentChords ? ` chorded from ${currentChords}` : ``}`);
|
||||
/**
|
||||
* Looks up a keybinding trigged as a result of pressing a sequence of chords - `[...currentChords, keypress]`
|
||||
*
|
||||
* Example: resolving 3 chords pressed sequentially - `cmd+k cmd+p cmd+i`:
|
||||
* `currentChords = [ 'cmd+k' , 'cmd+p' ]` and `keypress = `cmd+i` - last pressed chord
|
||||
*/
|
||||
public resolve(context: IContext, currentChords: string[], keypress: string): ResolutionResult {
|
||||
|
||||
const pressedChords = [...currentChords, keypress];
|
||||
|
||||
this._log(`| Resolving ${pressedChords}`);
|
||||
|
||||
const kbCandidates = this._map.get(pressedChords[0]);
|
||||
if (kbCandidates === undefined) {
|
||||
// No bindings with such 0-th chord
|
||||
this._log(`\\ No keybinding entries.`);
|
||||
return NoMatchingKb;
|
||||
}
|
||||
|
||||
let lookupMap: ResolvedKeybindingItem[] | null = null;
|
||||
|
||||
if (currentChords !== null) {
|
||||
if (pressedChords.length < 2) {
|
||||
lookupMap = kbCandidates;
|
||||
} else {
|
||||
// Fetch all chord bindings for `currentChords`
|
||||
const candidates = this._map.get(currentChords[0]);
|
||||
if (typeof candidates === 'undefined') {
|
||||
// No chords starting with `currentChords`
|
||||
this._log(`\\ No keybinding entries.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
lookupMap = [];
|
||||
for (let i = 0, len = candidates.length; i < len; i++) {
|
||||
const candidate = candidates[i];
|
||||
if (candidate.chords.length <= currentChords.length) {
|
||||
for (let i = 0, len = kbCandidates.length; i < len; i++) {
|
||||
|
||||
const candidate = kbCandidates[i];
|
||||
|
||||
if (pressedChords.length > candidate.chords.length) { // # of pressed chords can't be less than # of chords in a keybinding to invoke
|
||||
continue;
|
||||
}
|
||||
|
||||
let prefixMatches = true;
|
||||
for (let i = 1; i < currentChords.length; i++) {
|
||||
if (candidate.chords[i] !== currentChords[i]) {
|
||||
for (let i = 1; i < pressedChords.length; i++) {
|
||||
if (candidate.chords[i] !== pressedChords[i]) {
|
||||
prefixMatches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prefixMatches && candidate.chords[currentChords.length] === keypress) {
|
||||
if (prefixMatches) {
|
||||
lookupMap.push(candidate);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const candidates = this._map.get(keypress);
|
||||
if (typeof candidates === 'undefined') {
|
||||
// No bindings with `keypress`
|
||||
this._log(`\\ No keybinding entries.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
lookupMap = candidates;
|
||||
}
|
||||
|
||||
// check there's a keybinding with a matching when clause
|
||||
const result = this._findCommand(context, lookupMap);
|
||||
if (!result) {
|
||||
this._log(`\\ From ${lookupMap.length} keybinding entries, no when clauses matched the context.`);
|
||||
return null;
|
||||
return NoMatchingKb;
|
||||
}
|
||||
|
||||
if (currentChords === null && result.chords.length > 1 && result.chords[1] !== null) {
|
||||
this._log(`\\ From ${lookupMap.length} keybinding entries, matched chord, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);
|
||||
return {
|
||||
enterMultiChord: true,
|
||||
leaveMultiChord: false,
|
||||
commandId: null,
|
||||
commandArgs: null,
|
||||
bubble: false
|
||||
};
|
||||
} else if (currentChords !== null && currentChords.length + 1 < result.chords.length) {
|
||||
this._log(`\\ From ${lookupMap.length} keybinding entries, continued chord, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);
|
||||
return {
|
||||
enterMultiChord: false,
|
||||
leaveMultiChord: false,
|
||||
commandId: null,
|
||||
commandArgs: null,
|
||||
bubble: false
|
||||
};
|
||||
// check we got all chords necessary to be sure a particular keybinding needs to be invoked
|
||||
if (pressedChords.length < result.chords.length) {
|
||||
// The chord sequence is not complete
|
||||
this._log(`\\ From ${lookupMap.length} keybinding entries, awaiting ${result.chords.length - pressedChords.length} more chord(s), when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);
|
||||
return MoreChordsNeeded;
|
||||
}
|
||||
|
||||
this._log(`\\ From ${lookupMap.length} keybinding entries, matched ${result.command}, when: ${printWhenExplanation(result.when)}, source: ${printSourceExplanation(result)}.`);
|
||||
return {
|
||||
enterMultiChord: false,
|
||||
leaveMultiChord: result.chords.length > 1,
|
||||
commandId: result.command,
|
||||
commandArgs: result.commandArgs,
|
||||
bubble: result.bubble
|
||||
};
|
||||
|
||||
return KbFound(result.command, result.commandArgs, result.bubble);
|
||||
}
|
||||
|
||||
private _findCommand(context: IContext, matches: ResolvedKeybindingItem[]): ResolvedKeybindingItem | null {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { decodeKeybinding, createSimpleKeybinding, KeyCodeChord } from 'vs/base/
|
||||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { ContextKeyExpr, ContextKeyExpression, IContext } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingResolver } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { KeybindingResolver, ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
import { createUSLayoutResolvedKeybinding } from 'vs/platform/keybinding/test/common/keybindingsTestUtils';
|
||||
@@ -50,8 +50,13 @@ suite('KeybindingResolver', () => {
|
||||
assert.strictEqual(contextRules.evaluate(createContext({ bar: 'bz' })), false);
|
||||
|
||||
const resolver = new KeybindingResolver([keybindingItem], [], () => { });
|
||||
assert.strictEqual(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(runtimeKeybinding))!.commandId, 'yes');
|
||||
assert.strictEqual(resolver.resolve(createContext({ bar: 'bz' }), null, getDispatchStr(runtimeKeybinding)), null);
|
||||
|
||||
const r1 = resolver.resolve(createContext({ bar: 'baz' }), [], getDispatchStr(runtimeKeybinding));
|
||||
assert.ok(r1.kind === ResultKind.KbFound);
|
||||
assert.strictEqual(r1.commandId, 'yes');
|
||||
|
||||
const r2 = resolver.resolve(createContext({ bar: 'bz' }), [], getDispatchStr(runtimeKeybinding));
|
||||
assert.strictEqual(r2.kind, ResultKind.NoMatchingKb);
|
||||
});
|
||||
|
||||
test('resolve key with arguments', () => {
|
||||
@@ -62,247 +67,253 @@ suite('KeybindingResolver', () => {
|
||||
const keybindingItem = kbItem(keybinding, 'yes', commandArgs, contextRules, true);
|
||||
|
||||
const resolver = new KeybindingResolver([keybindingItem], [], () => { });
|
||||
assert.strictEqual(resolver.resolve(createContext({ bar: 'baz' }), null, getDispatchStr(runtimeKeybinding))!.commandArgs, commandArgs);
|
||||
|
||||
const r = resolver.resolve(createContext({ bar: 'baz' }), [], getDispatchStr(runtimeKeybinding));
|
||||
assert.ok(r.kind === ResultKind.KbFound);
|
||||
assert.strictEqual(r.commandArgs, commandArgs);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals simple 1', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false),
|
||||
]);
|
||||
suite('handle keybinding removals', () => {
|
||||
|
||||
test('simple 1', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), false),
|
||||
]);
|
||||
});
|
||||
|
||||
test('simple 2', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyC, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true),
|
||||
kbItem(KeyCode.KeyC, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false),
|
||||
]);
|
||||
});
|
||||
|
||||
test('removal with not matching when', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, ContextKeyExpr.equals('1', 'b'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('removal with not matching keybinding', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyB, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('removal with matching keybinding and when', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('removal with unspecified keybinding', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(0, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('removal with unspecified when', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, undefined, false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('removal with unspecified when and unspecified keybinding', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(0, '-yes1', null, undefined, false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #138997 - removal in default list', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, undefined, true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, undefined, true),
|
||||
kbItem(0, '-yes1', null, undefined, false)
|
||||
];
|
||||
const overrides: ResolvedKeybindingItem[] = [];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, undefined, true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #612#issuecomment-222109084 cannot remove keybindings for commands with ^', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, '^yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, undefined, false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #140884 Unable to reassign F1 as keybinding for Show All Commands', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-command1', null, undefined, false),
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, false)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #141638: Keyboard Shortcuts: Change When Expression might actually remove keybinding in Insiders', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, ContextKeyExpr.equals('a', '1'), false),
|
||||
kbItem(KeyCode.KeyA, '-command1', null, undefined, false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, ContextKeyExpr.equals('a', '1'), false)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #157751: Auto-quoting of context keys prevents removal of keybindings via UI', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, ContextKeyExpr.deserialize(`editorTextFocus && activeEditor != workbench.editor.notebook && editorLangId in julia.supportedLanguageIds`), true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-command1', null, ContextKeyExpr.deserialize(`editorTextFocus && activeEditor != 'workbench.editor.notebook' && editorLangId in 'julia.supportedLanguageIds'`), false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, []);
|
||||
});
|
||||
|
||||
test('issue #160604: Remove keybindings with when clause does not work', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-command1', null, ContextKeyExpr.true(), false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, []);
|
||||
});
|
||||
|
||||
test('contextIsEntirelyIncluded', () => {
|
||||
const toContextKeyExpression = (expr: ContextKeyExpression | string | null) => {
|
||||
if (typeof expr === 'string' || !expr) {
|
||||
return ContextKeyExpr.deserialize(expr);
|
||||
}
|
||||
return expr;
|
||||
};
|
||||
const assertIsIncluded = (a: ContextKeyExpression | string | null, b: ContextKeyExpression | string | null) => {
|
||||
assert.strictEqual(KeybindingResolver.whenIsEntirelyIncluded(toContextKeyExpression(a), toContextKeyExpression(b)), true);
|
||||
};
|
||||
const assertIsNotIncluded = (a: ContextKeyExpression | string | null, b: ContextKeyExpression | string | null) => {
|
||||
assert.strictEqual(KeybindingResolver.whenIsEntirelyIncluded(toContextKeyExpression(a), toContextKeyExpression(b)), false);
|
||||
};
|
||||
|
||||
assertIsIncluded(null, null);
|
||||
assertIsIncluded(null, ContextKeyExpr.true());
|
||||
assertIsIncluded(ContextKeyExpr.true(), null);
|
||||
assertIsIncluded(ContextKeyExpr.true(), ContextKeyExpr.true());
|
||||
assertIsIncluded('key1', null);
|
||||
assertIsIncluded('key1', '');
|
||||
assertIsIncluded('key1', 'key1');
|
||||
assertIsIncluded('key1', ContextKeyExpr.true());
|
||||
assertIsIncluded('!key1', '');
|
||||
assertIsIncluded('!key1', '!key1');
|
||||
assertIsIncluded('key2', '');
|
||||
assertIsIncluded('key2', 'key2');
|
||||
assertIsIncluded('key1 && key1 && key2 && key2', 'key2');
|
||||
assertIsIncluded('key1 && key2', 'key2');
|
||||
assertIsIncluded('key1 && key2', 'key1');
|
||||
assertIsIncluded('key1 && key2', '');
|
||||
assertIsIncluded('key1', 'key1 || key2');
|
||||
assertIsIncluded('key1 || !key1', 'key2 || !key2');
|
||||
assertIsIncluded('key1', 'key1 || key2 && key3');
|
||||
|
||||
assertIsNotIncluded('key1', '!key1');
|
||||
assertIsNotIncluded('!key1', 'key1');
|
||||
assertIsNotIncluded('key1 && key2', 'key3');
|
||||
assertIsNotIncluded('key1 && key2', 'key4');
|
||||
assertIsNotIncluded('key1', 'key2');
|
||||
assertIsNotIncluded('key1 || key2', 'key2');
|
||||
assertIsNotIncluded('', 'key2');
|
||||
assertIsNotIncluded(null, 'key2');
|
||||
});
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals simple 2', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyC, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true),
|
||||
kbItem(KeyCode.KeyC, 'yes3', null, ContextKeyExpr.equals('3', 'c'), false),
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals removal with not matching when', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, ContextKeyExpr.equals('1', 'b'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals removal with not matching keybinding', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyB, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals removal with matching keybinding and when', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals removal with unspecified keybinding', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(0, '-yes1', null, ContextKeyExpr.equals('1', 'a'), false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals removal with unspecified when', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, undefined, false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('KeybindingResolver.handleRemovals removal with unspecified when and unspecified keybinding', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(0, '-yes1', null, undefined, false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #138997 KeybindingResolver.handleRemovals removal in default list', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'yes1', null, undefined, true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, undefined, true),
|
||||
kbItem(0, '-yes1', null, undefined, false)
|
||||
];
|
||||
const overrides: ResolvedKeybindingItem[] = [];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, undefined, true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #612#issuecomment-222109084 cannot remove keybindings for commands with ^', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, '^yes1', null, ContextKeyExpr.equals('1', 'a'), true),
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-yes1', null, undefined, false)
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyB, 'yes2', null, ContextKeyExpr.equals('2', 'b'), true)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #140884 Unable to reassign F1 as keybinding for Show All Commands', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-command1', null, undefined, false),
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, false)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #141638: Keyboard Shortcuts: Change When Expression might actually remove keybinding in Insiders', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, ContextKeyExpr.equals('a', '1'), false),
|
||||
kbItem(KeyCode.KeyA, '-command1', null, undefined, false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, ContextKeyExpr.equals('a', '1'), false)
|
||||
]);
|
||||
});
|
||||
|
||||
test('issue #157751: Auto-quoting of context keys prevents removal of keybindings via UI', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, ContextKeyExpr.deserialize(`editorTextFocus && activeEditor != workbench.editor.notebook && editorLangId in julia.supportedLanguageIds`), true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-command1', null, ContextKeyExpr.deserialize(`editorTextFocus && activeEditor != 'workbench.editor.notebook' && editorLangId in 'julia.supportedLanguageIds'`), false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, []);
|
||||
});
|
||||
|
||||
test('issue #160604: Remove keybindings with when clause does not work', () => {
|
||||
const defaults = [
|
||||
kbItem(KeyCode.KeyA, 'command1', null, undefined, true),
|
||||
];
|
||||
const overrides = [
|
||||
kbItem(KeyCode.KeyA, '-command1', null, ContextKeyExpr.true(), false),
|
||||
];
|
||||
const actual = KeybindingResolver.handleRemovals([...defaults, ...overrides]);
|
||||
assert.deepStrictEqual(actual, []);
|
||||
});
|
||||
|
||||
test('contextIsEntirelyIncluded', () => {
|
||||
const toContextKeyExpression = (expr: ContextKeyExpression | string | null) => {
|
||||
if (typeof expr === 'string' || !expr) {
|
||||
return ContextKeyExpr.deserialize(expr);
|
||||
}
|
||||
return expr;
|
||||
};
|
||||
const assertIsIncluded = (a: ContextKeyExpression | string | null, b: ContextKeyExpression | string | null) => {
|
||||
assert.strictEqual(KeybindingResolver.whenIsEntirelyIncluded(toContextKeyExpression(a), toContextKeyExpression(b)), true);
|
||||
};
|
||||
const assertIsNotIncluded = (a: ContextKeyExpression | string | null, b: ContextKeyExpression | string | null) => {
|
||||
assert.strictEqual(KeybindingResolver.whenIsEntirelyIncluded(toContextKeyExpression(a), toContextKeyExpression(b)), false);
|
||||
};
|
||||
|
||||
assertIsIncluded(null, null);
|
||||
assertIsIncluded(null, ContextKeyExpr.true());
|
||||
assertIsIncluded(ContextKeyExpr.true(), null);
|
||||
assertIsIncluded(ContextKeyExpr.true(), ContextKeyExpr.true());
|
||||
assertIsIncluded('key1', null);
|
||||
assertIsIncluded('key1', '');
|
||||
assertIsIncluded('key1', 'key1');
|
||||
assertIsIncluded('key1', ContextKeyExpr.true());
|
||||
assertIsIncluded('!key1', '');
|
||||
assertIsIncluded('!key1', '!key1');
|
||||
assertIsIncluded('key2', '');
|
||||
assertIsIncluded('key2', 'key2');
|
||||
assertIsIncluded('key1 && key1 && key2 && key2', 'key2');
|
||||
assertIsIncluded('key1 && key2', 'key2');
|
||||
assertIsIncluded('key1 && key2', 'key1');
|
||||
assertIsIncluded('key1 && key2', '');
|
||||
assertIsIncluded('key1', 'key1 || key2');
|
||||
assertIsIncluded('key1 || !key1', 'key2 || !key2');
|
||||
assertIsIncluded('key1', 'key1 || key2 && key3');
|
||||
|
||||
assertIsNotIncluded('key1', '!key1');
|
||||
assertIsNotIncluded('!key1', 'key1');
|
||||
assertIsNotIncluded('key1 && key2', 'key3');
|
||||
assertIsNotIncluded('key1 && key2', 'key4');
|
||||
assertIsNotIncluded('key1', 'key2');
|
||||
assertIsNotIncluded('key1 || key2', 'key2');
|
||||
assertIsNotIncluded('', 'key2');
|
||||
assertIsNotIncluded(null, 'key2');
|
||||
});
|
||||
|
||||
test('resolve command', () => {
|
||||
suite('resolve command', () => {
|
||||
|
||||
function _kbItem(keybinding: number | number[], command: string, when: ContextKeyExpression | undefined): ResolvedKeybindingItem {
|
||||
return kbItem(keybinding, command, null, when, true);
|
||||
@@ -370,30 +381,40 @@ suite('KeybindingResolver', () => {
|
||||
undefined
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC),
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC), // cmd+k cmd+c
|
||||
'comment lines',
|
||||
undefined
|
||||
),
|
||||
_kbItem(
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KeyG, KeyMod.CtrlCmd | KeyCode.KeyC),
|
||||
KeyChord(KeyMod.CtrlCmd | KeyCode.KeyG, KeyMod.CtrlCmd | KeyCode.KeyC), // cmd+g cmd+c
|
||||
'unreachablechord',
|
||||
undefined
|
||||
),
|
||||
_kbItem(
|
||||
KeyMod.CtrlCmd | KeyCode.KeyG,
|
||||
KeyMod.CtrlCmd | KeyCode.KeyG, // cmd+g
|
||||
'eleven',
|
||||
undefined
|
||||
),
|
||||
_kbItem(
|
||||
[KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyA, KeyCode.KeyB],
|
||||
[KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyA, KeyCode.KeyB], // cmd+k a b
|
||||
'long multi chord',
|
||||
undefined
|
||||
),
|
||||
_kbItem(
|
||||
[KeyMod.CtrlCmd | KeyCode.KeyB, KeyMod.CtrlCmd | KeyCode.KeyC], // cmd+b cmd+c
|
||||
'shadowed by long-multi-chord-2',
|
||||
undefined
|
||||
),
|
||||
_kbItem(
|
||||
[KeyMod.CtrlCmd | KeyCode.KeyB, KeyMod.CtrlCmd | KeyCode.KeyC, KeyCode.KeyI], // cmd+b cmd+c i
|
||||
'long-multi-chord-2',
|
||||
undefined
|
||||
)
|
||||
];
|
||||
|
||||
const resolver = new KeybindingResolver(items, [], () => { });
|
||||
|
||||
const testKey = (commandId: string, expectedKeys: number[] | number[][]) => {
|
||||
const testKbLookupByCommand = (commandId: string, expectedKeys: number[] | number[][]) => {
|
||||
// Test lookup
|
||||
const lookupResult = resolver.lookupKeybindings(commandId);
|
||||
assert.strictEqual(lookupResult.length, expectedKeys.length, 'Length mismatch @ commandId ' + commandId);
|
||||
@@ -407,68 +428,93 @@ suite('KeybindingResolver', () => {
|
||||
const testResolve = (ctx: IContext, _expectedKey: number | number[], commandId: string) => {
|
||||
const expectedKeybinding = decodeKeybinding(_expectedKey, OS)!;
|
||||
|
||||
let previousChord: string[] | null = null;
|
||||
const previousChord: string[] = [];
|
||||
|
||||
for (let i = 0, len = expectedKeybinding.chords.length; i < len; i++) {
|
||||
|
||||
const chord = getDispatchStr(<KeyCodeChord>expectedKeybinding.chords[i]);
|
||||
|
||||
const result = resolver.resolve(ctx, previousChord, chord);
|
||||
|
||||
if (i === len - 1) {
|
||||
// if it's the final chord, then we should find a valid command,
|
||||
// and there should not be a chord.
|
||||
assert.ok(result !== null, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.commandId, commandId, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.enterMultiChord, false, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
assert.ok(result.kind === ResultKind.KbFound, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result.commandId, commandId, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
} else if (i > 0) {
|
||||
// if this is an intermediate chord, we should not find a valid command,
|
||||
// and there should be an open chord we continue.
|
||||
assert.ok(result !== null, `Continues multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.commandId, null, `Continues multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.enterMultiChord, false, `Is already in multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.leaveMultiChord, false, `Does not leave multi chord for ${commandId} at chord ${i}`);
|
||||
assert.ok(result.kind === ResultKind.MoreChordsNeeded, `Continues multi chord for ${commandId} at chord ${i}`);
|
||||
} else {
|
||||
// if it's not the final chord and not an intermediate, then we should not
|
||||
// find a valid command, and we should enter a chord.
|
||||
assert.ok(result !== null, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.commandId, null, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
assert.strictEqual(result!.enterMultiChord, true, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
}
|
||||
if (previousChord === null) {
|
||||
previousChord = [];
|
||||
assert.ok(result.kind === ResultKind.MoreChordsNeeded, `Enters multi chord for ${commandId} at chord ${i}`);
|
||||
}
|
||||
previousChord.push(chord);
|
||||
}
|
||||
};
|
||||
|
||||
testKey('first', []);
|
||||
test('resolve command - 1', () => {
|
||||
testKbLookupByCommand('first', []);
|
||||
});
|
||||
|
||||
testKey('second', [KeyCode.KeyZ, KeyCode.KeyX]);
|
||||
testResolve(createContext({ key2: true }), KeyCode.KeyX, 'second');
|
||||
testResolve(createContext({}), KeyCode.KeyZ, 'second');
|
||||
test('resolve command - 2', () => {
|
||||
testKbLookupByCommand('second', [KeyCode.KeyZ, KeyCode.KeyX]);
|
||||
testResolve(createContext({ key2: true }), KeyCode.KeyX, 'second');
|
||||
testResolve(createContext({}), KeyCode.KeyZ, 'second');
|
||||
});
|
||||
|
||||
testKey('third', [KeyCode.KeyX]);
|
||||
testResolve(createContext({ key3: true }), KeyCode.KeyX, 'third');
|
||||
test('resolve command - 3', () => {
|
||||
testKbLookupByCommand('third', [KeyCode.KeyX]);
|
||||
testResolve(createContext({ key3: true }), KeyCode.KeyX, 'third');
|
||||
});
|
||||
|
||||
testKey('fourth', []);
|
||||
test('resolve command - 4', () => {
|
||||
testKbLookupByCommand('fourth', []);
|
||||
});
|
||||
|
||||
testKey('fifth', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyY, KeyCode.KeyZ)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyY, KeyCode.KeyZ), 'fifth');
|
||||
test('resolve command - 5', () => {
|
||||
testKbLookupByCommand('fifth', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyY, KeyCode.KeyZ)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyY, KeyCode.KeyZ), 'fifth');
|
||||
});
|
||||
|
||||
testKey('seventh', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyK)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyK), 'seventh');
|
||||
test('resolve command - 6', () => {
|
||||
testKbLookupByCommand('seventh', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyK)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyK), 'seventh');
|
||||
});
|
||||
|
||||
testKey('uncomment lines', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyU)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyU), 'uncomment lines');
|
||||
test('resolve command - 7', () => {
|
||||
testKbLookupByCommand('uncomment lines', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyU)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyU), 'uncomment lines');
|
||||
});
|
||||
|
||||
testKey('comment lines', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC), 'comment lines');
|
||||
test('resolve command - 8', () => {
|
||||
testKbLookupByCommand('comment lines', [KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC)]);
|
||||
testResolve(createContext({}), KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyC), 'comment lines');
|
||||
});
|
||||
|
||||
testKey('unreachablechord', []);
|
||||
test('resolve command - 9', () => {
|
||||
testKbLookupByCommand('unreachablechord', []);
|
||||
});
|
||||
|
||||
testKey('eleven', [KeyMod.CtrlCmd | KeyCode.KeyG]);
|
||||
testResolve(createContext({}), KeyMod.CtrlCmd | KeyCode.KeyG, 'eleven');
|
||||
test('resolve command - 10', () => {
|
||||
testKbLookupByCommand('eleven', [KeyMod.CtrlCmd | KeyCode.KeyG]);
|
||||
testResolve(createContext({}), KeyMod.CtrlCmd | KeyCode.KeyG, 'eleven');
|
||||
});
|
||||
|
||||
testKey('sixth', []);
|
||||
test('resolve command - 11', () => {
|
||||
testKbLookupByCommand('sixth', []);
|
||||
});
|
||||
|
||||
testKey('long multi chord', [[KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyA, KeyCode.KeyB]]);
|
||||
testResolve(createContext({}), [KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyA, KeyCode.KeyB], 'long multi chord');
|
||||
test('resolve command - 12', () => {
|
||||
testKbLookupByCommand('long multi chord', [[KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyA, KeyCode.KeyB]]);
|
||||
testResolve(createContext({}), [KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.KeyA, KeyCode.KeyB], 'long multi chord');
|
||||
});
|
||||
|
||||
const emptyContext = createContext({});
|
||||
|
||||
test('KBs having common prefix - the one defined later is returned', () => {
|
||||
testResolve(emptyContext, [KeyMod.CtrlCmd | KeyCode.KeyB, KeyMod.CtrlCmd | KeyCode.KeyC, KeyCode.KeyI], 'long-multi-chord-2');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ResolvedKeybinding, KeyCodeChord, Keybinding } from 'vs/base/common/key
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { ContextKeyExpression, ContextKeyValue, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IScopedContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IKeybindingService, IKeyboardEvent } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IResolveResult } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolutionResult } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { ResolvedKeybindingItem } from 'vs/platform/keybinding/common/resolvedKeybindingItem';
|
||||
import { USLayoutResolvedKeybinding } from 'vs/platform/keybinding/common/usLayoutResolvedKeybinding';
|
||||
|
||||
@@ -135,7 +135,7 @@ export class MockKeybindingService implements IKeybindingService {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public softDispatch(keybinding: IKeyboardEvent, target: IContextKeyServiceTarget): IResolveResult | null {
|
||||
public softDispatch(keybinding: IKeyboardEvent, target: IContextKeyServiceTarget): ResolutionResult | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import { IContextViewService } from 'vs/platform/contextview/browser/contextView
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { createDecorator, IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IStyleOverride, defaultFindWidgetStyles, defaultListStyles, getListStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
|
||||
@@ -809,7 +810,7 @@ function createKeyboardNavigationEventFilter(keybindingService: IKeybindingServi
|
||||
|
||||
const result = keybindingService.softDispatch(event, event.target);
|
||||
|
||||
if (result?.enterMultiChord) {
|
||||
if (result?.kind === ResultKind.MoreChordsNeeded) {
|
||||
inMultiChord = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ export class Win32UpdateService extends AbstractUpdateService {
|
||||
});
|
||||
|
||||
const readyMutexName = `${this.productService.win32MutexName}-ready`;
|
||||
const mutex = await import('windows-mutex');
|
||||
const mutex = await import('@vscode/windows-mutex');
|
||||
|
||||
// poll for mutex-ready
|
||||
pollUntil(() => mutex.isActive(readyMutexName))
|
||||
|
||||
@@ -29,6 +29,7 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
|
||||
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
|
||||
import { ResolutionResult, ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
|
||||
class InspectContextKeysAction extends Action2 {
|
||||
|
||||
@@ -259,7 +260,7 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
const shortcut = keybindingService.softDispatch(event, event.target);
|
||||
|
||||
// Hide the single arrow key pressed
|
||||
if (shortcut?.commandId && configurationService.getValue('screencastMode.hideSingleEditorCursorMoves') && (
|
||||
if (shortcut && shortcut.kind === ResultKind.KbFound && shortcut.commandId && configurationService.getValue('screencastMode.hideSingleEditorCursorMoves') && (
|
||||
['cursorLeft', 'cursorRight', 'cursorUp', 'cursorDown'].includes(shortcut.commandId))
|
||||
) {
|
||||
return;
|
||||
@@ -278,7 +279,7 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
|
||||
const format = configurationService.getValue<'keys' | 'command' | 'commandWithGroup' | 'commandAndKeys' | 'commandWithGroupAndKeys'>('screencastMode.keyboardShortcutsFormat');
|
||||
const keybinding = keybindingService.resolveKeyboardEvent(event);
|
||||
const command = shortcut?.commandId ? MenuRegistry.getCommand(shortcut.commandId) : null;
|
||||
const command = (this._isKbFound(shortcut) && shortcut.commandId) ? MenuRegistry.getCommand(shortcut.commandId) : null;
|
||||
|
||||
let titleLabel = '';
|
||||
let keyLabel: string | undefined | null = keybinding.getLabel();
|
||||
@@ -290,7 +291,7 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
titleLabel = `${typeof command.category === 'string' ? command.category : command.category.value}: ${titleLabel} `;
|
||||
}
|
||||
|
||||
if (shortcut?.commandId) {
|
||||
if (this._isKbFound(shortcut) && shortcut.commandId) {
|
||||
const keybindings = keybindingService.lookupKeybindings(shortcut.commandId)
|
||||
.filter(k => k.getLabel()?.endsWith(keyLabel ?? ''));
|
||||
|
||||
@@ -306,7 +307,7 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
append(keyboardMarker, $('span.title', {}, `${titleLabel} `));
|
||||
}
|
||||
|
||||
if (onlyKeyboardShortcuts || !titleLabel || shortcut?.commandId && (format === 'keys' || format === 'commandAndKeys' || format === 'commandWithGroupAndKeys')) {
|
||||
if (onlyKeyboardShortcuts || !titleLabel || (this._isKbFound(shortcut) && shortcut.commandId) && (format === 'keys' || format === 'commandAndKeys' || format === 'commandWithGroupAndKeys')) {
|
||||
// Fix label for arrow keys
|
||||
keyLabel = keyLabel?.replace('UpArrow', '↑')
|
||||
?.replace('DownArrow', '↓')
|
||||
@@ -322,6 +323,10 @@ class ToggleScreencastModeAction extends Action2 {
|
||||
|
||||
ToggleScreencastModeAction.disposable = disposables;
|
||||
}
|
||||
|
||||
private _isKbFound(resolutionResult: ResolutionResult | null): resolutionResult is { kind: ResultKind.KbFound; commandId: string | null; commandArgs: any; isBubble: boolean } {
|
||||
return resolutionResult !== null && resolutionResult.kind === ResultKind.KbFound;
|
||||
}
|
||||
}
|
||||
|
||||
class LogStorageAction extends Action2 {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { fromNow } from 'vs/base/common/date';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer';
|
||||
import { defaultButtonStyles, defaultCheckboxStyles, defaultDialogStyles, defaultInputBoxStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
|
||||
export class BrowserDialogHandler extends AbstractDialogHandler {
|
||||
|
||||
@@ -127,7 +128,7 @@ export class BrowserDialogHandler extends AbstractDialogHandler {
|
||||
type: this.getDialogType(type),
|
||||
keyEventProcessor: (event: StandardKeyboardEvent) => {
|
||||
const resolved = this.keybindingService.softDispatch(event, this.layoutService.container);
|
||||
if (resolved?.commandId) {
|
||||
if (resolved && resolved.kind === ResultKind.KbFound && resolved.commandId) {
|
||||
if (BrowserDialogHandler.ALLOWABLE_COMMANDS.indexOf(resolved.commandId) === -1) {
|
||||
EventHelper.stop(event, true);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ import { editorBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { TerminalExtensionsRegistry } from 'vs/workbench/contrib/terminal/browser/terminalExtensions';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keybindings';
|
||||
import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
|
||||
const enum Constants {
|
||||
/**
|
||||
@@ -941,7 +942,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
// Respect chords if the allowChords setting is set and it's not Escape. Escape is
|
||||
// handled specially for Zen Mode's Escape, Escape chord, plus it's important in
|
||||
// terminals generally
|
||||
const isValidChord = resolveResult?.enterMultiChord && this._configHelper.config.allowChords && event.key !== 'Escape';
|
||||
const isValidChord = resolveResult?.kind === ResultKind.MoreChordsNeeded && this._configHelper.config.allowChords && event.key !== 'Escape';
|
||||
if (this._keybindingService.inChordMode || isValidChord) {
|
||||
event.preventDefault();
|
||||
return false;
|
||||
@@ -961,7 +962,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
|
||||
// for keyboard events that resolve to commands described
|
||||
// within commandsToSkipShell, either alert or skip processing by xterm.js
|
||||
if (resolveResult && resolveResult.commandId && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) {
|
||||
if (resolveResult && resolveResult.kind === ResultKind.KbFound && resolveResult.commandId && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) {
|
||||
// don't alert when terminal is opened or closed
|
||||
if (this._storageService.getBoolean(SHOW_TERMINAL_CONFIG_PROMPT_KEY, StorageScope.APPLICATION, true) &&
|
||||
this._hasHadInput &&
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Fake</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; overflow: hidden; width: 100%; height: 100%" role="document">
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; overflow: hidden; width: 100%; height: 100%" role="document">
|
||||
|
||||
@@ -311,8 +311,7 @@ const apiMenus: IAPIMenu[] = [
|
||||
{
|
||||
key: 'editor/lineNumber/context',
|
||||
id: MenuId.EditorLineNumberContext,
|
||||
description: localize('editorLineNumberContext', "The contributed editor line number context menu"),
|
||||
proposed: 'contribEditorLineNumberMenu'
|
||||
description: localize('editorLineNumberContext', "The contributed editor line number context menu")
|
||||
},
|
||||
{
|
||||
key: 'mergeEditor/result/title',
|
||||
|
||||
@@ -14,7 +14,6 @@ export const allApiProposals = Object.freeze({
|
||||
contribCommentThreadAdditionalMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribCommentThreadAdditionalMenu.d.ts',
|
||||
contribEditSessions: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribEditSessions.d.ts',
|
||||
contribEditorContentMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribEditorContentMenu.d.ts',
|
||||
contribEditorLineNumberMenu: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribEditorLineNumberMenu.d.ts',
|
||||
contribLabelFormatterWorkspaceTooltip: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribLabelFormatterWorkspaceTooltip.d.ts',
|
||||
contribMenuBarHome: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribMenuBarHome.d.ts',
|
||||
contribMergeEditorMenus: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.contribMergeEditorMenus.d.ts',
|
||||
|
||||
@@ -25,6 +25,7 @@ import { IViewsService, IViewDescriptorService, ViewContainerLocation } from 'vs
|
||||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||
import { stripIcons } from 'vs/base/common/iconLabels';
|
||||
import { defaultButtonStyles, defaultCheckboxStyles, defaultDialogStyles, defaultInputBoxStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver';
|
||||
|
||||
export class ProgressService extends Disposable implements IProgressService {
|
||||
|
||||
@@ -556,7 +557,7 @@ export class ProgressService extends Disposable implements IProgressService {
|
||||
disableDefaultAction: options.sticky,
|
||||
keyEventProcessor: (event: StandardKeyboardEvent) => {
|
||||
const resolved = this.keybindingService.softDispatch(event, this.layoutService.container);
|
||||
if (resolved?.commandId) {
|
||||
if (resolved && resolved.kind === ResultKind.KbFound && resolved.commandId) {
|
||||
if (!allowableCommands.includes(resolved.commandId)) {
|
||||
EventHelper.stop(event, true);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head id='headID'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Strada </title>
|
||||
<link href="site.css" rel="stylesheet" type="text/css" />
|
||||
<script src="jquery-1.4.1.js"></script>
|
||||
|
||||
@@ -157,7 +157,7 @@ flakySuite('TextSearch-integration', function () {
|
||||
contentPattern: { pattern: 'e' }
|
||||
};
|
||||
|
||||
return doSearchTest(config, 788);
|
||||
return doSearchTest(config, 781);
|
||||
});
|
||||
|
||||
test('Text: e (with excludes)', () => {
|
||||
@@ -167,7 +167,7 @@ flakySuite('TextSearch-integration', function () {
|
||||
excludePattern: { '**/examples': true }
|
||||
};
|
||||
|
||||
return doSearchTest(config, 394);
|
||||
return doSearchTest(config, 387);
|
||||
});
|
||||
|
||||
test('Text: e (with includes)', () => {
|
||||
@@ -344,12 +344,12 @@ flakySuite('TextSearch-integration', function () {
|
||||
|
||||
return doSearchTest(config, 4).then(results => {
|
||||
assert.strictEqual(results.length, 4);
|
||||
assert.strictEqual((<ITextSearchContext>results[0].results![0]).lineNumber, 25);
|
||||
assert.strictEqual((<ITextSearchContext>results[0].results![0]).lineNumber, 24);
|
||||
assert.strictEqual((<ITextSearchContext>results[0].results![0]).text, ' compiler.addUnit(prog,"input.ts");');
|
||||
// assert.strictEqual((<ITextSearchMatch>results[1].results[0]).preview.text, ' compiler.typeCheck();\n'); // See https://github.com/BurntSushi/ripgrep/issues/1095
|
||||
assert.strictEqual((<ITextSearchContext>results[2].results![0]).lineNumber, 27);
|
||||
assert.strictEqual((<ITextSearchContext>results[2].results![0]).lineNumber, 26);
|
||||
assert.strictEqual((<ITextSearchContext>results[2].results![0]).text, ' compiler.emit();');
|
||||
assert.strictEqual((<ITextSearchContext>results[3].results![0]).lineNumber, 28);
|
||||
assert.strictEqual((<ITextSearchContext>results[3].results![0]).lineNumber, 27);
|
||||
assert.strictEqual((<ITextSearchContext>results[3].results![0]).text, '');
|
||||
});
|
||||
});
|
||||
|
||||
Vendored
+5
-5
@@ -6499,7 +6499,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Outputs the given trace message to the channel. Use this method to log verbose information.
|
||||
*
|
||||
* The message is only loggeed if the channel is configured to display {@link LogLevel.Trace trace} log level.
|
||||
* The message is only logged if the channel is configured to display {@link LogLevel.Trace trace} log level.
|
||||
*
|
||||
* @param message trace message to log
|
||||
*/
|
||||
@@ -6508,7 +6508,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Outputs the given debug message to the channel.
|
||||
*
|
||||
* The message is only loggeed if the channel is configured to display {@link LogLevel.Debug debug} log level or lower.
|
||||
* The message is only logged if the channel is configured to display {@link LogLevel.Debug debug} log level or lower.
|
||||
*
|
||||
* @param message debug message to log
|
||||
*/
|
||||
@@ -6517,7 +6517,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Outputs the given information message to the channel.
|
||||
*
|
||||
* The message is only loggeed if the channel is configured to display {@link LogLevel.Info info} log level or lower.
|
||||
* The message is only logged if the channel is configured to display {@link LogLevel.Info info} log level or lower.
|
||||
*
|
||||
* @param message info message to log
|
||||
*/
|
||||
@@ -6526,7 +6526,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Outputs the given warning message to the channel.
|
||||
*
|
||||
* The message is only loggeed if the channel is configured to display {@link LogLevel.Warning warning} log level or lower.
|
||||
* The message is only logged if the channel is configured to display {@link LogLevel.Warning warning} log level or lower.
|
||||
*
|
||||
* @param message warning message to log
|
||||
*/
|
||||
@@ -6535,7 +6535,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Outputs the given error or error message to the channel.
|
||||
*
|
||||
* The message is only loggeed if the channel is configured to display {@link LogLevel.Error error} log level or lower.
|
||||
* The message is only logged if the channel is configured to display {@link LogLevel.Error error} log level or lower.
|
||||
*
|
||||
* @param error Error or error message to log
|
||||
*/
|
||||
|
||||
@@ -1153,11 +1153,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/windows-foreground-love/-/windows-foreground-love-0.3.0.tgz#26bc230b2568aa7ab7c56d35bb5653c0a6965a42"
|
||||
integrity sha512-tFUVA/fiofNqOh6lZlymvQiQYPY+cZXZPR9mn9wN6/KS8uwx0zgH4Ij/jmFyRYr+x+DGZWEIeknS2BMi7FZJAQ==
|
||||
|
||||
"@types/windows-mutex@^0.4.0":
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/windows-mutex/-/windows-mutex-0.4.0.tgz#d27070418aa26047c6c860c704952ff26aeb961b"
|
||||
integrity sha512-zUMH4nutIURLARU6f10Ls6XcZWhUkwmzVEALs26dt1ZbaLv/qxsGdYiePUbwhQmrQUp3EPZ1HxopWpzzC8ot5A==
|
||||
|
||||
"@types/windows-process-tree@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/windows-process-tree/-/windows-process-tree-0.2.0.tgz#2fa205c838a8ef0a07697cd747c954653978d22c"
|
||||
@@ -1391,6 +1386,14 @@
|
||||
dependencies:
|
||||
node-addon-api "^3.0.2"
|
||||
|
||||
"@vscode/windows-mutex@0.4.2":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/windows-mutex/-/windows-mutex-0.4.2.tgz#3f796896c3bc2cf32bfe7148e608edb0cb7247db"
|
||||
integrity sha512-7MSBH22cI7OwxXImjJ3VJ7QeHrEbumtyi/xqTgv6xqZCIZfUk/eu5MMBD2Vkehut8dGZU4xIjqt5AGdm0uPixQ==
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
nan "^2.14.0"
|
||||
|
||||
"@vscode/windows-registry@1.0.6":
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.0.6.tgz#8b9fb9a55bf5a0be4ea11849c45ae94c6910e3e4"
|
||||
@@ -10842,14 +10845,6 @@ windows-foreground-love@0.5.0:
|
||||
resolved "https://registry.yarnpkg.com/windows-foreground-love/-/windows-foreground-love-0.5.0.tgz#7672b04eb05f934a6543cacdc3cd16ff34e3cb10"
|
||||
integrity sha512-yjBwmKEmQBDk3Z7yg/U9hizGWat8C6Pe4MQWl5bN6mvPU81Bt6HV2k/6mGlK3ETJLW1hCLhYx2wcGh+ykUUCyA==
|
||||
|
||||
windows-mutex@0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/windows-mutex/-/windows-mutex-0.4.1.tgz#2eccdfc312e15e7f212fb16280f060fc6b5f00cd"
|
||||
integrity sha512-RW1xN6yzw8hAcfy1BKVClhJZg/PzuNz4Qz+CNhYmmdzJiwKSU9CqvVcmAvNrtdinNkXfSqTZVBVh5kUATg6xOA==
|
||||
dependencies:
|
||||
bindings "^1.2.1"
|
||||
nan "^2.14.0"
|
||||
|
||||
windows-process-tree@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/windows-process-tree/-/windows-process-tree-0.4.0.tgz#31ac49c5da557e628ce7e37a5800972173d3349a"
|
||||
|
||||
Reference in New Issue
Block a user