@opentui/keymap 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/package.json +30 -20
- package/{addons → src/addons}/index.js +310 -61
- package/{addons → src/addons}/opentui/index.js +347 -98
- package/src/addons/universal/binding-overrides.d.ts +6 -0
- package/src/addons/universal/index.d.ts +1 -0
- package/src/extras/binding-sections.d.ts +18 -0
- package/src/extras/command-bindings.d.ts +19 -0
- package/src/extras/formatting.d.ts +24 -0
- package/src/extras/index.d.ts +6 -0
- package/src/extras/index.js +226 -0
- package/{html.js → src/html.js} +259 -59
- package/src/index.d.ts +1 -1
- package/{index.js → src/index.js} +259 -59
- package/src/keymap.d.ts +7 -3
- package/{opentui.js → src/opentui.js} +259 -59
- package/src/runtime-modules.d.ts +18 -0
- package/src/runtime-modules.js +23 -0
- package/src/services/command-catalog.d.ts +12 -4
- package/src/services/command-executor.d.ts +1 -1
- package/src/services/compiler.d.ts +3 -1
- package/src/services/environment.d.ts +4 -1
- package/src/services/layers.d.ts +1 -0
- package/src/services/primitives/binding-inputs.d.ts +2 -2
- package/src/services/primitives/command-normalization.d.ts +3 -0
- package/src/services/state.d.ts +2 -1
- package/src/types.d.ts +18 -2
- /package/{react → src/react}/index.js +0 -0
- /package/{solid → src/solid}/index.js +0 -0
|
@@ -144,7 +144,7 @@ function stringifyKeyStroke(input, options) {
|
|
|
144
144
|
return stringifyCanonicalStroke(normalizeKeyStroke(input));
|
|
145
145
|
}
|
|
146
146
|
function stringifyKeySequence(input, options) {
|
|
147
|
-
return input.map((part) => stringifyKeyStroke(part, options)).join("");
|
|
147
|
+
return input.map((part) => stringifyKeyStroke(part, options)).join(options?.separator ?? "");
|
|
148
148
|
}
|
|
149
149
|
function stringifyCanonicalStroke(stroke) {
|
|
150
150
|
const parts = [];
|
|
@@ -729,6 +729,28 @@ var RESERVED_COMMAND_FIELDS = new Set(["name", "run"]);
|
|
|
729
729
|
var RESERVED_BINDING_FIELDS = new Set(["key", "cmd", "event", "preventDefault", "fallthrough"]);
|
|
730
730
|
var RESERVED_LAYER_FIELDS = new Set(["target", "targetMode", "priority", "bindings", "commands"]);
|
|
731
731
|
|
|
732
|
+
// src/services/primitives/command-normalization.ts
|
|
733
|
+
function normalizeBindingCommand(command) {
|
|
734
|
+
if (command === undefined || typeof command === "function") {
|
|
735
|
+
return command;
|
|
736
|
+
}
|
|
737
|
+
const trimmed = command.trim();
|
|
738
|
+
if (!trimmed) {
|
|
739
|
+
throw new Error("Invalid keymap command: command cannot be empty");
|
|
740
|
+
}
|
|
741
|
+
return trimmed;
|
|
742
|
+
}
|
|
743
|
+
function normalizeCommandName(name) {
|
|
744
|
+
const trimmed = name.trim();
|
|
745
|
+
if (!trimmed) {
|
|
746
|
+
throw new Error("Invalid keymap command name: name cannot be empty");
|
|
747
|
+
}
|
|
748
|
+
if (/\s/.test(trimmed)) {
|
|
749
|
+
throw new Error(`Invalid keymap command name "${name}": command names cannot contain whitespace`);
|
|
750
|
+
}
|
|
751
|
+
return trimmed;
|
|
752
|
+
}
|
|
753
|
+
|
|
732
754
|
// src/services/primitives/field-invariants.ts
|
|
733
755
|
function mergeRequirement(target, name, value, source) {
|
|
734
756
|
if (Object.prototype.hasOwnProperty.call(target, name) && !Object.is(target[name], value)) {
|
|
@@ -806,26 +828,6 @@ function createCommandChainCacheState() {
|
|
|
806
828
|
fallbackWithRecordErrors: new Set
|
|
807
829
|
};
|
|
808
830
|
}
|
|
809
|
-
function normalizeBindingCommand(command) {
|
|
810
|
-
if (command === undefined || typeof command === "function") {
|
|
811
|
-
return command;
|
|
812
|
-
}
|
|
813
|
-
const trimmed = command.trim();
|
|
814
|
-
if (!trimmed) {
|
|
815
|
-
throw new Error("Invalid keymap command: command cannot be empty");
|
|
816
|
-
}
|
|
817
|
-
return trimmed;
|
|
818
|
-
}
|
|
819
|
-
function normalizeCommandName(name) {
|
|
820
|
-
const trimmed = name.trim();
|
|
821
|
-
if (!trimmed) {
|
|
822
|
-
throw new Error("Invalid keymap command name: name cannot be empty");
|
|
823
|
-
}
|
|
824
|
-
if (/\s/.test(trimmed)) {
|
|
825
|
-
throw new Error(`Invalid keymap command name "${name}": command names cannot contain whitespace`);
|
|
826
|
-
}
|
|
827
|
-
return trimmed;
|
|
828
|
-
}
|
|
829
831
|
|
|
830
832
|
class CommandCatalogService {
|
|
831
833
|
state;
|
|
@@ -898,6 +900,19 @@ class CommandCatalogService {
|
|
|
898
900
|
bindings: item.bindings
|
|
899
901
|
}));
|
|
900
902
|
}
|
|
903
|
+
getCommandBindings(query) {
|
|
904
|
+
const bindingsByCommand = new Map;
|
|
905
|
+
for (const command of query.commands) {
|
|
906
|
+
if (!bindingsByCommand.has(command)) {
|
|
907
|
+
bindingsByCommand.set(command, []);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (bindingsByCommand.size === 0) {
|
|
911
|
+
return bindingsByCommand;
|
|
912
|
+
}
|
|
913
|
+
this.collectCommandBindings(bindingsByCommand, this.getCommandQueryContext(query));
|
|
914
|
+
return bindingsByCommand;
|
|
915
|
+
}
|
|
901
916
|
getResolvedCommandChain(command, focused, includeRecord) {
|
|
902
917
|
const view = this.getActiveCommandView(focused);
|
|
903
918
|
const entries = this.getResolvedCommandChainFromView(view, command, focused, includeRecord, "active", view.chainsByName.get(command));
|
|
@@ -926,14 +941,26 @@ class CommandCatalogService {
|
|
|
926
941
|
cache.set(command, resolved);
|
|
927
942
|
return resolved;
|
|
928
943
|
}
|
|
929
|
-
|
|
930
|
-
const view = this.
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
944
|
+
getActiveRegisteredResolvedEntries(command, focused, includeRecord) {
|
|
945
|
+
const view = this.getActiveCommandView(focused);
|
|
946
|
+
const chain = view.chainsByName.get(command);
|
|
947
|
+
if (!chain || chain.length === 0) {
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
const resolved = [];
|
|
951
|
+
for (const entry of chain) {
|
|
952
|
+
resolved.push({
|
|
953
|
+
target: entry.layer.target,
|
|
954
|
+
resolved: resolveRegisteredCommand(entry.command, { includeRecord })
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
return resolved;
|
|
958
|
+
}
|
|
959
|
+
resolveRegisteredResolverFallback(command, includeRecord) {
|
|
960
|
+
return this.resolveCommandWithResolvers(command, null, { includeRecord, mode: "registered" });
|
|
961
|
+
}
|
|
962
|
+
resolveActiveResolverFallback(command, focused, includeRecord) {
|
|
963
|
+
return this.resolveCommandWithResolvers(command, focused, { includeRecord, mode: "active" });
|
|
937
964
|
}
|
|
938
965
|
getCommandAttrs(command, focused) {
|
|
939
966
|
const top = this.getTopResolvedCommand(command, focused, false);
|
|
@@ -1240,6 +1267,31 @@ class CommandCatalogService {
|
|
|
1240
1267
|
}
|
|
1241
1268
|
}
|
|
1242
1269
|
}
|
|
1270
|
+
collectCommandBindings(bindingsByCommand, context) {
|
|
1271
|
+
if (context.visibility === "registered") {
|
|
1272
|
+
for (const layer of this.state.layers.layers) {
|
|
1273
|
+
for (const binding of layer.compiledBindings) {
|
|
1274
|
+
this.collectBindingForCommandBindings(bindingsByCommand, binding, context);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
const activeView = context.activeView;
|
|
1280
|
+
if (!activeView) {
|
|
1281
|
+
return;
|
|
1282
|
+
}
|
|
1283
|
+
for (const layer of getActiveLayersForFocused(this.state.layers, this.host, context.focused)) {
|
|
1284
|
+
if (layer.compiledBindings.length === 0 || !this.conditions.layerMatchesRuntimeState(layer)) {
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
for (const binding of layer.compiledBindings) {
|
|
1288
|
+
if (!this.conditions.matchesConditions(binding) || !this.isBindingVisible(binding, context.focused, activeView)) {
|
|
1289
|
+
continue;
|
|
1290
|
+
}
|
|
1291
|
+
this.collectBindingForCommandBindings(bindingsByCommand, binding, context);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1243
1295
|
collectBindingForCommandEntries(grouped, indexesByName, binding) {
|
|
1244
1296
|
if (typeof binding.command !== "string") {
|
|
1245
1297
|
return;
|
|
@@ -1253,17 +1305,43 @@ class CommandCatalogService {
|
|
|
1253
1305
|
if (!item) {
|
|
1254
1306
|
continue;
|
|
1255
1307
|
}
|
|
1256
|
-
item.bindings.push(
|
|
1257
|
-
sequence: binding.sequence,
|
|
1258
|
-
command: binding.command,
|
|
1259
|
-
commandAttrs: item.command.attrs,
|
|
1260
|
-
attrs: binding.attrs,
|
|
1261
|
-
event: binding.event,
|
|
1262
|
-
preventDefault: binding.preventDefault,
|
|
1263
|
-
fallthrough: binding.fallthrough
|
|
1264
|
-
});
|
|
1308
|
+
item.bindings.push(this.createActiveBinding(binding, item.command.attrs));
|
|
1265
1309
|
}
|
|
1266
1310
|
}
|
|
1311
|
+
collectBindingForCommandBindings(bindingsByCommand, binding, context) {
|
|
1312
|
+
if (typeof binding.command !== "string") {
|
|
1313
|
+
return;
|
|
1314
|
+
}
|
|
1315
|
+
const bindings = bindingsByCommand.get(binding.command);
|
|
1316
|
+
if (!bindings) {
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
bindings.push(this.createActiveBinding(binding, this.getCommandBindingAttrs(binding, context)));
|
|
1320
|
+
}
|
|
1321
|
+
createActiveBinding(binding, commandAttrs) {
|
|
1322
|
+
return {
|
|
1323
|
+
sequence: binding.sequence,
|
|
1324
|
+
command: binding.command,
|
|
1325
|
+
commandAttrs,
|
|
1326
|
+
attrs: binding.attrs,
|
|
1327
|
+
event: binding.event,
|
|
1328
|
+
preventDefault: binding.preventDefault,
|
|
1329
|
+
fallthrough: binding.fallthrough
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
getCommandBindingAttrs(binding, context) {
|
|
1333
|
+
if (typeof binding.command !== "string") {
|
|
1334
|
+
return;
|
|
1335
|
+
}
|
|
1336
|
+
if (context.visibility === "registered") {
|
|
1337
|
+
return this.getTopRegisteredCommand(binding.command)?.command.attrs;
|
|
1338
|
+
}
|
|
1339
|
+
const activeView = context.activeView;
|
|
1340
|
+
if (!activeView) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
return this.getBindingCommandAttrs(binding, context.focused, activeView);
|
|
1344
|
+
}
|
|
1267
1345
|
resolveCommandWithResolvers(command, focused, options) {
|
|
1268
1346
|
const includeRecord = options?.includeRecord === true;
|
|
1269
1347
|
const context = this.createCommandResolverContext(includeRecord, focused, options?.mode ?? "active");
|
|
@@ -1457,12 +1535,53 @@ function queryLayerCommandEntries(options) {
|
|
|
1457
1535
|
const filter = options.query?.filter;
|
|
1458
1536
|
let filterEntries;
|
|
1459
1537
|
let filterPredicate;
|
|
1538
|
+
let exactNameFilter;
|
|
1460
1539
|
if (typeof filter === "function") {
|
|
1461
1540
|
filterPredicate = filter;
|
|
1462
1541
|
} else if (filter) {
|
|
1463
|
-
|
|
1542
|
+
const entries = Object.entries(filter);
|
|
1543
|
+
const remainingEntries = [];
|
|
1544
|
+
for (const [key, matcher] of entries) {
|
|
1545
|
+
if (key === "name") {
|
|
1546
|
+
if (typeof matcher === "string") {
|
|
1547
|
+
exactNameFilter = new Set([matcher]);
|
|
1548
|
+
continue;
|
|
1549
|
+
}
|
|
1550
|
+
if (Array.isArray(matcher)) {
|
|
1551
|
+
const names = new Set;
|
|
1552
|
+
for (const value of matcher) {
|
|
1553
|
+
if (typeof value === "string") {
|
|
1554
|
+
names.add(value);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
exactNameFilter = names;
|
|
1558
|
+
continue;
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
remainingEntries.push([key, matcher]);
|
|
1562
|
+
}
|
|
1563
|
+
filterEntries = remainingEntries.length > 0 ? remainingEntries : undefined;
|
|
1464
1564
|
}
|
|
1465
1565
|
const results = [];
|
|
1566
|
+
if (exactNameFilter) {
|
|
1567
|
+
for (const entry of options.entries) {
|
|
1568
|
+
const command = entry.command;
|
|
1569
|
+
if (!commandMatchesNamespace(command, namespace)) {
|
|
1570
|
+
continue;
|
|
1571
|
+
}
|
|
1572
|
+
if (!commandMatchesSearch(command, normalizedSearch, searchKeys)) {
|
|
1573
|
+
continue;
|
|
1574
|
+
}
|
|
1575
|
+
if (!exactNameFilter.has(command.name)) {
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
if (!commandMatchesFilters(command, filterEntries, options)) {
|
|
1579
|
+
continue;
|
|
1580
|
+
}
|
|
1581
|
+
results.push(entry);
|
|
1582
|
+
}
|
|
1583
|
+
return results;
|
|
1584
|
+
}
|
|
1466
1585
|
for (const entry of options.entries) {
|
|
1467
1586
|
const command = entry.command;
|
|
1468
1587
|
if (!commandMatchesNamespace(command, namespace)) {
|
|
@@ -1702,7 +1821,7 @@ class CommandExecutorService {
|
|
|
1702
1821
|
rejectedResult = execution.result;
|
|
1703
1822
|
}
|
|
1704
1823
|
}
|
|
1705
|
-
const fallback = this.catalog.
|
|
1824
|
+
const fallback = this.catalog.resolveRegisteredResolverFallback(normalized, includeRecord);
|
|
1706
1825
|
if (fallback.resolved) {
|
|
1707
1826
|
const execution = this.executeResolvedCommand(normalized, fallback.resolved, {
|
|
1708
1827
|
keymap: this.options.keymap,
|
|
@@ -1735,8 +1854,7 @@ class CommandExecutorService {
|
|
|
1735
1854
|
const focused = options?.focused ?? this.activation.getFocusedTargetIfAvailable();
|
|
1736
1855
|
const event = options?.event ?? this.options.createCommandEvent();
|
|
1737
1856
|
const data = this.runtime.getReadonlyData();
|
|
1738
|
-
const
|
|
1739
|
-
const chain = chainLookup.entries;
|
|
1857
|
+
const chain = this.catalog.getActiveRegisteredResolvedEntries(normalized, focused, includeRecord);
|
|
1740
1858
|
let rejectedResult;
|
|
1741
1859
|
if (chain?.length === 1) {
|
|
1742
1860
|
const [entry] = chain;
|
|
@@ -1769,7 +1887,21 @@ class CommandExecutorService {
|
|
|
1769
1887
|
rejectedResult = execution.result;
|
|
1770
1888
|
}
|
|
1771
1889
|
}
|
|
1772
|
-
|
|
1890
|
+
const fallback = this.catalog.resolveActiveResolverFallback(normalized, focused, includeRecord);
|
|
1891
|
+
if (fallback.resolved) {
|
|
1892
|
+
const execution = this.executeResolvedCommand(normalized, fallback.resolved, {
|
|
1893
|
+
keymap: this.options.keymap,
|
|
1894
|
+
event,
|
|
1895
|
+
focused,
|
|
1896
|
+
target: options?.target ?? null,
|
|
1897
|
+
data
|
|
1898
|
+
});
|
|
1899
|
+
if (execution.status === "handled" || execution.status === "error") {
|
|
1900
|
+
return execution.result;
|
|
1901
|
+
}
|
|
1902
|
+
rejectedResult = execution.result;
|
|
1903
|
+
}
|
|
1904
|
+
if (fallback.hadError) {
|
|
1773
1905
|
return { ok: false, reason: "error" };
|
|
1774
1906
|
}
|
|
1775
1907
|
const unavailable = this.catalog.getDispatchUnavailableCommandState(normalized, focused, includeRecord);
|
|
@@ -1881,21 +2013,32 @@ function applyBindingEventEffects(binding, event) {
|
|
|
1881
2013
|
}
|
|
1882
2014
|
|
|
1883
2015
|
// src/services/primitives/binding-inputs.ts
|
|
1884
|
-
function
|
|
1885
|
-
|
|
1886
|
-
|
|
2016
|
+
function isKeyLike(value) {
|
|
2017
|
+
return typeof value === "string" || !!value && typeof value === "object" && !Array.isArray(value);
|
|
2018
|
+
}
|
|
2019
|
+
function validateBindingInputs(bindings) {
|
|
2020
|
+
if (!Array.isArray(bindings)) {
|
|
2021
|
+
return { ok: false, reason: "Invalid keymap bindings: expected an array of binding objects" };
|
|
1887
2022
|
}
|
|
1888
|
-
const
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
2023
|
+
for (const [index, binding] of bindings.entries()) {
|
|
2024
|
+
if (!binding || typeof binding !== "object" || Array.isArray(binding)) {
|
|
2025
|
+
return { ok: false, reason: `Invalid keymap binding at index ${index}: expected a binding object` };
|
|
2026
|
+
}
|
|
2027
|
+
if (!isKeyLike(binding.key)) {
|
|
2028
|
+
return {
|
|
2029
|
+
ok: false,
|
|
2030
|
+
reason: `Invalid keymap binding at index ${index}: expected "key" to be a string or keystroke object`
|
|
2031
|
+
};
|
|
1892
2032
|
}
|
|
1893
|
-
normalized.push({ key, cmd });
|
|
1894
2033
|
}
|
|
1895
|
-
return
|
|
2034
|
+
return { ok: true };
|
|
1896
2035
|
}
|
|
1897
2036
|
function snapshotBindingInputs(bindings) {
|
|
1898
|
-
|
|
2037
|
+
const validation = validateBindingInputs(bindings);
|
|
2038
|
+
if (!validation.ok) {
|
|
2039
|
+
throw new Error(validation.reason);
|
|
2040
|
+
}
|
|
2041
|
+
return bindings.map((binding) => ({
|
|
1899
2042
|
...binding,
|
|
1900
2043
|
key: typeof binding.key === "string" ? binding.key : { ...binding.key }
|
|
1901
2044
|
}));
|
|
@@ -1948,6 +2091,23 @@ class CompilerService {
|
|
|
1948
2091
|
parseObjectKey: (value, options) => this.parseObjectKeyPart(value, options)
|
|
1949
2092
|
});
|
|
1950
2093
|
}
|
|
2094
|
+
parseKeySequence(key) {
|
|
2095
|
+
if (typeof key !== "string") {
|
|
2096
|
+
return [this.parseObjectKeyPart(key)];
|
|
2097
|
+
}
|
|
2098
|
+
const parsed = parseBindingSequenceWithParsers(key, this.state.environment.bindingParsers.values(), {
|
|
2099
|
+
tokens: this.state.environment.tokens,
|
|
2100
|
+
layer: EMPTY_COMPILE_FIELDS,
|
|
2101
|
+
parseObjectKey: (value, options) => this.parseObjectKeyPart(value, options)
|
|
2102
|
+
});
|
|
2103
|
+
for (const tokenName of parsed.unknownTokens) {
|
|
2104
|
+
this.options.warnUnknownToken(tokenName, key);
|
|
2105
|
+
}
|
|
2106
|
+
return parsed.parts;
|
|
2107
|
+
}
|
|
2108
|
+
formatKey(key, options) {
|
|
2109
|
+
return stringifyKeySequence(this.parseKeySequence(key), options);
|
|
2110
|
+
}
|
|
1951
2111
|
compileBindings(bindings, tokens, sourceTarget, sourceLayerOrder, compileFields) {
|
|
1952
2112
|
const root = createSequenceNode(null, null, null);
|
|
1953
2113
|
const compiledBindings = [];
|
|
@@ -3219,6 +3379,15 @@ class EnvironmentService {
|
|
|
3219
3379
|
prependBindingTransformer(transformer) {
|
|
3220
3380
|
return this.state.environment.bindingTransformers.prepend(transformer);
|
|
3221
3381
|
}
|
|
3382
|
+
prependLayerBindingsTransformer(transformer) {
|
|
3383
|
+
return this.state.environment.layerBindingsTransformers.prepend(transformer);
|
|
3384
|
+
}
|
|
3385
|
+
appendLayerBindingsTransformer(transformer) {
|
|
3386
|
+
return this.state.environment.layerBindingsTransformers.append(transformer);
|
|
3387
|
+
}
|
|
3388
|
+
clearLayerBindingsTransformers() {
|
|
3389
|
+
this.state.environment.layerBindingsTransformers.clear();
|
|
3390
|
+
}
|
|
3222
3391
|
appendBindingTransformer(transformer) {
|
|
3223
3392
|
return this.state.environment.bindingTransformers.append(transformer);
|
|
3224
3393
|
}
|
|
@@ -3417,7 +3586,7 @@ class LayerService {
|
|
|
3417
3586
|
let targetMode;
|
|
3418
3587
|
try {
|
|
3419
3588
|
targetMode = this.normalizeTargetMode(layer);
|
|
3420
|
-
bindingInputs = snapshotBindingInputs(layer.bindings ?? []);
|
|
3589
|
+
bindingInputs = this.applyLayerBindingsTransformers(snapshotBindingInputs(layer.bindings ?? []), layer);
|
|
3421
3590
|
commands = !layer.commands || layer.commands.length === 0 ? [] : this.options.commands.normalizeCommands(layer.commands);
|
|
3422
3591
|
commandLookup = createCommandLookup(commands);
|
|
3423
3592
|
({ requires, matchers, conditionKeys, hasUnkeyedMatchers, compileFields } = this.compileLayerRuntimeState(layer));
|
|
@@ -3570,6 +3739,24 @@ class LayerService {
|
|
|
3570
3739
|
}
|
|
3571
3740
|
return layer.target ? "focus-within" : undefined;
|
|
3572
3741
|
}
|
|
3742
|
+
applyLayerBindingsTransformers(bindings, layer) {
|
|
3743
|
+
const transformers = this.state.environment.layerBindingsTransformers.values();
|
|
3744
|
+
if (transformers.length === 0) {
|
|
3745
|
+
return bindings;
|
|
3746
|
+
}
|
|
3747
|
+
let current = bindings;
|
|
3748
|
+
for (const transformer of transformers) {
|
|
3749
|
+
const next = transformer(current, {
|
|
3750
|
+
layer,
|
|
3751
|
+
validateBindings: (bindings2) => validateBindingInputs(bindings2)
|
|
3752
|
+
});
|
|
3753
|
+
if (!next) {
|
|
3754
|
+
continue;
|
|
3755
|
+
}
|
|
3756
|
+
current = snapshotBindingInputs(next);
|
|
3757
|
+
}
|
|
3758
|
+
return current;
|
|
3759
|
+
}
|
|
3573
3760
|
runLayerAnalyzers(options) {
|
|
3574
3761
|
const analyzers = this.state.layers.layerAnalyzers.values();
|
|
3575
3762
|
if (analyzers.length === 0) {
|
|
@@ -4043,6 +4230,7 @@ function createKeymapState() {
|
|
|
4043
4230
|
environment: {
|
|
4044
4231
|
tokens: new Map,
|
|
4045
4232
|
layerFields: new Map,
|
|
4233
|
+
layerBindingsTransformers: new OrderedRegistry,
|
|
4046
4234
|
bindingExpanders: new OrderedRegistry,
|
|
4047
4235
|
bindingParsers: new OrderedRegistry,
|
|
4048
4236
|
bindingTransformers: new OrderedRegistry,
|
|
@@ -4239,6 +4427,12 @@ class Keymap {
|
|
|
4239
4427
|
return getKeyMatchKey(input) === match;
|
|
4240
4428
|
};
|
|
4241
4429
|
}
|
|
4430
|
+
parseKeySequence(key) {
|
|
4431
|
+
return this.compiler.parseKeySequence(key);
|
|
4432
|
+
}
|
|
4433
|
+
formatKey(key, options) {
|
|
4434
|
+
return this.compiler.formatKey(key, options);
|
|
4435
|
+
}
|
|
4242
4436
|
clearPendingSequence() {
|
|
4243
4437
|
this.activation.setPendingSequence(null);
|
|
4244
4438
|
}
|
|
@@ -4254,11 +4448,8 @@ class Keymap {
|
|
|
4254
4448
|
getCommandEntries(query) {
|
|
4255
4449
|
return this.catalog.getCommandEntries(query);
|
|
4256
4450
|
}
|
|
4257
|
-
|
|
4258
|
-
return
|
|
4259
|
-
}
|
|
4260
|
-
normalizeBindings(bindings) {
|
|
4261
|
-
return normalizeBindingInputs(bindings);
|
|
4451
|
+
getCommandBindings(query) {
|
|
4452
|
+
return this.catalog.getCommandBindings(query);
|
|
4262
4453
|
}
|
|
4263
4454
|
acquireResource(key, setup) {
|
|
4264
4455
|
if (this.cleanedUp || this.host.isDestroyed) {
|
|
@@ -4305,6 +4496,15 @@ class Keymap {
|
|
|
4305
4496
|
registerLayerFields(fields) {
|
|
4306
4497
|
return this.environment.registerLayerFields(fields);
|
|
4307
4498
|
}
|
|
4499
|
+
prependLayerBindingsTransformer(transformer) {
|
|
4500
|
+
return this.environment.prependLayerBindingsTransformer(transformer);
|
|
4501
|
+
}
|
|
4502
|
+
appendLayerBindingsTransformer(transformer) {
|
|
4503
|
+
return this.environment.appendLayerBindingsTransformer(transformer);
|
|
4504
|
+
}
|
|
4505
|
+
clearLayerBindingsTransformers() {
|
|
4506
|
+
this.environment.clearLayerBindingsTransformers();
|
|
4507
|
+
}
|
|
4308
4508
|
prependBindingTransformer(transformer) {
|
|
4309
4509
|
return this.environment.prependBindingTransformer(transformer);
|
|
4310
4510
|
}
|
package/src/keymap.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ActiveKey, ActiveKeyOptions,
|
|
1
|
+
import type { ActiveBinding, ActiveKey, ActiveKeyOptions, BindingExpander, BindingParser, BindingFieldCompiler, LayerBindingsTransformer, BindingTransformer, Events, CommandFieldCompiler, CommandBindingsQuery, CommandEntry, CommandQuery, CommandRecord, KeymapEvent, KeymapHost, LayerAnalyzer, Listener, RunCommandOptions, RunCommandResult, CommandResolver, KeyInterceptOptions, KeyInputContext, Layer, LayerFieldCompiler, KeyDisambiguationResolver, RawInterceptOptions, RawInputContext, EventMatchResolver, KeyStringifyInput, KeyToken, KeyLike, KeySequencePart, StringifyOptions } from "./types.js";
|
|
2
2
|
export declare class Keymap<TTarget extends object, TEvent extends KeymapEvent = KeymapEvent> {
|
|
3
3
|
private readonly host;
|
|
4
4
|
private readonly state;
|
|
@@ -28,13 +28,14 @@ export declare class Keymap<TTarget extends object, TEvent extends KeymapEvent =
|
|
|
28
28
|
hasPendingSequence(): boolean;
|
|
29
29
|
getPendingSequence(): readonly KeySequencePart[];
|
|
30
30
|
createKeyMatcher(key: KeyLike): (input: KeyStringifyInput | null | undefined) => boolean;
|
|
31
|
+
parseKeySequence(key: KeyLike): readonly KeySequencePart[];
|
|
32
|
+
formatKey(key: KeyLike, options?: StringifyOptions): string;
|
|
31
33
|
clearPendingSequence(): void;
|
|
32
34
|
popPendingSequence(): boolean;
|
|
33
35
|
getActiveKeys(options?: ActiveKeyOptions): readonly ActiveKey<TTarget, TEvent>[];
|
|
34
36
|
getCommands(query?: CommandQuery<TTarget>): readonly CommandRecord[];
|
|
35
37
|
getCommandEntries(query?: CommandQuery<TTarget>): readonly CommandEntry<TTarget, TEvent>[];
|
|
36
|
-
|
|
37
|
-
normalizeBindings(bindings: Bindings<TTarget, TEvent>): BindingInput<TTarget, TEvent>[];
|
|
38
|
+
getCommandBindings(query: CommandBindingsQuery<TTarget>): ReadonlyMap<string, readonly ActiveBinding<TTarget, TEvent>[]>;
|
|
38
39
|
acquireResource(key: symbol, setup: () => () => void): () => void;
|
|
39
40
|
runCommand(cmd: string, options?: RunCommandOptions<TTarget, TEvent>): RunCommandResult;
|
|
40
41
|
dispatchCommand(cmd: string, options?: RunCommandOptions<TTarget, TEvent>): RunCommandResult;
|
|
@@ -46,6 +47,9 @@ export declare class Keymap<TTarget extends object, TEvent extends KeymapEvent =
|
|
|
46
47
|
intercept(name: "raw", fn: (ctx: RawInputContext) => void, options?: RawInterceptOptions): () => void;
|
|
47
48
|
registerLayer(layer: Layer<TTarget, TEvent>): () => void;
|
|
48
49
|
registerLayerFields(fields: Record<string, LayerFieldCompiler>): () => void;
|
|
50
|
+
prependLayerBindingsTransformer(transformer: LayerBindingsTransformer<TTarget, TEvent>): () => void;
|
|
51
|
+
appendLayerBindingsTransformer(transformer: LayerBindingsTransformer<TTarget, TEvent>): () => void;
|
|
52
|
+
clearLayerBindingsTransformers(): void;
|
|
49
53
|
prependBindingTransformer(transformer: BindingTransformer<TTarget, TEvent>): () => void;
|
|
50
54
|
appendBindingTransformer(transformer: BindingTransformer<TTarget, TEvent>): () => void;
|
|
51
55
|
clearBindingTransformers(): void;
|