@difizen/mana-core
Version:
916 lines (889 loc) • 47.5 kB
JavaScript
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.KeybindingScope = exports.KeybindingRegistry = exports.KeybindingContexts = exports.KeybindingContext = exports.Keybinding = void 0;
var _manaCommon = require("@difizen/mana-common");
var _manaSyringe = require("@difizen/mana-syringe");
var _application = require("../application");
var _command2 = require("../command");
var _debug = require("../common/debug");
var _keyboardLayoutService = require("../keyboard/keyboard-layout-service");
var _keys = require("../keyboard/keys");
var _contextKeyService = require("./context-key-service");
var _keybindingProocol = require("./keybinding-proocol");
var _dec, _class, _KeybindingRegistry;
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
* A Keybinding binds a specific key sequence ({@link Keybinding#keybinding}) to trigger a command ({@link Keybinding#command}). A Keybinding optionally may
* define a "when clause" ({@link Keybinding#when}) to specify in which context it becomes active.
* @see KeyBindingRegistry
*/
var Keybinding;
(function (_Keybinding) {
function equals(a, b) {
var ignoreKeybinding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var ignoreArgs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
if (a.command === b.command && (a.context || '') === (b.context || '') && (a.when || '') === (b.when || '') && (ignoreKeybinding || a.keybinding === b.keybinding) && (ignoreArgs || (a.args || '') === (b.args || ''))) {
return true;
}
return false;
}
_Keybinding.equals = equals;
function apiObjectify(binding) {
return {
command: binding.command,
keybinding: binding.keybinding,
context: binding.context,
when: binding.when,
args: binding.args
};
}
_Keybinding.apiObjectify = apiObjectify;
function stringify(binding) {
return JSON.stringify(apiObjectify(binding));
}
_Keybinding.stringify = stringify;
function is(arg) {
return !!arg && arg === Object(arg) && 'command' in arg && 'keybinding' in arg;
}
_Keybinding.is = is;
})(Keybinding || (exports.Keybinding = Keybinding = {}));
var KeybindingScope = exports.KeybindingScope = /*#__PURE__*/function (KeybindingScope) {
KeybindingScope[KeybindingScope["DEFAULT"] = 0] = "DEFAULT";
KeybindingScope[KeybindingScope["USER"] = 1] = "USER";
KeybindingScope[KeybindingScope["WORKSPACE"] = 2] = "WORKSPACE";
KeybindingScope[KeybindingScope["END"] = 3] = "END";
return KeybindingScope;
}({});
(function (_KeybindingScope) {
var length = _KeybindingScope.length = KeybindingScope.END - KeybindingScope.DEFAULT;
})(KeybindingScope || (exports.KeybindingScope = KeybindingScope = {}));
var KeybindingContext = exports.KeybindingContext = _manaSyringe.Syringe.defineToken('KeybindingContext');
var KeybindingContexts;
(function (_KeybindingContexts) {
var NOOP_CONTEXT = _KeybindingContexts.NOOP_CONTEXT = {
id: 'noop.keybinding.context',
isEnabled: function isEnabled() {
return true;
}
};
var DEFAULT_CONTEXT = _KeybindingContexts.DEFAULT_CONTEXT = {
id: 'default.keybinding.context',
isEnabled: function isEnabled() {
return false;
}
};
})(KeybindingContexts || (exports.KeybindingContexts = KeybindingContexts = {}));
var KeybindingRegistry = exports.KeybindingRegistry = (_dec = (0, _manaSyringe.singleton)({
contrib: _application.ApplicationContribution
}), _dec(_class = (_KeybindingRegistry = /*#__PURE__*/function () {
function KeybindingRegistry(keyboardLayoutService, contextProvider, commandRegistry, contributions, logger, whenContextService) {
_classCallCheck(this, KeybindingRegistry);
this.preventDefault = false;
this.stopPropagation = false;
this.keySequence = [];
this.contexts = {};
this.keymaps = _toConsumableArray(Array(KeybindingScope.length)).map(function () {
return [];
});
this.emitter = new _manaCommon.Emitter();
this.keybindingsChanged = new _manaCommon.Emitter();
this.toResetKeymap = new Map();
this.keyboardLayoutService = keyboardLayoutService;
this.contextProvider = contextProvider;
this.commandRegistry = commandRegistry;
this.contributions = contributions;
this.logger = logger;
this.whenContextService = whenContextService;
}
KeybindingRegistry = (0, _manaSyringe.inject)(_contextKeyService.ContextKeyService)(KeybindingRegistry, undefined, 5) || KeybindingRegistry;
KeybindingRegistry = (0, _manaSyringe.inject)(_debug.DebugService)(KeybindingRegistry, undefined, 4) || KeybindingRegistry;
KeybindingRegistry = (0, _manaSyringe.contrib)(_keybindingProocol.KeybindingContribution)(KeybindingRegistry, undefined, 3) || KeybindingRegistry;
KeybindingRegistry = (0, _manaSyringe.inject)(_command2.CommandRegistry)(KeybindingRegistry, undefined, 2) || KeybindingRegistry;
KeybindingRegistry = (0, _manaSyringe.contrib)(KeybindingContext)(KeybindingRegistry, undefined, 1) || KeybindingRegistry;
KeybindingRegistry = (0, _manaSyringe.inject)(_keyboardLayoutService.KeyboardLayoutService)(KeybindingRegistry, undefined, 0) || KeybindingRegistry;
_createClass(KeybindingRegistry, [{
key: "onStart",
value: function () {
var _onStart = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(app) {
var _this = this;
var _iterator, _step, contribution;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return this.keyboardLayoutService.initialize();
case 2:
this.keyboardLayoutService.onKeyboardLayoutChanged(function () {
_this.clearResolvedKeybindings();
_this.keybindingsChanged.fire(undefined);
});
this.registerContext(KeybindingContexts.NOOP_CONTEXT);
this.registerContext(KeybindingContexts.DEFAULT_CONTEXT);
this.registerContext.apply(this, _toConsumableArray(this.contextProvider.getContributions()));
_iterator = _createForOfIteratorHelper(this.contributions.getContributions());
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
contribution = _step.value;
contribution.registerKeybindings(this);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
app.onKeyDown(function (event) {
if (app.inComposition !== true) {
_this.run(event);
}
});
case 9:
case "end":
return _context.stop();
}
}, _callee, this);
}));
function onStart(_x) {
return _onStart.apply(this, arguments);
}
return onStart;
}()
}, {
key: "onKeybindingsChanged",
get:
/**
* Event that is fired when the resolved keybindings change due to a different keyboard layout
* or when a new keymap is being set
*/
function get() {
return this.keybindingsChanged.event;
}
/**
* Registers the keybinding context arguments into the application. Fails when an already registered
* context is being registered.
*
* @param contexts the keybinding contexts to register into the application.
*/
}, {
key: "registerContext",
value: function registerContext() {
for (var _len = arguments.length, contexts = new Array(_len), _key = 0; _key < _len; _key++) {
contexts[_key] = arguments[_key];
}
for (var _i = 0, _contexts = contexts; _i < _contexts.length; _i++) {
var context = _contexts[_i];
var id = context.id;
if (this.contexts[id]) {
this.logger("A keybinding context with ID ".concat(id, " is already registered."));
} else {
this.contexts[id] = context;
}
}
}
/**
* Register a default keybinding to the registry.
*
* Keybindings registered later have higher priority during evaluation.
*
* @param binding the keybinding to be registered
*/
}, {
key: "registerKeybinding",
value: function registerKeybinding(binding) {
return this.doRegisterKeybinding(binding);
}
/**
* Register multiple default keybindings to the registry
*
* @param bindings An array of keybinding to be registered
*/
}, {
key: "registerKeybindings",
value: function registerKeybindings() {
for (var _len2 = arguments.length, bindings = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
bindings[_key2] = arguments[_key2];
}
return this.doRegisterKeybindings(bindings, KeybindingScope.DEFAULT);
}
/**
* Unregister all keybindings from the registry that are bound to the key of the given keybinding
*
* @param binding a keybinding specifying the key to be unregistered
*/
}, {
key: "unregisterKeybinding",
value: function unregisterKeybinding(arg) {
var keymap = this.keymaps[KeybindingScope.DEFAULT];
var filter = _command2.Command.is(arg) ? function (_ref) {
var command = _ref.command;
return command === arg.id;
} : function (_ref2) {
var keybinding = _ref2.keybinding;
return Keybinding.is(arg) ? keybinding === arg.keybinding : keybinding === arg;
};
var _iterator2 = _createForOfIteratorHelper(keymap.filter(filter)),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var _binding = _step2.value;
var idx = keymap.indexOf(_binding);
if (idx !== -1) {
keymap.splice(idx, 1);
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
}
}, {
key: "doRegisterKeybindings",
value: function doRegisterKeybindings(bindings) {
var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : KeybindingScope.DEFAULT;
var toDispose = new _manaCommon.DisposableCollection();
var _iterator3 = _createForOfIteratorHelper(bindings),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var _binding2 = _step3.value;
toDispose.push(this.doRegisterKeybinding(_binding2, scope));
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
return toDispose;
}
}, {
key: "doRegisterKeybinding",
value: function doRegisterKeybinding(binding) {
var _this2 = this;
var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : KeybindingScope.DEFAULT;
try {
this.resolveKeybinding(binding);
var scoped = Object.assign(binding, {
scope: scope
});
this.insertBindingIntoScope(scoped, scope);
return _manaCommon.Disposable.create(function () {
var index = _this2.keymaps[scope].indexOf(scoped);
if (index !== -1) {
_this2.keymaps[scope].splice(index, 1);
}
});
} catch (error) {
this.logger("Could not register keybinding:\n ".concat(Keybinding.stringify(binding), "\n").concat(error));
return _manaCommon.Disposable.NONE;
}
}
/**
* Ensures that keybindings are inserted in order of increasing length of binding to ensure that if a
* user triggers a short keybinding (e.g. ctrl+k), the UI won't wait for a longer one (e.g. ctrl+k enter)
*/
}, {
key: "insertBindingIntoScope",
value: function insertBindingIntoScope(item, scope) {
var scopedKeymap = this.keymaps[scope];
var getNumberOfKeystrokes = function getNumberOfKeystrokes(binding) {
var _binding$keybinding$t, _binding$keybinding$t2;
return ((_binding$keybinding$t = (_binding$keybinding$t2 = binding.keybinding.trim().match(/\s/g)) === null || _binding$keybinding$t2 === void 0 ? void 0 : _binding$keybinding$t2.length) !== null && _binding$keybinding$t !== void 0 ? _binding$keybinding$t : 0) + 1;
};
var numberOfKeystrokesInBinding = getNumberOfKeystrokes(item);
var indexOfFirstItemWithEqualStrokes = scopedKeymap.findIndex(function (existingBinding) {
return getNumberOfKeystrokes(existingBinding) === numberOfKeystrokesInBinding;
});
if (indexOfFirstItemWithEqualStrokes > -1) {
scopedKeymap.splice(indexOfFirstItemWithEqualStrokes, 0, item);
} else {
scopedKeymap.push(item);
}
}
/**
* Ensure that the `resolved` property of the given binding is set by calling the KeyboardLayoutService.
*/
}, {
key: "resolveKeybinding",
value: function resolveKeybinding(binding) {
var _this3 = this;
if (!binding.resolved) {
var sequence = _keys.KeySequence.parse(binding.keybinding);
binding.resolved = sequence.map(function (code) {
return _this3.keyboardLayoutService.resolveKeyCode(code);
});
}
return binding.resolved;
}
/**
* Clear all `resolved` properties of registered keybindings so the KeyboardLayoutService is called
* again to resolve them. This is necessary when the user's keyboard layout has changed.
*/
}, {
key: "clearResolvedKeybindings",
value: function clearResolvedKeybindings() {
for (var i = KeybindingScope.DEFAULT; i < KeybindingScope.END; i++) {
var bindings = this.keymaps[i];
for (var j = 0; j < bindings.length; j++) {
var _binding3 = bindings[j];
_binding3.resolved = undefined;
}
}
}
/**
* Checks whether a colliding {@link common.Keybinding} exists in a specific scope.
* @param binding the keybinding to check
* @param scope the keybinding scope to check
* @returns true if there is a colliding keybinding
*/
}, {
key: "containsKeybindingInScope",
value: function containsKeybindingInScope(binding) {
var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : KeybindingScope.USER;
var bindingKeySequence = this.resolveKeybinding(binding);
var collisions = this.getKeySequenceCollisions(this.getUsableBindings(this.keymaps[scope]), bindingKeySequence).filter(function (b) {
return b.context === binding.context && !b.when && !binding.when;
});
if (collisions.full.length > 0) {
return true;
}
if (collisions.partial.length > 0) {
return true;
}
if (collisions.shadow.length > 0) {
return true;
}
return false;
}
/**
* Get a user visible representation of a {@link common.Keybinding}.
* @returns an array of strings representing all elements of the {@link KeySequence} defined by the {@link common.Keybinding}
* @param keybinding the keybinding
* @param separator the separator to be used to stringify {@link KeyCode}s that are part of the {@link KeySequence}
*/
}, {
key: "acceleratorFor",
value: function acceleratorFor(keybinding) {
var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ' ';
var bindingKeySequence = this.resolveKeybinding(keybinding);
return this.acceleratorForSequence(bindingKeySequence, separator);
}
/**
* Get a user visible representation of a {@link KeySequence}.
* @returns an array of strings representing all elements of the {@link KeySequence}
* @param keySequence the keysequence
* @param separator the separator to be used to stringify {@link KeyCode}s that are part of the {@link KeySequence}
*/
}, {
key: "acceleratorForSequence",
value: function acceleratorForSequence(keySequence) {
var _this4 = this;
var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ' ';
return keySequence.map(function (keyCode) {
return _this4.acceleratorForKeyCode(keyCode, separator);
});
}
/**
* Get a user visible representation of a key code (a key with modifiers).
* @returns a string representing the {@link KeyCode}
* @param keyCode the keycode
* @param separator the separator used to separate keys (key and modifiers) in the returning string
*/
}, {
key: "acceleratorForKeyCode",
value: function acceleratorForKeyCode(keyCode) {
var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ' ';
var keyCodeResult = [];
if (keyCode.meta && _manaCommon.isOSX) {
keyCodeResult.push('Cmd');
}
if (keyCode.ctrl) {
keyCodeResult.push('Ctrl');
}
if (keyCode.alt) {
keyCodeResult.push('Alt');
}
if (keyCode.shift) {
keyCodeResult.push('Shift');
}
if (keyCode.key) {
keyCodeResult.push(this.acceleratorForKey(keyCode.key));
}
return keyCodeResult.join(separator);
}
/**
* Return a user visible representation of a single key.
*/
}, {
key: "acceleratorForKey",
value: function acceleratorForKey(key) {
if (_manaCommon.isOSX) {
if (key === _keys.Key.ARROW_LEFT) {
return '←';
}
if (key === _keys.Key.ARROW_RIGHT) {
return '→';
}
if (key === _keys.Key.ARROW_UP) {
return '↑';
}
if (key === _keys.Key.ARROW_DOWN) {
return '↓';
}
}
var keyString = this.keyboardLayoutService.getKeyboardCharacter(key);
if (key.keyCode >= _keys.Key.KEY_A.keyCode && key.keyCode <= _keys.Key.KEY_Z.keyCode || key.keyCode >= _keys.Key.F1.keyCode && key.keyCode <= _keys.Key.F24.keyCode) {
return keyString.toUpperCase();
}
if (keyString.length > 1) {
return keyString.charAt(0).toUpperCase() + keyString.slice(1);
}
return keyString;
}
/**
* Finds collisions for a key sequence inside a list of bindings (error-free)
*
* @param bindings the reference bindings
* @param candidate the sequence to match
*/
}, {
key: "getKeySequenceCollisions",
value: function getKeySequenceCollisions(bindings, candidate) {
var result = new KeybindingRegistry.KeybindingsResult();
var _iterator4 = _createForOfIteratorHelper(bindings),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var _binding4 = _step4.value;
try {
var bindingKeySequence = this.resolveKeybinding(_binding4);
var compareResult = _keys.KeySequence.compare(candidate, bindingKeySequence);
switch (compareResult) {
case _keys.KeySequence.CompareResult.FULL:
{
result.full.push(_binding4);
break;
}
case _keys.KeySequence.CompareResult.PARTIAL:
{
result.partial.push(_binding4);
break;
}
case _keys.KeySequence.CompareResult.SHADOW:
{
result.shadow.push(_binding4);
break;
}
}
} catch (error) {
this.logger(error);
}
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
return result;
}
/**
* Get all keybindings associated to a commandId.
*
* @param commandId The ID of the command for which we are looking for keybindings.
* @returns an array of {@link ScopedKeybinding}
*/
}, {
key: "getKeybindingsForCommand",
value: function getKeybindingsForCommand(commandId) {
var _this5 = this;
var result = [];
var _loop = function _loop(scope) {
_this5.keymaps[scope].forEach(function (binding) {
var command = _this5.commandRegistry.getCommand(binding.command);
if (command) {
if (command.id === commandId) {
result.push(_objectSpread(_objectSpread({}, binding), {}, {
scope: scope
}));
}
}
});
if (result.length > 0) {
return {
v: result
};
}
},
_ret;
for (var scope = KeybindingScope.END - 1; scope >= KeybindingScope.DEFAULT; scope--) {
_ret = _loop(scope);
if (_ret) return _ret.v;
}
return result;
}
}, {
key: "isActive",
value: function isActive(binding) {
/* Pseudo commands like "passthrough" are always active (and not found
in the command registry). */
if (this.isPseudoCommand(binding.command)) {
return true;
}
var command = this.commandRegistry.getCommand(binding.command);
return !!command && !!this.commandRegistry.getEnableHandler(command.id);
}
/**
* Tries to execute a keybinding.
*
* @param binding to execute
* @param event keyboard event.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}, {
key: "executeKeyBinding",
value: function executeKeyBinding(binding, event) {
if (this.isPseudoCommand(binding.command)) {
/* Don't do anything, let the event propagate. */
} else {
var _command = this.commandRegistry.getCommand(binding.command);
if (_command) {
if (this.commandRegistry.isEnabled(binding.command, binding.args)) {
this.commandRegistry.executeCommand(binding.command, binding.args).catch(function (e) {
return console.error('Failed to execute command:', e);
});
}
/* Note that if a keybinding is in context but the command is
not active we still stop the processing here. */
var _binding$preventDefau = binding.preventDefault,
preventDefault = _binding$preventDefau === void 0 ? this.preventDefault : _binding$preventDefau,
_binding$stopPropagat = binding.stopPropagation,
stopPropagation = _binding$stopPropagat === void 0 ? this.stopPropagation : _binding$stopPropagat;
if (preventDefault) {
event.preventDefault();
}
if (stopPropagation) {
event.stopPropagation();
}
}
}
}
/**
* Only execute if it has no context (global context) or if we're in that context.
*/
}, {
key: "isEnabled",
value: function isEnabled(binding, event) {
var context = binding.context && this.contexts[binding.context];
if (context && !context.isEnabled(binding)) {
return false;
}
if (binding.when && !this.whenContextService.match(binding.when, event.target)) {
return false;
}
return true;
}
}, {
key: "dispatchCommand",
value: function dispatchCommand(id, target) {
var keybindings = this.getKeybindingsForCommand(id);
if (keybindings.length) {
var _iterator5 = _createForOfIteratorHelper(this.resolveKeybinding(keybindings[0])),
_step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
var keyCode = _step5.value;
this.dispatchKeyDown(keyCode, target);
}
} catch (err) {
_iterator5.e(err);
} finally {
_iterator5.f();
}
}
}
}, {
key: "dispatchKeyDown",
value: function dispatchKeyDown(input) {
var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document.activeElement || window;
var eventInit = this.asKeyboardEventInit(input);
var emulatedKeyboardEvent = new KeyboardEvent('keydown', eventInit);
target.dispatchEvent(emulatedKeyboardEvent);
}
}, {
key: "asKeyboardEventInit",
value: function asKeyboardEventInit(input) {
if (typeof input === 'string') {
return this.asKeyboardEventInit(_keys.KeyCode.createKeyCode(input));
}
if (input instanceof _keys.KeyCode) {
return {
metaKey: input.meta,
shiftKey: input.shift,
altKey: input.alt,
ctrlKey: input.ctrl,
code: input.key && input.key.code,
key: input && input.character || input.key && input.key.code,
keyCode: input.key && input.key.keyCode
};
}
return input;
}
/**
* Run the command matching to the given keyboard event.
*/
}, {
key: "run",
value: function run(event) {
if (event.defaultPrevented) {
return;
}
var keyCode = _keys.KeyCode.createKeyCode(event, 'code');
/* Keycode is only a modifier, next keycode will be modifier + key.
Ignore this one. */
if (keyCode.isModifierOnly()) {
return;
}
this.keyboardLayoutService.validateKeyCode(keyCode);
this.keySequence.push(keyCode);
var match = this.matchKeybinding(this.keySequence, event);
if (match && match.kind === 'partial') {
/* Accumulate the keysequence */
// TODO: The effective scope of of prevent propagation.
var _match$binding = match.binding,
_match$binding$preven = _match$binding.preventDefault,
preventDefault = _match$binding$preven === void 0 ? this.preventDefault : _match$binding$preven,
_match$binding$stopPr = _match$binding.stopPropagation,
stopPropagation = _match$binding$stopPr === void 0 ? this.stopPropagation : _match$binding$stopPr;
if (preventDefault) {
event.preventDefault();
}
if (stopPropagation) {
event.stopPropagation();
}
this.emitter.fire(match);
} else {
if (match && match.kind === 'full') {
this.executeKeyBinding(match.binding, event);
}
this.keySequence = [];
this.emitter.fire(match);
}
}
}, {
key: "onMatchChange",
value: function onMatchChange(callback) {
this.emitter.event(callback);
}
/**
* Match first binding in the current context.
* Keybindings ordered by a scope and by a registration order within the scope.
*
* FIXME:
* This method should run very fast since it happens on each keystroke. We should reconsider how keybindings are stored.
* It should be possible to look up full and partial keybinding for given key sequence for constant time using some kind of tree.
* Such tree should not contain disabled keybindings and be invalidated whenever the registry is changed.
*/
}, {
key: "matchKeybinding",
value: function matchKeybinding(keySequence, event) {
var _this6 = this;
var disabled;
var isEnabled = function isEnabled(binding) {
var _disabled;
if (event && !_this6.isEnabled(binding, event)) {
return false;
}
var command = binding.command,
context = binding.context,
when = binding.when,
keybinding = binding.keybinding;
if (!_this6.isUsable(binding)) {
disabled = disabled || new Set();
disabled.add(JSON.stringify({
command: command.substr(1),
context: context,
when: when,
keybinding: keybinding
}));
return false;
}
return !((_disabled = disabled) !== null && _disabled !== void 0 && _disabled.has(JSON.stringify({
command: command,
context: context,
when: when,
keybinding: keybinding
})));
};
for (var scope = KeybindingScope.END; --scope >= KeybindingScope.DEFAULT;) {
var _iterator6 = _createForOfIteratorHelper(this.keymaps[scope]),
_step6;
try {
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
var _binding5 = _step6.value;
var resolved = this.resolveKeybinding(_binding5);
var compareResult = _keys.KeySequence.compare(keySequence, resolved);
if (compareResult === _keys.KeySequence.CompareResult.FULL && isEnabled(_binding5)) {
return {
kind: 'full',
binding: _binding5
};
}
if (compareResult === _keys.KeySequence.CompareResult.PARTIAL && isEnabled(_binding5)) {
return {
kind: 'partial',
binding: _binding5
};
}
}
} catch (err) {
_iterator6.e(err);
} finally {
_iterator6.f();
}
}
return undefined;
}
/**
* Returns true if the binding is usable
* @param binding Binding to be checked
*/
}, {
key: "isUsable",
value: function isUsable(binding) {
return binding.command.charAt(0) !== '-';
}
/**
* Return a new filtered array containing only the usable bindings among the input bindings
* @param bindings Bindings to filter
*/
}, {
key: "getUsableBindings",
value: function getUsableBindings(bindings) {
var _this7 = this;
return bindings.filter(function (binding) {
return _this7.isUsable(binding);
});
}
/**
* Return true of string a pseudo-command id, in other words a command id
* that has a special meaning and that we won't find in the command
* registry.
*
* @param commandId commandId to test
*/
}, {
key: "isPseudoCommand",
value: function isPseudoCommand(commandId) {
return commandId === KeybindingRegistry.PASSTHROUGH_PSEUDO_COMMAND;
}
/**
* Sets a new keymap replacing all existing {@link common.Keybinding}s in the given scope.
* @param scope the keybinding scope
* @param bindings an array containing the new {@link common.Keybinding}s
*/
}, {
key: "setKeymap",
value: function setKeymap(scope, bindings) {
this.resetKeybindingsForScope(scope);
this.toResetKeymap.set(scope, this.doRegisterKeybindings(bindings, scope));
this.keybindingsChanged.fire(undefined);
}
}, {
key: "resetKeybindingsForScope",
value:
/**
* Reset keybindings for a specific scope
* @param scope scope to reset the keybindings for
*/
function resetKeybindingsForScope(scope) {
var toReset = this.toResetKeymap.get(scope);
if (toReset) {
toReset.dispose();
}
}
/**
* Reset keybindings for all scopes(only leaves the default keybindings mapped)
*/
}, {
key: "resetKeybindings",
value: function resetKeybindings() {
for (var i = KeybindingScope.DEFAULT + 1; i < KeybindingScope.END; i++) {
this.keymaps[i] = [];
}
}
/**
* Get all {@link common.Keybinding}s for a {@link KeybindingScope}.
* @returns an array of {@link common.ScopedKeybinding}
* @param scope the keybinding scope to retrieve the {@link common.Keybinding}s for.
*/
}, {
key: "getKeybindingsByScope",
value: function getKeybindingsByScope(scope) {
return this.keymaps[scope];
}
}]);
return KeybindingRegistry;
}(), _KeybindingRegistry.PASSTHROUGH_PSEUDO_COMMAND = 'passthrough', _KeybindingRegistry)) || _class);
(function (_KeybindingRegistry2) {
var KeybindingsResult = /*#__PURE__*/function () {
function KeybindingsResult() {
_classCallCheck(this, KeybindingsResult);
this.full = [];
this.partial = [];
this.shadow = [];
}
_createClass(KeybindingsResult, [{
key: "merge",
value:
/**
* Merge two results together inside `this`
*
* @param other the other KeybindingsResult to merge with
* @return this
*/
function merge(other) {
var _this$full, _this$partial, _this$shadow;
(_this$full = this.full).push.apply(_this$full, _toConsumableArray(other.full));
(_this$partial = this.partial).push.apply(_this$partial, _toConsumableArray(other.partial));
(_this$shadow = this.shadow).push.apply(_this$shadow, _toConsumableArray(other.shadow));
return this;
}
/**
* Returns a new filtered KeybindingsResult
*
* @param fn callback filter on the results
* @return filtered new result
*/
}, {
key: "filter",
value: function filter(fn) {
var result = new KeybindingsResult();
result.full = this.full.filter(fn);
result.partial = this.partial.filter(fn);
result.shadow = this.shadow.filter(fn);
return result;
}
}]);
return KeybindingsResult;
}();
_KeybindingRegistry2.KeybindingsResult = KeybindingsResult;
})(KeybindingRegistry || (exports.KeybindingRegistry = KeybindingRegistry = {}));