UNPKG

29.1 kBJavaScriptView Raw
1"use strict";
2// *****************************************************************************
3// Copyright (C) 2017 TypeFox and others.
4//
5// This program and the accompanying materials are made available under the
6// terms of the Eclipse Public License v. 2.0 which is available at
7// http://www.eclipse.org/legal/epl-2.0.
8//
9// This Source Code may also be made available under the following Secondary
10// Licenses when the conditions for such availability set forth in the Eclipse
11// Public License v. 2.0 are satisfied: GNU General Public License, version 2
12// with the GNU Classpath Exception which is available at
13// https://www.gnu.org/software/classpath/license.html.
14//
15// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16// *****************************************************************************
17var KeybindingRegistry_1;
18Object.defineProperty(exports, "__esModule", { value: true });
19exports.KeybindingRegistry = exports.KeybindingContexts = exports.KeybindingContext = exports.KeybindingContribution = exports.Keybinding = exports.KeybindingScope = void 0;
20const tslib_1 = require("tslib");
21const inversify_1 = require("inversify");
22const os_1 = require("../common/os");
23const event_1 = require("../common/event");
24const command_1 = require("../common/command");
25const disposable_1 = require("../common/disposable");
26const keys_1 = require("./keyboard/keys");
27const keyboard_layout_service_1 = require("./keyboard/keyboard-layout-service");
28const contribution_provider_1 = require("../common/contribution-provider");
29const logger_1 = require("../common/logger");
30const status_bar_1 = require("./status-bar/status-bar");
31const context_key_service_1 = require("./context-key-service");
32const core_preferences_1 = require("./core-preferences");
33const common = require("../common/keybinding");
34const nls_1 = require("../common/nls");
35var KeybindingScope;
36(function (KeybindingScope) {
37 KeybindingScope[KeybindingScope["DEFAULT"] = 0] = "DEFAULT";
38 KeybindingScope[KeybindingScope["USER"] = 1] = "USER";
39 KeybindingScope[KeybindingScope["WORKSPACE"] = 2] = "WORKSPACE";
40 KeybindingScope[KeybindingScope["END"] = 3] = "END";
41})(KeybindingScope = exports.KeybindingScope || (exports.KeybindingScope = {}));
42(function (KeybindingScope) {
43 KeybindingScope.length = KeybindingScope.END - KeybindingScope.DEFAULT;
44})(KeybindingScope = exports.KeybindingScope || (exports.KeybindingScope = {}));
45exports.Keybinding = common.Keybinding;
46exports.KeybindingContribution = Symbol('KeybindingContribution');
47exports.KeybindingContext = Symbol('KeybindingContext');
48var KeybindingContexts;
49(function (KeybindingContexts) {
50 KeybindingContexts.NOOP_CONTEXT = {
51 id: 'noop.keybinding.context',
52 isEnabled: () => true
53 };
54 KeybindingContexts.DEFAULT_CONTEXT = {
55 id: 'default.keybinding.context',
56 isEnabled: () => false
57 };
58})(KeybindingContexts = exports.KeybindingContexts || (exports.KeybindingContexts = {}));
59let KeybindingRegistry = KeybindingRegistry_1 = class KeybindingRegistry {
60 constructor() {
61 this.keySequence = [];
62 this.contexts = {};
63 this.keymaps = [...Array(KeybindingScope.length)].map(() => []);
64 this.keybindingsChanged = new event_1.Emitter();
65 this.toResetKeymap = new Map();
66 }
67 async onStart() {
68 await this.keyboardLayoutService.initialize();
69 this.keyboardLayoutService.onKeyboardLayoutChanged(newLayout => {
70 this.clearResolvedKeybindings();
71 this.keybindingsChanged.fire(undefined);
72 });
73 this.registerContext(KeybindingContexts.NOOP_CONTEXT);
74 this.registerContext(KeybindingContexts.DEFAULT_CONTEXT);
75 this.registerContext(...this.contextProvider.getContributions());
76 for (const contribution of this.contributions.getContributions()) {
77 contribution.registerKeybindings(this);
78 }
79 }
80 /**
81 * Event that is fired when the resolved keybindings change due to a different keyboard layout
82 * or when a new keymap is being set
83 */
84 get onKeybindingsChanged() {
85 return this.keybindingsChanged.event;
86 }
87 /**
88 * Registers the keybinding context arguments into the application. Fails when an already registered
89 * context is being registered.
90 *
91 * @param contexts the keybinding contexts to register into the application.
92 */
93 registerContext(...contexts) {
94 for (const context of contexts) {
95 const { id } = context;
96 if (this.contexts[id]) {
97 this.logger.error(`A keybinding context with ID ${id} is already registered.`);
98 }
99 else {
100 this.contexts[id] = context;
101 }
102 }
103 }
104 /**
105 * Register a default keybinding to the registry.
106 *
107 * Keybindings registered later have higher priority during evaluation.
108 *
109 * @param binding the keybinding to be registered
110 */
111 registerKeybinding(binding) {
112 return this.doRegisterKeybinding(binding);
113 }
114 /**
115 * Register multiple default keybindings to the registry
116 *
117 * @param bindings An array of keybinding to be registered
118 */
119 registerKeybindings(...bindings) {
120 return this.doRegisterKeybindings(bindings, KeybindingScope.DEFAULT);
121 }
122 unregisterKeybinding(arg) {
123 const keymap = this.keymaps[KeybindingScope.DEFAULT];
124 const filter = command_1.Command.is(arg)
125 ? ({ command }) => command === arg.id
126 : ({ keybinding }) => exports.Keybinding.is(arg)
127 ? keybinding === arg.keybinding
128 : keybinding === arg;
129 for (const binding of keymap.filter(filter)) {
130 const idx = keymap.indexOf(binding);
131 if (idx !== -1) {
132 keymap.splice(idx, 1);
133 }
134 }
135 }
136 doRegisterKeybindings(bindings, scope = KeybindingScope.DEFAULT) {
137 const toDispose = new disposable_1.DisposableCollection();
138 for (const binding of bindings) {
139 toDispose.push(this.doRegisterKeybinding(binding, scope));
140 }
141 return toDispose;
142 }
143 doRegisterKeybinding(binding, scope = KeybindingScope.DEFAULT) {
144 try {
145 this.resolveKeybinding(binding);
146 const scoped = Object.assign(binding, { scope });
147 this.insertBindingIntoScope(scoped, scope);
148 return disposable_1.Disposable.create(() => {
149 const index = this.keymaps[scope].indexOf(scoped);
150 if (index !== -1) {
151 this.keymaps[scope].splice(index, 1);
152 }
153 });
154 }
155 catch (error) {
156 this.logger.warn(`Could not register keybinding:\n ${common.Keybinding.stringify(binding)}\n${error}`);
157 return disposable_1.Disposable.NULL;
158 }
159 }
160 /**
161 * Ensures that keybindings are inserted in order of increasing length of binding to ensure that if a
162 * user triggers a short keybinding (e.g. ctrl+k), the UI won't wait for a longer one (e.g. ctrl+k enter)
163 */
164 insertBindingIntoScope(item, scope) {
165 const scopedKeymap = this.keymaps[scope];
166 const getNumberOfKeystrokes = (binding) => { var _a, _b; return ((_b = (_a = binding.keybinding.trim().match(/\s/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) + 1; };
167 const numberOfKeystrokesInBinding = getNumberOfKeystrokes(item);
168 const indexOfFirstItemWithEqualStrokes = scopedKeymap.findIndex(existingBinding => getNumberOfKeystrokes(existingBinding) === numberOfKeystrokesInBinding);
169 if (indexOfFirstItemWithEqualStrokes > -1) {
170 scopedKeymap.splice(indexOfFirstItemWithEqualStrokes, 0, item);
171 }
172 else {
173 scopedKeymap.push(item);
174 }
175 }
176 /**
177 * Ensure that the `resolved` property of the given binding is set by calling the KeyboardLayoutService.
178 */
179 resolveKeybinding(binding) {
180 if (!binding.resolved) {
181 const sequence = keys_1.KeySequence.parse(binding.keybinding);
182 binding.resolved = sequence.map(code => this.keyboardLayoutService.resolveKeyCode(code));
183 }
184 return binding.resolved;
185 }
186 /**
187 * Clear all `resolved` properties of registered keybindings so the KeyboardLayoutService is called
188 * again to resolve them. This is necessary when the user's keyboard layout has changed.
189 */
190 clearResolvedKeybindings() {
191 for (let i = KeybindingScope.DEFAULT; i < KeybindingScope.END; i++) {
192 const bindings = this.keymaps[i];
193 for (let j = 0; j < bindings.length; j++) {
194 const binding = bindings[j];
195 binding.resolved = undefined;
196 }
197 }
198 }
199 /**
200 * Checks whether a colliding {@link common.Keybinding} exists in a specific scope.
201 * @param binding the keybinding to check
202 * @param scope the keybinding scope to check
203 * @returns true if there is a colliding keybinding
204 */
205 containsKeybindingInScope(binding, scope = KeybindingScope.USER) {
206 const bindingKeySequence = this.resolveKeybinding(binding);
207 const collisions = this.getKeySequenceCollisions(this.getUsableBindings(this.keymaps[scope]), bindingKeySequence)
208 .filter(b => b.context === binding.context && !b.when && !binding.when);
209 if (collisions.full.length > 0) {
210 return true;
211 }
212 if (collisions.partial.length > 0) {
213 return true;
214 }
215 if (collisions.shadow.length > 0) {
216 return true;
217 }
218 return false;
219 }
220 /**
221 * Get a user visible representation of a {@link common.Keybinding}.
222 * @returns an array of strings representing all elements of the {@link KeySequence} defined by the {@link common.Keybinding}
223 * @param keybinding the keybinding
224 * @param separator the separator to be used to stringify {@link KeyCode}s that are part of the {@link KeySequence}
225 */
226 acceleratorFor(keybinding, separator = ' ', asciiOnly = false) {
227 const bindingKeySequence = this.resolveKeybinding(keybinding);
228 return this.acceleratorForSequence(bindingKeySequence, separator, asciiOnly);
229 }
230 /**
231 * Get a user visible representation of a {@link KeySequence}.
232 * @returns an array of strings representing all elements of the {@link KeySequence}
233 * @param keySequence the keysequence
234 * @param separator the separator to be used to stringify {@link KeyCode}s that are part of the {@link KeySequence}
235 */
236 acceleratorForSequence(keySequence, separator = ' ', asciiOnly = false) {
237 return keySequence.map(keyCode => this.acceleratorForKeyCode(keyCode, separator, asciiOnly));
238 }
239 /**
240 * Get a user visible representation of a key code (a key with modifiers).
241 * @returns a string representing the {@link KeyCode}
242 * @param keyCode the keycode
243 * @param separator the separator used to separate keys (key and modifiers) in the returning string
244 * @param asciiOnly if `true`, no special characters will be substituted into the string returned. Ensures correct keyboard shortcuts in Electron menus.
245 */
246 acceleratorForKeyCode(keyCode, separator = ' ', asciiOnly = false) {
247 return this.componentsForKeyCode(keyCode, asciiOnly).join(separator);
248 }
249 componentsForKeyCode(keyCode, asciiOnly = false) {
250 const keyCodeResult = [];
251 const useSymbols = os_1.isOSX && !asciiOnly;
252 if (keyCode.meta && os_1.isOSX) {
253 keyCodeResult.push(useSymbols ? '⌘' : 'Cmd');
254 }
255 if (keyCode.ctrl) {
256 keyCodeResult.push(useSymbols ? '⌃' : 'Ctrl');
257 }
258 if (keyCode.alt) {
259 keyCodeResult.push(useSymbols ? '⌥' : 'Alt');
260 }
261 if (keyCode.shift) {
262 keyCodeResult.push(useSymbols ? '⇧' : 'Shift');
263 }
264 if (keyCode.key) {
265 keyCodeResult.push(this.acceleratorForKey(keyCode.key, asciiOnly));
266 }
267 return keyCodeResult;
268 }
269 /**
270 * @param asciiOnly if `true`, no special characters will be substituted into the string returned. Ensures correct keyboard shortcuts in Electron menus.
271 *
272 * Return a user visible representation of a single key.
273 */
274 acceleratorForKey(key, asciiOnly = false) {
275 if (os_1.isOSX && !asciiOnly) {
276 if (key === keys_1.Key.ARROW_LEFT) {
277 return '←';
278 }
279 if (key === keys_1.Key.ARROW_RIGHT) {
280 return '→';
281 }
282 if (key === keys_1.Key.ARROW_UP) {
283 return '↑';
284 }
285 if (key === keys_1.Key.ARROW_DOWN) {
286 return '↓';
287 }
288 }
289 const keyString = this.keyboardLayoutService.getKeyboardCharacter(key);
290 if (key.keyCode >= keys_1.Key.KEY_A.keyCode && key.keyCode <= keys_1.Key.KEY_Z.keyCode ||
291 key.keyCode >= keys_1.Key.F1.keyCode && key.keyCode <= keys_1.Key.F24.keyCode) {
292 return keyString.toUpperCase();
293 }
294 else if (keyString.length > 1) {
295 return keyString.charAt(0).toUpperCase() + keyString.slice(1);
296 }
297 else {
298 return keyString;
299 }
300 }
301 /**
302 * Finds collisions for a key sequence inside a list of bindings (error-free)
303 *
304 * @param bindings the reference bindings
305 * @param candidate the sequence to match
306 */
307 getKeySequenceCollisions(bindings, candidate) {
308 const result = new KeybindingRegistry_1.KeybindingsResult();
309 for (const binding of bindings) {
310 try {
311 const bindingKeySequence = this.resolveKeybinding(binding);
312 const compareResult = keys_1.KeySequence.compare(candidate, bindingKeySequence);
313 switch (compareResult) {
314 case keys_1.KeySequence.CompareResult.FULL: {
315 result.full.push(binding);
316 break;
317 }
318 case keys_1.KeySequence.CompareResult.PARTIAL: {
319 result.partial.push(binding);
320 break;
321 }
322 case keys_1.KeySequence.CompareResult.SHADOW: {
323 result.shadow.push(binding);
324 break;
325 }
326 }
327 }
328 catch (error) {
329 this.logger.warn(error);
330 }
331 }
332 return result;
333 }
334 /**
335 * Get all keybindings associated to a commandId.
336 *
337 * @param commandId The ID of the command for which we are looking for keybindings.
338 * @returns an array of {@link ScopedKeybinding}
339 */
340 getKeybindingsForCommand(commandId) {
341 const result = [];
342 const disabledBindings = new Set();
343 for (let scope = KeybindingScope.END - 1; scope >= KeybindingScope.DEFAULT; scope--) {
344 this.keymaps[scope].forEach(binding => {
345 var _a;
346 if ((_a = binding.command) === null || _a === void 0 ? void 0 : _a.startsWith('-')) {
347 disabledBindings.add(JSON.stringify({ command: binding.command.substring(1), binding: binding.keybinding, context: binding.context, when: binding.when }));
348 }
349 else {
350 const command = this.commandRegistry.getCommand(binding.command);
351 if (command
352 && command.id === commandId
353 && !disabledBindings.has(JSON.stringify({ command: binding.command, binding: binding.keybinding, context: binding.context, when: binding.when }))) {
354 result.push({ ...binding, scope });
355 }
356 }
357 });
358 }
359 return result;
360 }
361 isActive(binding) {
362 /* Pseudo commands like "passthrough" are always active (and not found
363 in the command registry). */
364 if (this.isPseudoCommand(binding.command)) {
365 return true;
366 }
367 const command = this.commandRegistry.getCommand(binding.command);
368 return !!command && !!this.commandRegistry.getActiveHandler(command.id);
369 }
370 /**
371 * Tries to execute a keybinding.
372 *
373 * @param binding to execute
374 * @param event keyboard event.
375 */
376 executeKeyBinding(binding, event) {
377 if (this.isPseudoCommand(binding.command)) {
378 /* Don't do anything, let the event propagate. */
379 }
380 else {
381 const command = this.commandRegistry.getCommand(binding.command);
382 if (command) {
383 if (this.commandRegistry.isEnabled(binding.command, binding.args)) {
384 this.commandRegistry.executeCommand(binding.command, binding.args)
385 .catch(e => console.error('Failed to execute command:', e));
386 }
387 /* Note that if a keybinding is in context but the command is
388 not active we still stop the processing here. */
389 event.preventDefault();
390 event.stopPropagation();
391 }
392 }
393 }
394 /**
395 * Only execute if it has no context (global context) or if we're in that context.
396 */
397 isEnabled(binding, event) {
398 return this.isEnabledInScope(binding, event.target);
399 }
400 isEnabledInScope(binding, target) {
401 const context = binding.context && this.contexts[binding.context];
402 if (binding.command && (!this.isPseudoCommand(binding.command) && !this.commandRegistry.isEnabled(binding.command, binding.args))) {
403 return false;
404 }
405 if (context && !context.isEnabled(binding)) {
406 return false;
407 }
408 if (binding.when && !this.whenContextService.match(binding.when, target)) {
409 return false;
410 }
411 return true;
412 }
413 dispatchCommand(id, target) {
414 const keybindings = this.getKeybindingsForCommand(id);
415 if (keybindings.length) {
416 for (const keyCode of this.resolveKeybinding(keybindings[0])) {
417 this.dispatchKeyDown(keyCode, target);
418 }
419 }
420 }
421 dispatchKeyDown(input, target = document.activeElement || window) {
422 const eventInit = this.asKeyboardEventInit(input);
423 const emulatedKeyboardEvent = new KeyboardEvent('keydown', eventInit);
424 target.dispatchEvent(emulatedKeyboardEvent);
425 }
426 asKeyboardEventInit(input) {
427 if (typeof input === 'string') {
428 return this.asKeyboardEventInit(keys_1.KeyCode.createKeyCode(input));
429 }
430 if (input instanceof keys_1.KeyCode) {
431 return {
432 metaKey: input.meta,
433 shiftKey: input.shift,
434 altKey: input.alt,
435 ctrlKey: input.ctrl,
436 code: input.key && input.key.code,
437 key: (input && input.character) || (input.key && input.key.code),
438 keyCode: input.key && input.key.keyCode
439 };
440 }
441 return input;
442 }
443 registerEventListeners(win) {
444 /* vvv HOTFIX begin vvv
445 *
446 * This is a hotfix against issues eclipse/theia#6459 and gitpod-io/gitpod#875 .
447 * It should be reverted after Theia was updated to the newer Monaco.
448 */
449 let inComposition = false;
450 const compositionStart = () => {
451 inComposition = true;
452 };
453 win.document.addEventListener('compositionstart', compositionStart);
454 const compositionEnd = () => {
455 inComposition = false;
456 };
457 win.document.addEventListener('compositionend', compositionEnd);
458 const keydown = (event) => {
459 if (inComposition !== true) {
460 this.run(event);
461 }
462 };
463 win.document.addEventListener('keydown', keydown, true);
464 return disposable_1.Disposable.create(() => {
465 win.document.removeEventListener('compositionstart', compositionStart);
466 win.document.removeEventListener('compositionend', compositionEnd);
467 win.document.removeEventListener('keydown', keydown);
468 });
469 }
470 /**
471 * Run the command matching to the given keyboard event.
472 */
473 run(event) {
474 if (event.defaultPrevented) {
475 return;
476 }
477 const eventDispatch = this.corePreferences['keyboard.dispatch'];
478 const keyCode = keys_1.KeyCode.createKeyCode(event, eventDispatch);
479 /* Keycode is only a modifier, next keycode will be modifier + key.
480 Ignore this one. */
481 if (keyCode.isModifierOnly()) {
482 return;
483 }
484 this.keyboardLayoutService.validateKeyCode(keyCode);
485 this.keySequence.push(keyCode);
486 const match = this.matchKeybinding(this.keySequence, event);
487 if (match && match.kind === 'partial') {
488 /* Accumulate the keysequence */
489 event.preventDefault();
490 event.stopPropagation();
491 this.statusBar.setElement('keybinding-status', {
492 text: nls_1.nls.localize('theia/core/keybindingStatus', '{0} was pressed, waiting for more keys', `(${this.acceleratorForSequence(this.keySequence, '+')})`),
493 alignment: status_bar_1.StatusBarAlignment.LEFT,
494 priority: 2
495 });
496 }
497 else {
498 if (match && match.kind === 'full') {
499 this.executeKeyBinding(match.binding, event);
500 }
501 this.keySequence = [];
502 this.statusBar.removeElement('keybinding-status');
503 }
504 }
505 /**
506 * Match first binding in the current context.
507 * Keybindings ordered by a scope and by a registration order within the scope.
508 *
509 * FIXME:
510 * This method should run very fast since it happens on each keystroke. We should reconsider how keybindings are stored.
511 * It should be possible to look up full and partial keybinding for given key sequence for constant time using some kind of tree.
512 * Such tree should not contain disabled keybindings and be invalidated whenever the registry is changed.
513 */
514 matchKeybinding(keySequence, event) {
515 let disabled;
516 const isEnabled = (binding) => {
517 if (event && !this.isEnabled(binding, event)) {
518 return false;
519 }
520 const { command, context, when, keybinding } = binding;
521 if (!this.isUsable(binding)) {
522 disabled = disabled || new Set();
523 disabled.add(JSON.stringify({ command: command.substring(1), context, when, keybinding }));
524 return false;
525 }
526 return !(disabled === null || disabled === void 0 ? void 0 : disabled.has(JSON.stringify({ command, context, when, keybinding })));
527 };
528 for (let scope = KeybindingScope.END; --scope >= KeybindingScope.DEFAULT;) {
529 for (const binding of this.keymaps[scope]) {
530 const resolved = this.resolveKeybinding(binding);
531 const compareResult = keys_1.KeySequence.compare(keySequence, resolved);
532 if (compareResult === keys_1.KeySequence.CompareResult.FULL && isEnabled(binding)) {
533 return { kind: 'full', binding };
534 }
535 if (compareResult === keys_1.KeySequence.CompareResult.PARTIAL && isEnabled(binding)) {
536 return { kind: 'partial', binding };
537 }
538 }
539 }
540 return undefined;
541 }
542 /**
543 * Returns true if the binding is usable
544 * @param binding Binding to be checked
545 */
546 isUsable(binding) {
547 return binding.command.charAt(0) !== '-';
548 }
549 /**
550 * Return a new filtered array containing only the usable bindings among the input bindings
551 * @param bindings Bindings to filter
552 */
553 getUsableBindings(bindings) {
554 return bindings.filter(binding => this.isUsable(binding));
555 }
556 /**
557 * Return true of string a pseudo-command id, in other words a command id
558 * that has a special meaning and that we won't find in the command
559 * registry.
560 *
561 * @param commandId commandId to test
562 */
563 isPseudoCommand(commandId) {
564 return commandId === KeybindingRegistry_1.PASSTHROUGH_PSEUDO_COMMAND;
565 }
566 /**
567 * Sets a new keymap replacing all existing {@link common.Keybinding}s in the given scope.
568 * @param scope the keybinding scope
569 * @param bindings an array containing the new {@link common.Keybinding}s
570 */
571 setKeymap(scope, bindings) {
572 this.resetKeybindingsForScope(scope);
573 this.toResetKeymap.set(scope, this.doRegisterKeybindings(bindings, scope));
574 this.keybindingsChanged.fire(undefined);
575 }
576 /**
577 * Reset keybindings for a specific scope
578 * @param scope scope to reset the keybindings for
579 */
580 resetKeybindingsForScope(scope) {
581 const toReset = this.toResetKeymap.get(scope);
582 if (toReset) {
583 toReset.dispose();
584 }
585 }
586 /**
587 * Reset keybindings for all scopes(only leaves the default keybindings mapped)
588 */
589 resetKeybindings() {
590 for (let i = KeybindingScope.DEFAULT + 1; i < KeybindingScope.END; i++) {
591 this.keymaps[i] = [];
592 }
593 }
594 /**
595 * Get all {@link common.Keybinding}s for a {@link KeybindingScope}.
596 * @returns an array of {@link common.ScopedKeybinding}
597 * @param scope the keybinding scope to retrieve the {@link common.Keybinding}s for.
598 */
599 getKeybindingsByScope(scope) {
600 return this.keymaps[scope];
601 }
602};
603KeybindingRegistry.PASSTHROUGH_PSEUDO_COMMAND = 'passthrough';
604(0, tslib_1.__decorate)([
605 (0, inversify_1.inject)(core_preferences_1.CorePreferences),
606 (0, tslib_1.__metadata)("design:type", Object)
607], KeybindingRegistry.prototype, "corePreferences", void 0);
608(0, tslib_1.__decorate)([
609 (0, inversify_1.inject)(keyboard_layout_service_1.KeyboardLayoutService),
610 (0, tslib_1.__metadata)("design:type", keyboard_layout_service_1.KeyboardLayoutService)
611], KeybindingRegistry.prototype, "keyboardLayoutService", void 0);
612(0, tslib_1.__decorate)([
613 (0, inversify_1.inject)(contribution_provider_1.ContributionProvider),
614 (0, inversify_1.named)(exports.KeybindingContext),
615 (0, tslib_1.__metadata)("design:type", Object)
616], KeybindingRegistry.prototype, "contextProvider", void 0);
617(0, tslib_1.__decorate)([
618 (0, inversify_1.inject)(command_1.CommandRegistry),
619 (0, tslib_1.__metadata)("design:type", command_1.CommandRegistry)
620], KeybindingRegistry.prototype, "commandRegistry", void 0);
621(0, tslib_1.__decorate)([
622 (0, inversify_1.inject)(contribution_provider_1.ContributionProvider),
623 (0, inversify_1.named)(exports.KeybindingContribution),
624 (0, tslib_1.__metadata)("design:type", Object)
625], KeybindingRegistry.prototype, "contributions", void 0);
626(0, tslib_1.__decorate)([
627 (0, inversify_1.inject)(status_bar_1.StatusBar),
628 (0, tslib_1.__metadata)("design:type", Object)
629], KeybindingRegistry.prototype, "statusBar", void 0);
630(0, tslib_1.__decorate)([
631 (0, inversify_1.inject)(logger_1.ILogger),
632 (0, tslib_1.__metadata)("design:type", Object)
633], KeybindingRegistry.prototype, "logger", void 0);
634(0, tslib_1.__decorate)([
635 (0, inversify_1.inject)(context_key_service_1.ContextKeyService),
636 (0, tslib_1.__metadata)("design:type", Object)
637], KeybindingRegistry.prototype, "whenContextService", void 0);
638KeybindingRegistry = KeybindingRegistry_1 = (0, tslib_1.__decorate)([
639 (0, inversify_1.injectable)()
640], KeybindingRegistry);
641exports.KeybindingRegistry = KeybindingRegistry;
642(function (KeybindingRegistry) {
643 class KeybindingsResult {
644 constructor() {
645 this.full = [];
646 this.partial = [];
647 this.shadow = [];
648 }
649 /**
650 * Merge two results together inside `this`
651 *
652 * @param other the other KeybindingsResult to merge with
653 * @return this
654 */
655 merge(other) {
656 this.full.push(...other.full);
657 this.partial.push(...other.partial);
658 this.shadow.push(...other.shadow);
659 return this;
660 }
661 /**
662 * Returns a new filtered KeybindingsResult
663 *
664 * @param fn callback filter on the results
665 * @return filtered new result
666 */
667 filter(fn) {
668 const result = new KeybindingsResult();
669 result.full = this.full.filter(fn);
670 result.partial = this.partial.filter(fn);
671 result.shadow = this.shadow.filter(fn);
672 return result;
673 }
674 }
675 KeybindingRegistry.KeybindingsResult = KeybindingsResult;
676})(KeybindingRegistry = exports.KeybindingRegistry || (exports.KeybindingRegistry = {}));
677exports.KeybindingRegistry = KeybindingRegistry;
678//# sourceMappingURL=keybinding.js.map
\No newline at end of file