mirror of
https://github.com/anomalyco/opentui.git
synced 2026-04-25 04:55:58 +03:00
[PR #770] [MERGED] core: add stdin tokenizer/router #1551
Labels
No labels
bug
core
documentation
feature
good first issue
help wanted
pull-request
question
react
solid
tmux
windows
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/opentui#1551
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/anomalyco/opentui/pull/770
Author: @simonklee
Created: 3/2/2026
Status: ✅ Merged
Merged: 3/9/2026
Merged by: @kommander
Base:
main← Head:stdin-unified📝 Commits (10+)
bfe7b0dcore: add stdin tokenizer/router6c4efaffix overflow and memory model375e317labeled switch parser8426a56add focus + mouse event test4f7281aterminal-palette cleanup5707b64fix zig stdin timeout parity and overflow recovery78ce9d7more memory mng issues612efedmemory ownership clarification0088a95remove unused fields804a6bbfix zig stdin paste parity and high-byte timeout fallback📊 Changes
24 files changed (+4048 additions, -1648 deletions)
View changed files
📝
packages/core/src/lib/KeyHandler.integration.test.ts(+20 -10)📝
packages/core/src/lib/KeyHandler.stopPropagation.test.ts(+23 -13)📝
packages/core/src/lib/KeyHandler.test.ts(+38 -31)📝
packages/core/src/lib/KeyHandler.ts(+3 -21)➕
packages/core/src/lib/clock.ts(+21 -0)📝
packages/core/src/lib/index.ts(+2 -1)📝
packages/core/src/lib/parse.keypress-kitty.test.ts(+23 -0)📝
packages/core/src/lib/parse.keypress.test.ts(+51 -1)📝
packages/core/src/lib/parse.keypress.ts(+22 -6)📝
packages/core/src/lib/parse.mouse.test.ts(+7 -0)📝
packages/core/src/lib/parse.mouse.ts(+7 -8)➖
packages/core/src/lib/stdin-buffer.test.ts(+0 -926)➖
packages/core/src/lib/stdin-buffer.ts(+0 -423)➕
packages/core/src/lib/stdin-parser.test.ts(+1660 -0)➕
packages/core/src/lib/stdin-parser.ts(+1233 -0)📝
packages/core/src/lib/terminal-palette.test.ts(+33 -0)📝
packages/core/src/lib/terminal-palette.ts(+128 -103)📝
packages/core/src/renderables/TabSelect.test.ts(+11 -2)📝
packages/core/src/renderables/__tests__/Textarea.stress.test.ts(+24 -0)📝
packages/core/src/renderer.ts(+128 -64)...and 4 more files
📄 Description
Fixes #748 + related #705, #682, #727, #686, OpenCode 15760
We currently have a chunk-level either/or stdin split in
CliRenderer:That design is unsafe for mixed chunks and can silently drop input (e.g. mouse + key in same read).
Examples:
\x1b[<64;10;5Mx-> trailingxcan be droppedx\x1b[<64;10;5M-> mouse can be swallowed by non-mouse pathI want to have one canonical stdin pipeline, but i tried to add this a merge-safe way, which is why this PR is a bit larger and more of a refactor than just a straight parser swap.
mainuses a split stdin pipeline:KeyHandlerreparses strings the parser stack already understandsThis makes input harder to reason about and can lose details for mixed protocol chunks, X10 mouse payload bytes, delayed escape continuations, and legacy high-byte/meta cases. For instance, issue 661, i now realize is most likely a case of utf8 decoding happening on X10 mouse bytes
The boundary is:
parseKeypress()andMouseParserinternally and creates fully typedStdinEventobjects (key, mouse, paste, response).ParsedKeyintoKeyEvent. It is not a parser.event.typeand forwarding to the right handler.This removes:
StdinBufferstring tokenizer and its even emittersetEncoding("utf8")on stdin (decoded strings before framing, wrong order for a binary protocol)MouseParserinstance in renderer that consumed mouse bytes before they ever reached the bufferparseKeypress()call insideKeyHandler.processInput()Also:
stdinReadStream directly AFAIK, which is why the setEncoding issues have gone unnoticed, i think. I haven't addressed this yet. - Added many tests to the parser :)In one sentence: main decodes first, parses later. In the PR we parse bytes first, decode only when semantics are known.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.