From b7a8b2009113f7d0898e6ab32adf34258adb30a9 Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Thu, 2 Jul 2026 18:03:20 -0400 Subject: [PATCH 1/2] fix: quit only on q shortcut --- .changeset/quit-with-q-only.md | 5 +++ src/ui/AppHost.interactions.test.tsx | 44 ++++++++++++++++++++++++- src/ui/hooks/useAppKeyboardShortcuts.ts | 7 +--- 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 .changeset/quit-with-q-only.md diff --git a/.changeset/quit-with-q-only.md b/.changeset/quit-with-q-only.md new file mode 100644 index 00000000..6f5c0cc3 --- /dev/null +++ b/.changeset/quit-with-q-only.md @@ -0,0 +1,5 @@ +--- +"hunkdiff": patch +--- + +Stop treating Escape as a global quit shortcut; use `q` to quit while preserving Escape for dialogs and focused controls. diff --git a/src/ui/AppHost.interactions.test.tsx b/src/ui/AppHost.interactions.test.tsx index 8dba4a6e..cb5adda1 100644 --- a/src/ui/AppHost.interactions.test.tsx +++ b/src/ui/AppHost.interactions.test.tsx @@ -3356,7 +3356,7 @@ describe("App interactions", () => { } }); - test("quit shortcuts route through the provided onQuit handler in regular and pager modes", async () => { + test("q routes through the provided onQuit handler in regular and pager modes", async () => { const regularQuit = mock(() => undefined); const regularSetup = await testRender( , @@ -3397,4 +3397,46 @@ describe("App interactions", () => { }); } }); + + test("Escape does not quit in regular or pager modes", async () => { + const regularQuit = mock(() => undefined); + const regularSetup = await testRender( + , + { width: 220, height: 24 }, + ); + + try { + await flush(regularSetup); + await act(async () => { + await regularSetup.mockInput.pressEscape(); + }); + await flush(regularSetup); + + expect(regularQuit).toHaveBeenCalledTimes(0); + } finally { + await act(async () => { + regularSetup.renderer.destroy(); + }); + } + + const pagerQuit = mock(() => undefined); + const pagerSetup = await testRender( + , + { width: 180, height: 20 }, + ); + + try { + await flush(pagerSetup); + await act(async () => { + await pagerSetup.mockInput.pressEscape(); + }); + await flush(pagerSetup); + + expect(pagerQuit).toHaveBeenCalledTimes(0); + } finally { + await act(async () => { + pagerSetup.renderer.destroy(); + }); + } + }); }); diff --git a/src/ui/hooks/useAppKeyboardShortcuts.ts b/src/ui/hooks/useAppKeyboardShortcuts.ts index eb1e19a5..d6f35ded 100644 --- a/src/ui/hooks/useAppKeyboardShortcuts.ts +++ b/src/ui/hooks/useAppKeyboardShortcuts.ts @@ -202,7 +202,7 @@ export function useAppKeyboardShortcuts({ return; } - if (key.name === "q" || isEscapeKey(key)) { + if (key.name === "q") { requestQuit(); return; } @@ -415,11 +415,6 @@ export function useAppKeyboardShortcuts({ return; } - if (isEscapeKey(key)) { - requestQuit(); - return; - } - if (key.name === "tab") { toggleFocusArea(); return; From c6cf54e4c8974dd892ee51dcaaf3e86b961c9728 Mon Sep 17 00:00:00 2001 From: Ben Vinegar Date: Thu, 2 Jul 2026 18:19:06 -0400 Subject: [PATCH 2/2] chore: format README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 520b24c6..a6189e45 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Or with Homebrew: ```bash brew install hunk ``` + > [!NOTE] > If you previously installed hunk via `modem-dev/tap`, be sure to uninstall it first with `brew uninstall modem-dev/tap/hunk`.