UNPKG

monaco-editor

Version:
224 lines (223 loc) • 8.45 kB
import { ContextKeyAndExpr } from '../../contextkey/common/contextkey.js'; var KeybindingResolver = /** @class */ (function () { function KeybindingResolver(defaultKeybindings, overrides) { this._defaultKeybindings = defaultKeybindings; this._defaultBoundCommands = new Map(); for (var i = 0, len = defaultKeybindings.length; i < len; i++) { var command = defaultKeybindings[i].command; if (command) { this._defaultBoundCommands.set(command, true); } } this._map = new Map(); this._lookupMap = new Map(); this._keybindings = KeybindingResolver.combine(defaultKeybindings, overrides); for (var i = 0, len = this._keybindings.length; i < len; i++) { var k = this._keybindings[i]; if (k.keypressFirstPart === null) { // unbound continue; } this._addKeyPress(k.keypressFirstPart, k); } } KeybindingResolver._isTargetedForRemoval = function (defaultKb, keypressFirstPart, keypressChordPart, command, when) { if (defaultKb.command !== command) { return false; } if (keypressFirstPart && defaultKb.keypressFirstPart !== keypressFirstPart) { return false; } if (keypressChordPart && defaultKb.keypressChordPart !== keypressChordPart) { return false; } if (when) { if (!defaultKb.when) { return false; } if (!when.equals(defaultKb.when)) { return false; } } return true; }; /** * Looks for rules containing -command in `overrides` and removes them directly from `defaults`. */ KeybindingResolver.combine = function (defaults, rawOverrides) { defaults = defaults.slice(0); var overrides = []; for (var i = 0, len = rawOverrides.length; i < len; i++) { var override = rawOverrides[i]; if (!override.command || override.command.length === 0 || override.command.charAt(0) !== '-') { overrides.push(override); continue; } var command = override.command.substr(1); var keypressFirstPart = override.keypressFirstPart; var keypressChordPart = override.keypressChordPart; var when = override.when; for (var j = defaults.length - 1; j >= 0; j--) { if (this._isTargetedForRemoval(defaults[j], keypressFirstPart, keypressChordPart, command, when)) { defaults.splice(j, 1); } } } return defaults.concat(overrides); }; KeybindingResolver.prototype._addKeyPress = function (keypress, item) { var conflicts = this._map.get(keypress); if (typeof conflicts === 'undefined') { // There is no conflict so far this._map.set(keypress, [item]); this._addToLookupMap(item); return; } for (var i = conflicts.length - 1; i >= 0; i--) { var conflict = conflicts[i]; if (conflict.command === item.command) { continue; } var conflictIsChord = (conflict.keypressChordPart !== null); var itemIsChord = (item.keypressChordPart !== null); if (conflictIsChord && itemIsChord && conflict.keypressChordPart !== item.keypressChordPart) { // The conflict only shares the chord start with this command continue; } if (KeybindingResolver.whenIsEntirelyIncluded(conflict.when, item.when)) { // `item` completely overwrites `conflict` // Remove conflict from the lookupMap this._removeFromLookupMap(conflict); } } conflicts.push(item); this._addToLookupMap(item); }; KeybindingResolver.prototype._addToLookupMap = function (item) { if (!item.command) { return; } var arr = this._lookupMap.get(item.command); if (typeof arr === 'undefined') { arr = [item]; this._lookupMap.set(item.command, arr); } else { arr.push(item); } }; KeybindingResolver.prototype._removeFromLookupMap = function (item) { if (!item.command) { return; } var arr = this._lookupMap.get(item.command); if (typeof arr === 'undefined') { return; } for (var i = 0, len = arr.length; i < len; i++) { if (arr[i] === item) { arr.splice(i, 1); return; } } }; /** * Returns true if it is provable `a` implies `b`. * **Precondition**: Assumes `a` and `b` are normalized! */ KeybindingResolver.whenIsEntirelyIncluded = function (a, b) { if (!b) { return true; } if (!a) { return false; } var aExpressions = ((a instanceof ContextKeyAndExpr) ? a.expr : [a]); var bExpressions = ((b instanceof ContextKeyAndExpr) ? b.expr : [b]); var aIndex = 0; for (var bIndex = 0; bIndex < bExpressions.length; bIndex++) { var bExpr = bExpressions[bIndex]; var bExprMatched = false; while (!bExprMatched && aIndex < aExpressions.length) { var aExpr = aExpressions[aIndex]; if (aExpr.equals(bExpr)) { bExprMatched = true; } aIndex++; } if (!bExprMatched) { return false; } } return true; }; KeybindingResolver.prototype.lookupPrimaryKeybinding = function (commandId) { var items = this._lookupMap.get(commandId); if (typeof items === 'undefined' || items.length === 0) { return null; } return items[items.length - 1]; }; KeybindingResolver.prototype.resolve = function (context, currentChord, keypress) { var lookupMap = null; if (currentChord !== null) { // Fetch all chord bindings for `currentChord` var candidates = this._map.get(currentChord); if (typeof candidates === 'undefined') { // No chords starting with `currentChord` return null; } lookupMap = []; for (var i = 0, len = candidates.length; i < len; i++) { var candidate = candidates[i]; if (candidate.keypressChordPart === keypress) { lookupMap.push(candidate); } } } else { var candidates = this._map.get(keypress); if (typeof candidates === 'undefined') { // No bindings with `keypress` return null; } lookupMap = candidates; } var result = this._findCommand(context, lookupMap); if (!result) { return null; } if (currentChord === null && result.keypressChordPart !== null) { return { enterChord: true, commandId: null, commandArgs: null, bubble: false }; } return { enterChord: false, commandId: result.command, commandArgs: result.commandArgs, bubble: result.bubble }; }; KeybindingResolver.prototype._findCommand = function (context, matches) { for (var i = matches.length - 1; i >= 0; i--) { var k = matches[i]; if (!KeybindingResolver.contextMatchesRules(context, k.when)) { continue; } return k; } return null; }; KeybindingResolver.contextMatchesRules = function (context, rules) { if (!rules) { return true; } return rules.evaluate(context); }; return KeybindingResolver; }()); export { KeybindingResolver };