Skip to content

Move key handling into EditorState.handleKey (step 3b)#190

Merged
shellicar merged 1 commit intomainfrom
feature/editor-handle-key
Apr 6, 2026
Merged

Move key handling into EditorState.handleKey (step 3b)#190
shellicar merged 1 commit intomainfrom
feature/editor-handle-key

Conversation

@shellicar
Copy link
Copy Markdown
Owner

What

All editor key transitions move from AppLayout into EditorState.handleKey.

Changes

  • EditorState.handleKey(key: KeyAction): boolean — handles every editing key; returns true when consumed so the caller schedules a re-render, false for ctrl+enter and unknown keys
  • #wordStartLeft / #wordEndRight move from AppLayout into EditorState as private helpers
  • lines getter now returns readonly string[] — enforces that AppLayout only reads for rendering
  • AppLayout.handleKey collapses from a 220-line switch to four lines: delegate to handleKey, schedule render, then handle ctrl+enter inline
  • ctrl+enter stays in AppLayout: it reads #attachments and resolves #editorResolve, which are not editor state

Testing

56 unit tests in EditorState.spec.ts cover every key case as pure state assertions — no ANSI, no rendering, no terminal.

All editor key transitions now live in EditorState: enter, backspace,
delete, ctrl+backspace/delete/k/u, left/right/up/down, home/end,
ctrl+home/end, ctrl+left/right, and char. The word-navigation helpers
(wordStartLeft, wordEndRight) moved with them as private methods.

handleKey returns true when it consumed the key so the caller knows
to schedule a re-render. It returns false for ctrl+enter (which
involves attachments and a promise resolve that live in AppLayout)
and for unknown keys.

AppLayout.handleKey collapses from a 220-line switch to a four-line
delegate plus the ctrl+enter block. The lines getter now returns
readonly string[] — the type reflects that AppLayout reads it for
rendering only; all mutations go through handleKey or reset.

56 unit tests cover every key case as pure state assertions.
@shellicar shellicar added this to the 1.0 milestone Apr 6, 2026
@shellicar shellicar added the enhancement New feature or request label Apr 6, 2026
@shellicar shellicar self-assigned this Apr 6, 2026
@shellicar shellicar requested a review from bananabot9000 April 6, 2026 10:37
@shellicar shellicar enabled auto-merge (squash) April 6, 2026 10:38
Copy link
Copy Markdown
Collaborator

@bananabot9000 bananabot9000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Textbook state extraction 🍌

220 lines of key handling → EditorState.handleKey() returning boolean (consumed/not-mine). Clean delegate pattern. AppLayout collapses to ~4 lines for the editor path plus the ctrl+enter submit block.

Boundary is right: ctrl+enter stays in AppLayout (touches #attachments, #editorResolve — not editor state). Everything that affects text/cursor is in EditorState. Everything that affects the app stays out.

readonly string[] on lines getter — compile-time enforcement that AppLayout can't accidentally mutate. Public setters removed. All mutation is internal to EditorState now. The contract from 3a is tightened.

56 tests covering every key case as pure state assertions. Boundary cases included (col 0 backspace, line 0 up-arrow, word nav with trailing spaces). ctrl+enter and unknown keys explicitly tested to return false.

One observation (not blocking): every editor key returns true even when no state changed (e.g. up-arrow at line 0). This means a no-op still triggers a render. Fine for now — it's a render performance knob for later if needed.

text getter from 3a correctly reused in the ctrl+enter path. JSDoc updated. KeyAction is a type-only import — no runtime dependency on the input layer.

Ship it 🚢🍌

@shellicar shellicar merged commit 4aa6535 into main Apr 6, 2026
4 checks passed
@shellicar shellicar deleted the feature/editor-handle-key branch April 6, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants