Просмотр исходного кода

fix(tui): restore composer shell kill shortcut (#42366)

Kit Langton 3 дней назад
Родитель
Сommit
2cf20e660e

+ 13 - 0
packages/tui/src/routes/session/composer/shell-tab.tsx

@@ -23,6 +23,19 @@ export function ShellTab(props: { sessionID: string }) {
 
   const selectedEntry = createMemo(() => entries()[store.selected])
 
+  const keymap = Keymap.use()
+  createEffect(() => {
+    if (!composer.active("shell")) return
+    const cleanup = keymap.intercept("key", ({ event, consume }) => {
+      if (event.name !== "d" || !event.ctrl) return
+      if (!shortcuts.list("composer.shell.kill").includes("ctrl+d")) return
+      if (!selectedEntry()) return
+      consume()
+      keymap.dispatch("composer.shell.kill")
+    })
+    onCleanup(cleanup)
+  })
+
   createEffect(() => {
     if (store.selected >= entries().length) setStore("selected", Math.max(0, entries().length - 1))
   })

+ 33 - 2
packages/tui/test/cli/tui/composer-keymap.test.tsx

@@ -23,7 +23,11 @@ const sessions = {
 
 const shells = [shell("sh-a", "bun test"), shell("sh-b", "bun dev")]
 
-async function renderComposer(defaultTab: "subagents" | "shell", keybinds: Partial<TuiKeybind.Keybinds>) {
+async function renderComposer(
+  defaultTab: "subagents" | "shell",
+  keybinds: Partial<TuiKeybind.Keybinds>,
+  focusedTextarea = false,
+) {
   const events = createEventStream()
   const interrupted: string[] = []
   const removed: string[] = []
@@ -69,7 +73,21 @@ async function renderComposer(defaultTab: "subagents" | "shell", keybinds: Parti
         .then(() => wait(() => data.session.status("child-a") === "running"))
         .then(() => ready.resolve(), ready.reject)
     })
-    return <Composer sessionID="parent" open={true} defaultTab={defaultTab} onClose={() => closed++} />
+    return (
+      <>
+        {focusedTextarea && <textarea focused={true} initialValue="draft" />}
+        <Composer sessionID="parent" open={true} defaultTab={defaultTab} onClose={() => closed++} />
+      </>
+    )
+  }
+
+  function AppExit() {
+    Keymap.createLayer(() => ({
+      mode: "global",
+      commands: [{ id: "app.exit", title: "Exit", group: "System", run: () => {} }],
+    }))
+    Keymap.createLayer(() => ({ bindings: ["app.exit"] }))
+    return null
   }
 
   const app = await testRender(
@@ -77,6 +95,7 @@ async function renderComposer(defaultTab: "subagents" | "shell", keybinds: Parti
       <TestTuiContexts directory={directory}>
         <ConfigProvider config={createTuiResolvedConfig({ keybinds })}>
           <Keymap.Provider>
+            <AppExit />
             <ClientProvider api={createApi(calls.fetch)}>
               <DataProvider>
                 <LocationProvider>
@@ -154,6 +173,18 @@ test("disabled shell bindings have no component fallbacks", async () => {
   }
 })
 
+test("shell kill binding overrides app exit", async () => {
+  const composer = await renderComposer("shell", {}, true)
+  try {
+    expect(composer.app.captureCharFrame()).toContain("bun test")
+    composer.app.mockInput.pressKey("d", { ctrl: true })
+    await wait(() => composer.removed.length === 1)
+    expect(composer.removed).toEqual(["sh-a"])
+  } finally {
+    composer.app.renderer.destroy()
+  }
+})
+
 function session(id: string, title: string, parentID?: string) {
   return {
     id,