Add split-pane layout store and navigation shortcuts
This commit is contained in:
@@ -18,6 +18,17 @@ export type KeyboardActionId =
|
||||
| "workspace.tab.close.current"
|
||||
| "workspace.tab.navigate.index"
|
||||
| "workspace.tab.navigate.relative"
|
||||
| "workspace.pane.split.right"
|
||||
| "workspace.pane.split.down"
|
||||
| "workspace.pane.focus.left"
|
||||
| "workspace.pane.focus.right"
|
||||
| "workspace.pane.focus.up"
|
||||
| "workspace.pane.focus.down"
|
||||
| "workspace.pane.move-tab.left"
|
||||
| "workspace.pane.move-tab.right"
|
||||
| "workspace.pane.move-tab.up"
|
||||
| "workspace.pane.move-tab.down"
|
||||
| "workspace.pane.close"
|
||||
| "workspace.navigate.index"
|
||||
| "workspace.navigate.relative"
|
||||
| "sidebar.toggle.left"
|
||||
|
||||
@@ -13,7 +13,18 @@ export type KeyboardActionId =
|
||||
| "workspace.tab.new"
|
||||
| "workspace.tab.close-current"
|
||||
| "workspace.tab.navigate-index"
|
||||
| "workspace.tab.navigate-relative";
|
||||
| "workspace.tab.navigate-relative"
|
||||
| "workspace.pane.split.right"
|
||||
| "workspace.pane.split.down"
|
||||
| "workspace.pane.focus.left"
|
||||
| "workspace.pane.focus.right"
|
||||
| "workspace.pane.focus.up"
|
||||
| "workspace.pane.focus.down"
|
||||
| "workspace.pane.move-tab.left"
|
||||
| "workspace.pane.move-tab.right"
|
||||
| "workspace.pane.move-tab.up"
|
||||
| "workspace.pane.move-tab.down"
|
||||
| "workspace.pane.close";
|
||||
|
||||
export type KeyboardActionDefinition =
|
||||
| { id: "message-input.focus"; scope: KeyboardActionScope }
|
||||
@@ -24,7 +35,18 @@ export type KeyboardActionDefinition =
|
||||
| { id: "workspace.tab.new"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.tab.close-current"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.tab.navigate-index"; scope: KeyboardActionScope; index: number }
|
||||
| { id: "workspace.tab.navigate-relative"; scope: KeyboardActionScope; delta: 1 | -1 };
|
||||
| { id: "workspace.tab.navigate-relative"; scope: KeyboardActionScope; delta: 1 | -1 }
|
||||
| { id: "workspace.pane.split.right"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.split.down"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.focus.left"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.focus.right"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.focus.up"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.focus.down"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.move-tab.left"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.move-tab.right"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.move-tab.up"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.move-tab.down"; scope: KeyboardActionScope }
|
||||
| { id: "workspace.pane.close"; scope: KeyboardActionScope };
|
||||
|
||||
export type KeyboardActionHandler = {
|
||||
handlerId: string;
|
||||
|
||||
@@ -169,6 +169,42 @@ describe("keyboard-shortcuts", () => {
|
||||
context: { isMac: true, isTauri: true },
|
||||
action: "workspace.tab.close.current",
|
||||
},
|
||||
{
|
||||
name: "matches Cmd+Backslash to split pane right on macOS",
|
||||
event: { key: "\\", code: "Backslash", metaKey: true },
|
||||
context: { isMac: true },
|
||||
action: "workspace.pane.split.right",
|
||||
},
|
||||
{
|
||||
name: "matches Cmd+Shift+Backslash to split pane down on macOS",
|
||||
event: { key: "|", code: "Backslash", metaKey: true, shiftKey: true },
|
||||
context: { isMac: true },
|
||||
action: "workspace.pane.split.down",
|
||||
},
|
||||
{
|
||||
name: "matches Cmd+Shift+ArrowRight to focus pane right on macOS",
|
||||
event: { key: "ArrowRight", code: "ArrowRight", metaKey: true, shiftKey: true },
|
||||
context: { isMac: true },
|
||||
action: "workspace.pane.focus.right",
|
||||
},
|
||||
{
|
||||
name: "matches Cmd+Shift+Alt+ArrowDown to move tab down on macOS",
|
||||
event: {
|
||||
key: "ArrowDown",
|
||||
code: "ArrowDown",
|
||||
metaKey: true,
|
||||
shiftKey: true,
|
||||
altKey: true,
|
||||
},
|
||||
context: { isMac: true },
|
||||
action: "workspace.pane.move-tab.down",
|
||||
},
|
||||
{
|
||||
name: "matches Cmd+Shift+W to close pane on macOS",
|
||||
event: { key: "W", code: "KeyW", metaKey: true, shiftKey: true },
|
||||
context: { isMac: true },
|
||||
action: "workspace.pane.close",
|
||||
},
|
||||
{
|
||||
name: "matches Cmd+B sidebar toggle on macOS",
|
||||
event: { key: "b", code: "KeyB", metaKey: true },
|
||||
@@ -242,6 +278,11 @@ describe("keyboard-shortcuts", () => {
|
||||
event: { key: "d", code: "KeyD", metaKey: true },
|
||||
context: { isMac: true, focusScope: "terminal" },
|
||||
},
|
||||
{
|
||||
name: "does not bind pane shortcuts on non-mac platforms",
|
||||
event: { key: "\\", code: "Backslash", ctrlKey: true },
|
||||
context: { isMac: false },
|
||||
},
|
||||
{
|
||||
name: "keeps space typing available in message input",
|
||||
event: { key: " ", code: "Space" },
|
||||
@@ -278,6 +319,8 @@ describe("keyboard-shortcut help sections", () => {
|
||||
"workspace-jump-index": ["alt", "1-9"],
|
||||
"workspace-tab-jump-index": ["alt", "shift", "1-9"],
|
||||
"workspace-tab-close-current": ["alt", "shift", "W"],
|
||||
"workspace-pane-split-right": ["mod", "\\"],
|
||||
"workspace-pane-close": ["mod", "shift", "W"],
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -289,6 +332,8 @@ describe("keyboard-shortcut help sections", () => {
|
||||
"workspace-jump-index": ["mod", "1-9"],
|
||||
"workspace-tab-jump-index": ["alt", "1-9"],
|
||||
"workspace-tab-close-current": ["mod", "W"],
|
||||
"workspace-pane-split-right": ["mod", "\\"],
|
||||
"workspace-pane-close": ["mod", "shift", "W"],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -71,6 +71,10 @@ function isMod(event: KeyboardEvent): boolean {
|
||||
return event.metaKey || event.ctrlKey;
|
||||
}
|
||||
|
||||
function isMacCommand(event: KeyboardEvent): boolean {
|
||||
return event.metaKey && !event.ctrlKey;
|
||||
}
|
||||
|
||||
function parseDigit(event: KeyboardEvent): number | null {
|
||||
const code = event.code ?? "";
|
||||
if (code.startsWith("Digit")) {
|
||||
@@ -373,6 +377,204 @@ const SHORTCUT_BINDINGS: readonly KeyboardShortcutBinding[] = [
|
||||
keys: ["alt", "shift", "]"],
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-split-right-cmd-backslash",
|
||||
action: "workspace.pane.split.right",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
!event.shiftKey &&
|
||||
event.code === "Backslash",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-split-right",
|
||||
section: "global",
|
||||
label: "Split pane right",
|
||||
keys: ["mod", "\\"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-split-down-cmd-shift-backslash",
|
||||
action: "workspace.pane.split.down",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "Backslash",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-split-down",
|
||||
section: "global",
|
||||
label: "Split pane down",
|
||||
keys: ["mod", "shift", "\\"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-focus-left-cmd-shift-left",
|
||||
action: "workspace.pane.focus.left",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowLeft",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-focus-left",
|
||||
section: "global",
|
||||
label: "Focus pane left",
|
||||
keys: ["mod", "shift", "Left"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-focus-right-cmd-shift-right",
|
||||
action: "workspace.pane.focus.right",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowRight",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-focus-right",
|
||||
section: "global",
|
||||
label: "Focus pane right",
|
||||
keys: ["mod", "shift", "Right"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-focus-up-cmd-shift-up",
|
||||
action: "workspace.pane.focus.up",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowUp",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-focus-up",
|
||||
section: "global",
|
||||
label: "Focus pane up",
|
||||
keys: ["mod", "shift", "Up"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-focus-down-cmd-shift-down",
|
||||
action: "workspace.pane.focus.down",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowDown",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-focus-down",
|
||||
section: "global",
|
||||
label: "Focus pane down",
|
||||
keys: ["mod", "shift", "Down"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-move-tab-left-cmd-shift-alt-left",
|
||||
action: "workspace.pane.move-tab.left",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowLeft",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-move-tab-left",
|
||||
section: "global",
|
||||
label: "Move tab left",
|
||||
keys: ["mod", "shift", "alt", "Left"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-move-tab-right-cmd-shift-alt-right",
|
||||
action: "workspace.pane.move-tab.right",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowRight",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-move-tab-right",
|
||||
section: "global",
|
||||
label: "Move tab right",
|
||||
keys: ["mod", "shift", "alt", "Right"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-move-tab-up-cmd-shift-alt-up",
|
||||
action: "workspace.pane.move-tab.up",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowUp",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-move-tab-up",
|
||||
section: "global",
|
||||
label: "Move tab up",
|
||||
keys: ["mod", "shift", "alt", "Up"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-move-tab-down-cmd-shift-alt-down",
|
||||
action: "workspace.pane.move-tab.down",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
event.altKey &&
|
||||
event.shiftKey &&
|
||||
event.code === "ArrowDown",
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-move-tab-down",
|
||||
section: "global",
|
||||
label: "Move tab down",
|
||||
keys: ["mod", "shift", "alt", "Down"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "workspace-pane-close-cmd-shift-w",
|
||||
action: "workspace.pane.close",
|
||||
matches: (event) =>
|
||||
isMacCommand(event) &&
|
||||
!event.altKey &&
|
||||
event.shiftKey &&
|
||||
(event.code === "KeyW" || event.key.toLowerCase() === "w"),
|
||||
when: (context) =>
|
||||
context.isMac && context.focusScope !== "terminal" && !context.commandCenterOpen,
|
||||
help: {
|
||||
id: "workspace-pane-close",
|
||||
section: "global",
|
||||
label: "Close pane",
|
||||
keys: ["mod", "shift", "W"],
|
||||
when: (context) => context.isMac,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "command-center-toggle",
|
||||
action: "command-center.toggle",
|
||||
|
||||
Reference in New Issue
Block a user