Skip to content

Commit 84c855e

Browse files
committed
fix(keybindings): honor null overrides and terminal shortcut forwarding
1 parent b6ae63c commit 84c855e

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

src/cm/commandRegistry.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const commandKeymapCompartment = new Compartment();
108108
* run: (view?: EditorView | null) => boolean | void;
109109
* requiresView?: boolean;
110110
* defaultDescription?: string;
111+
* defaultKey?: string | null;
111112
* key?: string | null;
112113
* }} CommandEntry
113114
*/
@@ -1177,6 +1178,7 @@ function addCommand(entry) {
11771178
const command = {
11781179
...entry,
11791180
defaultDescription: entry.description || entry.name,
1181+
defaultKey: entry.key ?? null,
11801182
key: entry.key ?? null,
11811183
};
11821184
commandMap.set(entry.name, command);
@@ -1314,6 +1316,26 @@ function parseKeyString(keyString) {
13141316
.filter(Boolean);
13151317
}
13161318

1319+
function hasOwnBindingOverride(name) {
1320+
return Object.prototype.hasOwnProperty.call(resolvedKeyBindings ?? {}, name);
1321+
}
1322+
1323+
function resolveBindingInfo(name) {
1324+
const baseBinding = keyBindings[name] ?? null;
1325+
if (!hasOwnBindingOverride(name)) return baseBinding;
1326+
1327+
const override = resolvedKeyBindings?.[name];
1328+
if (override === null) {
1329+
return baseBinding ? { ...baseBinding, key: null } : { key: null };
1330+
}
1331+
1332+
if (!override || typeof override !== "object") {
1333+
return baseBinding;
1334+
}
1335+
1336+
return baseBinding ? { ...baseBinding, ...override } : override;
1337+
}
1338+
13171339
function toCodeMirrorKey(combo) {
13181340
if (!combo) return null;
13191341
const parts = combo
@@ -1356,10 +1378,13 @@ function toCodeMirrorKey(combo) {
13561378
function rebuildKeymap() {
13571379
const bindings = [];
13581380
commandMap.forEach((command, name) => {
1359-
const bindingInfo = resolvedKeyBindings?.[name];
1381+
const bindingInfo = resolveBindingInfo(name);
13601382
command.description =
13611383
bindingInfo?.description || command.defaultDescription;
1362-
const keySource = bindingInfo?.key ?? command.key ?? null;
1384+
const keySource =
1385+
bindingInfo && Object.prototype.hasOwnProperty.call(bindingInfo, "key")
1386+
? bindingInfo.key
1387+
: (command.defaultKey ?? null);
13631388
command.key = keySource;
13641389
const combos = parseKeyString(keySource);
13651390
combos.forEach((combo) => {
@@ -1410,6 +1435,19 @@ export function getRegisteredCommands() {
14101435
}));
14111436
}
14121437

1438+
export function getResolvedKeyBindings() {
1439+
const bindingNames = new Set([
1440+
...Object.keys(keyBindings),
1441+
...Object.keys(resolvedKeyBindings ?? {}),
1442+
]);
1443+
1444+
return Object.fromEntries(
1445+
Array.from(bindingNames, (name) => [name, resolveBindingInfo(name)]).filter(
1446+
([, binding]) => binding,
1447+
),
1448+
);
1449+
}
1450+
14131451
export function getCommandKeymapExtension() {
14141452
return commandKeymapCompartment.of(keymap.of(cachedKeymap));
14151453
}

src/components/terminal/terminal.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import { Unicode11Addon } from "@xterm/addon-unicode11";
1111
import { WebLinksAddon } from "@xterm/addon-web-links";
1212
import { WebglAddon } from "@xterm/addon-webgl";
1313
import { Terminal as Xterm } from "@xterm/xterm";
14+
import { getResolvedKeyBindings } from "cm/commandRegistry";
1415
import toast from "components/toast";
1516
import confirm from "dialogs/confirm";
1617
import fonts from "lib/fonts";
17-
import keyBindings from "lib/keyBindings";
1818
import appSettings from "lib/settings";
1919
import LigaturesAddon from "./ligatures";
2020
import { getTerminalSettings } from "./terminalDefaults";
@@ -337,7 +337,7 @@ export default class TerminalComponent {
337337
parseAppKeybindings() {
338338
const parsedBindings = [];
339339

340-
Object.values(keyBindings).forEach((binding) => {
340+
Object.values(getResolvedKeyBindings()).forEach((binding) => {
341341
if (!binding.key) return;
342342

343343
// Skip editor-only keybindings in terminal
@@ -368,7 +368,7 @@ export default class TerminalComponent {
368368
parsed.meta = true;
369369
} else {
370370
// This is the actual key
371-
parsed.key = part;
371+
parsed.key = part.toLowerCase();
372372
}
373373
});
374374

@@ -432,7 +432,7 @@ export default class TerminalComponent {
432432
binding.shift === event.shiftKey &&
433433
binding.alt === event.altKey &&
434434
binding.meta === event.metaKey &&
435-
binding.key === event.key,
435+
binding.key === event.key.toLowerCase(),
436436
);
437437

438438
if (isAppKeybinding) {

0 commit comments

Comments
 (0)