keybindingResolver.ts ×18

Frontier kind: Code frontier

unlabeled · c_bcce3e33e47b

591 tests · 7420 LOC · 36 files · introduces 0 tests · 90 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
18 ranges90 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1074 ranges7420 lines · 36 files · Browse complete extent
All tests (intent)
591 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 90 introduced LOC across 18 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/keybinding/common/keybindingResolver.ts 90 introduced LOC · 18 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- keybindingResolver.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { ContextKeyExpression, ContextKeyExprType, IContext, IContextKeyService, implies } from '../../contextkey/common/contextkey.js';
7 > import { ResolvedKeybindingItem } from './resolvedKeybindingItem.js';
8 >
9 > //#region resolution-result
10 >
11 > export const enum ResultKind {
12 > /** No keybinding found this sequence of chords */
13 > NoMatchingKb,
14 >
15 > /** There're several keybindings that have the given sequence of chords as a prefix */
16 > MoreChordsNeeded,
17 >
18 > /** A single keybinding found to be dispatched/invoked */
19 > KbFound
20 > }
21 >
22 > export type ResolutionResult =
23 > | { kind: ResultKind.NoMatchingKb }
24 > | { kind: ResultKind.MoreChordsNeeded }
25 > | { kind: ResultKind.KbFound; commandId: string | null; commandArgs: any; isBubble: boolean };
26 >
27 >
28 > // util definitions to make working with the above types easier within this module:
29 >
30 > export const NoMatchingKb: ResolutionResult = { kind: ResultKind.NoMatchingKb };
31 > const MoreChordsNeeded: ResolutionResult = { kind: ResultKind.MoreChordsNeeded };
32 function KbFound(commandId: string | null, commandArgs: any, isBubble: boolean): ResolutionResult {
33 return { kind: ResultKind.KbFound, commandId, commandArgs, isBubble };
34 }
36 > //#endregion
37 >
38 > /**
39 > * Stores mappings from keybindings to commands and from commands to keybindings.
40 > * Given a sequence of chords, `resolve`s which keybinding it matches
41 > */
42 > export class KeybindingResolver {
43 > private readonly _log: (str: string) => void;
44 > private readonly _defaultKeybindings: ResolvedKeybindingItem[];
45 > private readonly _keybindings: ResolvedKeybindingItem[];
46 > private readonly _defaultBoundCommands: Map</* commandId */ string, boolean>;
47 > private readonly _map: Map</* 1st chord's keypress */ string, ResolvedKeybindingItem[]>;
48 > private readonly _lookupMap: Map</* commandId */ string, ResolvedKeybindingItem[]>;
49 >
50 > constructor(
51 /** built-in and extension-provided keybindings */
52 defaultKeybindings: ResolvedKeybindingItem[],
88 }
89 }
91 > private static _isTargetedForRemoval(defaultKb: ResolvedKeybindingItem, keypress: string[] | null, when: ContextKeyExpression | undefined): boolean {
92 if (keypress) {
93 for (let i = 0; i < keypress.length; i++) {
118
119 }
121 > /**
122 > * Looks for rules containing "-commandId" and removes them.
123 > */
124 > public static handleRemovals(rules: ResolvedKeybindingItem[]): ResolvedKeybindingItem[] {
125 // Do a first pass and construct a hash-map for removals
126 const removals = new Map</* commandId */ string, ResolvedKeybindingItem[]>();
174 return result;
175 }
177 > private _addKeyPress(keypress: string, item: ResolvedKeybindingItem): void {
178
179 const conflicts = this._map.get(keypress);
217 this._addToLookupMap(item);
218 }
220 > private _addToLookupMap(item: ResolvedKeybindingItem): void {
221 if (!item.command) {
222 return;
231 }
232 }
234 > private _removeFromLookupMap(item: ResolvedKeybindingItem): void {
235 if (!item.command) {
236 return;
247 }
248 }
250 > /**
251 > * Returns true if it is provable `a` implies `b`.
252 > */
253 > public static whenIsEntirelyIncluded(a: ContextKeyExpression | null | undefined, b: ContextKeyExpression | null | undefined): boolean {
254 if (!b || b.type === ContextKeyExprType.True) {
255 return true;
261 return implies(a, b);
262 }
264 > public getDefaultBoundCommands(): Map<string, boolean> {
265 return this._defaultBoundCommands;
266 }
268 > public getDefaultKeybindings(): readonly ResolvedKeybindingItem[] {
269 return this._defaultKeybindings;
270 }
272 > public getKeybindings(): readonly ResolvedKeybindingItem[] {
273 return this._keybindings;
274 }
276 > public lookupKeybindings(commandId: string): ResolvedKeybindingItem[] {
277 const items = this._lookupMap.get(commandId);
278 if (typeof items === 'undefined' || items.length === 0) {
288 return result;
289 }
291 > public lookupPrimaryKeybinding(commandId: string, context: IContextKeyService, enforceContextCheck = false): ResolvedKeybindingItem | null {
292 const items = this._lookupMap.get(commandId);
293 if (typeof items === 'undefined' || items.length === 0) {
311 return items[items.length - 1];
312 }
314 > /**
315 > * Looks up a keybinding trigged as a result of pressing a sequence of chords - `[...currentChords, keypress]`
316 > *
317 > * Example: resolving 3 chords pressed sequentially - `cmd+k cmd+p cmd+i`:
318 > * `currentChords = [ 'cmd+k' , 'cmd+p' ]` and `keypress = `cmd+i` - last pressed chord
319 > */
320 > public resolve(context: IContext, currentChords: string[], keypress: string): ResolutionResult {
321
322 const pressedChords = [...currentChords, keypress];
377 return KbFound(result.command, result.commandArgs, result.bubble);
378 }
380 > private _findCommand(context: IContext, matches: ResolvedKeybindingItem[]): ResolvedKeybindingItem | null {
381 for (let i = matches.length - 1; i >= 0; i--) {
382 const k = matches[i];
391 return null;
392 }
394 > private static _contextMatchesRules(context: IContext, rules: ContextKeyExpression | null | undefined): boolean {
395 if (!rules) {
396 return true;
398 return rules.evaluate(context);
399 }
401 >
402 function printWhenExplanation(when: ContextKeyExpression | undefined): string {
403 if (!when) {
406 return `${when.serialize()}`;
407 }
409 function printSourceExplanation(kb: ResolvedKeybindingItem): string {
410 return (