diff --git a/docs/contract.md b/docs/contract.md index 953b5eb..8d6ee69 100644 --- a/docs/contract.md +++ b/docs/contract.md @@ -102,7 +102,8 @@ Editing flow: - `Enter`: save and submit the current input - `Esc`: save draft and close the editor -- `Up`, `Down`, `Tab`, `Shift+Tab`: save draft and continue navigation +- arrow keys and `Tab` stay in the editor so the cursor can move while typing +- navigation resumes only after closing the editor with `Esc` ## Non-interactive mode diff --git a/src/ui/constants.ts b/src/ui/constants.ts index 54eac9a..6525243 100644 --- a/src/ui/constants.ts +++ b/src/ui/constants.ts @@ -16,8 +16,8 @@ export const UI_TEXT = { reviewTitle: "Review your answers", readyToSubmit: "Ready to submit your answers?", unanswered: "→ (unanswered)", - footerInput: " Enter submit · Esc save and close · Tab/←→ save and navigate", - footerNote: " Enter save · Esc save and close · Tab/←→ save and navigate", + footerInput: " Enter submit · Esc save and close", + footerNote: " Enter save · Esc save and close", footerSubmit: " ↑↓ select · Enter confirm · Esc cancel", footerMulti: " ⇆ tab · ↑↓ select · Space toggle · Enter continue · N option note · Ctrl+N question note · Esc dismiss · 1-9 quick toggle", diff --git a/src/ui/input.ts b/src/ui/input.ts index 1f1d712..6bd3546 100644 --- a/src/ui/input.ts +++ b/src/ui/input.ts @@ -42,18 +42,6 @@ export function formatKeybindingLabel(key: string): string { } function getEditingInputCommand(data: string): AskInputCommand { - if (matchesKey(data, Key.tab) || matchesKey(data, Key.right)) { - return { kind: "editMoveTab", delta: 1 }; - } - if (matchesKey(data, Key.shift("tab")) || matchesKey(data, Key.left)) { - return { kind: "editMoveTab", delta: -1 }; - } - if (matchesKey(data, Key.up)) { - return { kind: "editMoveOption", delta: -1 }; - } - if (matchesKey(data, Key.down)) { - return { kind: "editMoveOption", delta: 1 }; - } if (matchesKey(data, Key.escape)) { return { kind: "editClose" }; } diff --git a/tests/input.test.ts b/tests/input.test.ts index 3d60b46..8e8fe9a 100644 --- a/tests/input.test.ts +++ b/tests/input.test.ts @@ -21,19 +21,35 @@ function inputState() { return state; } -test("editing views let up and down move navigation", () => { +test("typing mode delegates arrow keys to the editor", () => { const input = inputState(); + assert.deepEqual(getInputCommand(input, "\x1b[A"), { - kind: "editMoveOption", - delta: -1, + kind: "delegateToEditor", }); assert.deepEqual(getInputCommand(input, "\x1b[B"), { - kind: "editMoveOption", - delta: 1, + kind: "delegateToEditor", + }); + assert.deepEqual(getInputCommand(input, "\x1b[C"), { + kind: "delegateToEditor", + }); + assert.deepEqual(getInputCommand(input, "\x1b[D"), { + kind: "delegateToEditor", }); }); -test("note editing views let up and down move navigation", () => { +test("typing mode delegates tab to the editor", () => { + const input = inputState(); + + assert.deepEqual(getInputCommand(input, "\t"), { + kind: "delegateToEditor", + }); + assert.deepEqual(getInputCommand(input, "\x1b[Z"), { + kind: "delegateToEditor", + }); +}); + +test("note editing mode delegates arrows and tab to the editor", () => { const state = enterQuestionNoteMode( createInitialState({ questions: [ @@ -48,11 +64,18 @@ test("note editing views let up and down move navigation", () => { ); assert.deepEqual(getInputCommand(state, "\x1b[A"), { - kind: "editMoveOption", - delta: -1, + kind: "delegateToEditor", }); assert.deepEqual(getInputCommand(state, "\x1b[B"), { - kind: "editMoveOption", - delta: 1, + kind: "delegateToEditor", + }); + assert.deepEqual(getInputCommand(state, "\x1b[C"), { + kind: "delegateToEditor", + }); + assert.deepEqual(getInputCommand(state, "\x1b[D"), { + kind: "delegateToEditor", + }); + assert.deepEqual(getInputCommand(state, "\t"), { + kind: "delegateToEditor", }); }); diff --git a/tests/render-helpers.test.ts b/tests/render-helpers.test.ts index d644747..a22e82a 100644 --- a/tests/render-helpers.test.ts +++ b/tests/render-helpers.test.ts @@ -1,6 +1,9 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { renderEditorBlock } from "../src/ui/render-helpers.ts"; +import { + renderEditorBlock, + renderFooterText, +} from "../src/ui/render-helpers.ts"; const ABC_PATTERN = /abc/; const BORDER_PATTERN = /┌|└/; @@ -69,3 +72,8 @@ test("renderEditorBlock reapplies background after editor reset sequences", () = assert.match(lines[0], SELECTED_BG_PATTERN); assert(lines[0].includes("\x1b[0m{selectedBg}")); }); + +test("editing footers do not advertise tab navigation", () => { + assert.equal(renderFooterText("input"), " Enter submit · Esc save and close"); + assert.equal(renderFooterText("note"), " Enter save · Esc save and close"); +});