-
Notifications
You must be signed in to change notification settings - Fork 3
feat!: refactor the input processor #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughReplaces legacy ParseKeys with a new Parser class and CSI/UTF‑8 state machine, adds focus events and Screen.enableFocus, removes many legacy control-key constants and Termcap key fields across terminfo, and updates demos and TTY input loop to use the new parser and focus model. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant TTY as TTY (fd/read)
participant Parser as Parser
participant EQ as EventQueue
participant App as Application
Note over TTY,Parser: terminal byte stream (ESC / CSI / OSC / UTF‑8 / mouse / focus)
TTY->>Parser: feed bytes (Parser.parse/scan)
Parser->>Parser: decode UTF‑8, handle CSI/OSC/DCS, mouse, focus
Parser-->>EQ: post Event (Key / Mouse / Paste / Focus)
EQ-->>App: deliver Event(s)
App->>TTY: call enableFocus(true/false) when starting/stopping
TTY-->>App: (optional) terminal acknowledges / focus notifications
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
mkinfo/source/mkinfo.d (1)
355-355: Critical bug: comparison instead of bit shift.Line 355 uses
1 < 24(comparison, alwaystrue→1) instead of1 << 24(bit shift for 16M colors). This would settc.colorsto1instead of16777216for xterm-direct terminals.- tc.colors = 1 < 24; + tc.colors = 1 << 24;source/dcell/parser.d (1)
1284-1363: Unittest failure at lone‑ESC assertion is consistent with the ESC timeout bugThe failing assertion:
assert(p.parse(['\x1b']) == false); ... Thread.sleep(msecs(100)); assert(p.parse([]) == true);expects ESC to be held as a partial sequence until the timeout, then emitted later. With the current
msecs(0)check inscan(),parse(['\x1b'])can already returntrueand push aKey.escevent, tripping this test at line 1326.Once you change the timeout comparison to use
seqTime(as suggested in thescan()comment), this test—and the preceding Alt+O test that relies on the same mechanism—should pass again.
🧹 Nitpick comments (6)
demos/colors/source/colors.d (2)
143-159: Make Ctrl+L detection resilient to additional modifiersThe resize shortcut now relies on:
case Key.rune: if (ev.key.ch == 'l' && ev.key.mod == Modifiers.ctrl)If
Modifiersis a bitmask, this will fail when other bits are set (e.g., Ctrl+Meta+L), even though Ctrl is pressed. A more robust check is:- case Key.rune: - if (ev.key.ch == 'l' && ev.key.mod == Modifiers.ctrl) + case Key.rune: + if (ev.key.ch == 'l' && (ev.key.mod & Modifiers.ctrl) != 0)This keeps the behavior for plain Ctrl+L while allowing combined modifiers.
Please confirm this matches the new key/modifier semantics from the input refactor.
166-167: Minor nit: fix typo in error assertion messageThe assertion currently says
"errror received"(threers). Consider correcting it to"error received":- case EventType.error: - assert(0, "errror received"); + case EventType.error: + assert(0, "error received");source/dcell/key.d (1)
245-259: Verify modifier ordering in toString() is intentional.The modifier prefix order is now Shift → Meta → Alt → Hyper → Ctrl. This differs from some common conventions (e.g., Ctrl-Shift-Alt). If this ordering is intentional for consistency with tcell or other conventions, consider adding a brief comment.
source/dcell/ttyscreen.d (1)
591-639:pollflag is now unused; consider removing to avoid confusion
pollis set based onp.empty()/finishedbut never read, so it’s effectively dead state now that all reads go throughf.read()withblocking(true/false). Dropping it (and its assignments) would make the loop intent clearer without changing behavior.source/dcell/parser.d (2)
749-766: Guard CSI‑u modifier decoding to avoid bogus flags when only one parameter is presentIn the CSI‑u handler:
case 'u': // CSI-u kitty keyboard protocol if (plen > 0) { Modifiers mod = Modifiers.none; Key key = Key.rune; dchar chr = 0; ... evs ~= newKeyEvent(key, chr, calcModifier(p1)); } return;When
plen == 1,p1remains its default0, andcalcModifier(0)(which doesn--) produces nonsensical modifiers. For CSI‑u, the modifier parameter is optional and defaults to “no modifiers”.A safer implementation:
- Modifiers mod = Modifiers.none; + Modifiers mod = Modifiers.none; Key key = Key.rune; dchar chr = 0; if (p0 in csiUKeys) { auto k = csiUKeys[p0]; key = k.key; } else { chr = cast(dchar) p0; } - evs ~= newKeyEvent(key, chr, calcModifier(p1)); + if (plen > 1 && p1 > 0) + { + mod = calcModifier(p1); + } + evs ~= newKeyEvent(key, chr, mod);This keeps modifiers correct once CSI‑u is enabled without affecting current behavior.
Please double‑check CSI‑u’s exact parameter semantics against the kitty keyboard protocol spec to confirm this mapping.
666-679:handleOscresets toParseState.init; consider usingParseState.inifor clarity
handleOscends with:// string is located in scratch. parseState = ParseState.init;Using
.inithere works because it’s the enum’s default (which isini), but it’s atypical compared to the rest of the file whereParseState.iniis used explicitly. For readability and to avoid confusion with the “ini” state name, consider:- parseState = ParseState.init; + parseState = ParseState.ini;Behavior is unchanged; this is just a clarity cleanup.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
demos/colors/source/colors.d(2 hunks)demos/mouse/source/mouse.d(2 hunks)mkinfo/source/mkinfo.d(3 hunks)source/dcell/database.d(0 hunks)source/dcell/event.d(4 hunks)source/dcell/key.d(7 hunks)source/dcell/parser.d(5 hunks)source/dcell/screen.d(3 hunks)source/dcell/termcap.d(0 hunks)source/dcell/terminfo/aixterm.d(0 hunks)source/dcell/terminfo/alacritty.d(0 hunks)source/dcell/terminfo/ansi.d(0 hunks)source/dcell/terminfo/dtterm.d(0 hunks)source/dcell/terminfo/gnome.d(0 hunks)source/dcell/terminfo/konsole.d(0 hunks)source/dcell/terminfo/linux.d(0 hunks)source/dcell/terminfo/rxvt.d(0 hunks)source/dcell/terminfo/screen.d(0 hunks)source/dcell/terminfo/vt100.d(0 hunks)source/dcell/terminfo/vt102.d(0 hunks)source/dcell/terminfo/vt220.d(0 hunks)source/dcell/terminfo/vt320.d(0 hunks)source/dcell/terminfo/vt420.d(0 hunks)source/dcell/terminfo/xfce.d(0 hunks)source/dcell/terminfo/xterm.d(0 hunks)source/dcell/ttyscreen.d(7 hunks)
💤 Files with no reviewable changes (18)
- source/dcell/terminfo/dtterm.d
- source/dcell/terminfo/screen.d
- source/dcell/terminfo/vt320.d
- source/dcell/terminfo/vt420.d
- source/dcell/terminfo/alacritty.d
- source/dcell/database.d
- source/dcell/terminfo/xfce.d
- source/dcell/terminfo/vt100.d
- source/dcell/terminfo/aixterm.d
- source/dcell/terminfo/vt102.d
- source/dcell/terminfo/linux.d
- source/dcell/terminfo/ansi.d
- source/dcell/terminfo/gnome.d
- source/dcell/terminfo/xterm.d
- source/dcell/terminfo/vt220.d
- source/dcell/terminfo/konsole.d
- source/dcell/terminfo/rxvt.d
- source/dcell/termcap.d
🧰 Additional context used
🪛 GitHub Actions: dmd
source/dcell/parser.d
[error] 1326-1326: dub -q test failed: unittest failure at source/dcell/parser.d:1326. Exit code 2.
🔇 Additional comments (22)
source/dcell/key.d (4)
24-26: LGTM!Good documentation explaining why low key values are reserved for control encodings and how they're now translated.
117-121: LGTM!The explicit ASCII mappings for basic keys (backspace, tab, esc, enter) are clear and align with standard terminal conventions.
219-231: LGTM!The
hypermodifier follows the existing bit flag pattern consistently.
268-279: LGTM!The rune handling logic is clear: show raw character when no modifiers, "Space" for space with modifiers, and uppercase for other modified characters.
mkinfo/source/mkinfo.d (3)
1-1: LGTM!Copyright year update is appropriate.
304-304: LGTM!Minor spacing adjustment around cast.
435-435: LGTM!Adding the
numvariable to track the index in the foreach is appropriate for the term source generation.source/dcell/screen.d (2)
60-70: LGTM!The
opDollarmethod body is reformatted for better readability while maintaining identical logic.
123-131: LGTM!The
enableFocusmethod is a clean addition to the interface with appropriate documentation. This aligns with the new focus event support in the event system.source/dcell/event.d (3)
27-27: LGTM!The
focusevent type is appropriately added to the enum.
46-46: LGTM!The
focusfield in the union follows the existing pattern for other event types.
66-71: LGTM!The
FocusEventstruct is minimal and appropriate. The singlefocusedboolean clearly indicates focus gained (true) vs lost (false).demos/mouse/source/mouse.d (7)
22-28: LGTM!Indentation standardized to 4 spaces.
103-103: LGTM!Focus format string added for status display.
108-122: LGTM!Good additions:
enableFocus(true)is called during initialization, and thefocusedstate is properly initialized totrue(assuming the window starts focused).
138-138: LGTM!Focus state is now displayed in the status area.
188-191: LGTM!Ctrl+L to trigger
sync()is a standard terminal convention for screen refresh.
209-210: LGTM!Hyper modifier handling added, consistent with the new
Modifiers.hyperin key.d.
285-287: LGTM!Focus event handling is clean and correctly updates the
focusedstate.source/dcell/ttyscreen.d (1)
228-232: Focus-mode enable/disable sequence looks correctUsing
CSI ?1004 h/lhere matches xterm’s focus-in/out protocol and pairing it with an unconditionalflush()is appropriate. The only behavioral change is thatstop()now always sends\x1b[?1004lviaenableFocus(false), which is a safe cleanup even if focus reporting was never enabled.source/dcell/parser.d (2)
35-194: Key mapping tables mirror common terminal encodingsThe
CsiKeystruct pluscsiAllKeys,ss3Keys,linuxFKeys,csiUKeys, andwinKeystables look consistent with typical xterm/aixterm/linux/kitty/Win32 encodings and cover a wide range of function and navigation keys without obvious overlaps. This should give the new parser a solid base behaviorally.
1087-1096: New focus event helper matches the event layout
newFocusEventfillstype,when, and thefocus.focusedfield, which is exactly what the focus CSI (‘I’/‘O’) handler expects. This keeps focus reporting nicely encapsulated in the parser.
05c8925 to
39c5d7e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
source/dcell/parser.d (1)
1087-1123: UseMonoTime.currTime()(with parentheses) in bothnewMouseEventoverloadsBoth overloads are missing parentheses on the
MonoTime.currTimefunction call at lines 1116 and 1131:type: EventType.mouse, when: MonoTime.currTime, mouse: { ... }This assigns the function symbol instead of calling it to get a
MonoTimevalue, which will cause a compilation error. All other event constructors (newFocusEvent,newKeyEvent,newPasteEvent) correctly useMonoTime.currTime()with parentheses. Fix both instances by adding().
♻️ Duplicate comments (1)
source/dcell/parser.d (1)
949-1049: Fix win32 handler: lone modifiers, Key.rune check typo, and event emissionTwo issues in
handleWinKeywill either prevent compilation or yield incorrect behavior:
- Lone‑modifier filtering checks
keyinstead of the virtual key codeelse if (key == 0x11 || key == 0x13 || key == 0x14) { // lone modifiers return; }
0x11,0x13, and0x14are virtual key codes (Ctrl, Alt, etc.). This should be checkingp0, not thekeyenum, otherwise lone modifier presses will not be filtered.
- Repeat‑event guard compares against
key.runefor (; rpt > 0; rpt--) { if (key != key.rune || chr != 0) { evs ~= newKeyEvent(key, chr, mod); } }
key.runeis a typo; it should be the enum memberKey.rune. As written, this won’t compile.Suggested fix:
- else if (key == 0x11 || key == 0x13 || key == 0x14) + else if (p0 == 0x11 || p0 == 0x13 || p0 == 0x14) { // lone modifiers return; } @@ - for (; rpt > 0; rpt--) - { - if (key != key.rune || chr != 0) - { - evs ~= newKeyEvent(key, chr, mod); - } - } + for (; rpt > 0; rpt--) + { + // Suppress pure-repeat events where we have no real key/char payload. + if (key != Key.rune || chr != 0) + { + evs ~= newKeyEvent(key, chr, mod); + } + }This aligns the logic with the intended semantics (ignore lone modifiers and empty repeats) and fixes the compilation error.
🧹 Nitpick comments (3)
source/dcell/key.d (1)
24-27: Clarify low‑key comment now that ASCII aliases are definedThe comment says the low key range is “empty”, but
backspace,tab,enter, andescare now explicitly assigned low values. Functionally this is fine (and matches how the parser uses ASCII control codes), but the comment is now misleading.Consider updating the comment to mention that a few well‑known control keys are explicitly aliased in this range while other control bytes are represented as
Key.runewith a control modifier.Also applies to: 116-121
source/dcell/parser.d (2)
35-262: Static CSI/SS3/Linux/win32 key maps look reasonable; consider modularization if they grow furtherThe
KeyCode/CsiKeydefinitions and thecsiAllKeys,ss3Keys,linuxFKeys,csiUKeys, andwinKeystables are straightforward and align with typical terminal encodings. I don’t see functional issues here.If this table set grows much more, consider moving them into a dedicated “key tables” module to keep the parser implementation itself easier to scan, but that’s purely organizational.
333-372: Unused parser fields/flags and legacy paste path
keyCodes,partial, and theparsePaste/pasteStart/pasteEndpath appear to be unused now:
const KeyCode[string] keyCodes;is never read.bool partialis only written inparseSequenceand never read.parsePaste()is private and not called anywhere inParser; bracketed paste is now handled entirely via CSI 200/201 inhandleCsi+postKey.If terminfo‑based paste handling is no longer planned, these can be removed to reduce mental overhead; otherwise it may be worth either wiring them back into the scan path or adding a brief comment indicating they’re reserved for future use.
Also applies to: 1183-1236
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
demos/colors/source/colors.d(2 hunks)demos/mouse/source/mouse.d(2 hunks)mkinfo/source/mkinfo.d(4 hunks)source/dcell/database.d(0 hunks)source/dcell/event.d(4 hunks)source/dcell/key.d(7 hunks)source/dcell/parser.d(5 hunks)source/dcell/screen.d(3 hunks)source/dcell/termcap.d(0 hunks)source/dcell/terminfo/aixterm.d(0 hunks)source/dcell/terminfo/alacritty.d(0 hunks)source/dcell/terminfo/ansi.d(0 hunks)source/dcell/terminfo/dtterm.d(0 hunks)source/dcell/terminfo/gnome.d(0 hunks)source/dcell/terminfo/konsole.d(0 hunks)source/dcell/terminfo/linux.d(0 hunks)source/dcell/terminfo/rxvt.d(0 hunks)source/dcell/terminfo/screen.d(0 hunks)source/dcell/terminfo/vt100.d(0 hunks)source/dcell/terminfo/vt102.d(0 hunks)source/dcell/terminfo/vt220.d(0 hunks)source/dcell/terminfo/vt320.d(0 hunks)source/dcell/terminfo/vt420.d(0 hunks)source/dcell/terminfo/xfce.d(0 hunks)source/dcell/terminfo/xterm.d(0 hunks)source/dcell/ttyscreen.d(7 hunks)
💤 Files with no reviewable changes (18)
- source/dcell/terminfo/vt102.d
- source/dcell/database.d
- source/dcell/terminfo/screen.d
- source/dcell/terminfo/vt420.d
- source/dcell/terminfo/gnome.d
- source/dcell/terminfo/xfce.d
- source/dcell/terminfo/alacritty.d
- source/dcell/terminfo/ansi.d
- source/dcell/terminfo/konsole.d
- source/dcell/terminfo/vt100.d
- source/dcell/terminfo/aixterm.d
- source/dcell/terminfo/vt220.d
- source/dcell/terminfo/vt320.d
- source/dcell/terminfo/xterm.d
- source/dcell/terminfo/rxvt.d
- source/dcell/terminfo/linux.d
- source/dcell/terminfo/dtterm.d
- source/dcell/termcap.d
🚧 Files skipped from review as they are similar to previous changes (1)
- source/dcell/screen.d
🔇 Additional comments (21)
demos/colors/source/colors.d (3)
149-156: LGTM: Ctrl+L handling updated to use rune-based detection.The change from
Key.ctrlLto checkingKey.runewithev.key.ch == 'l'andev.key.mod == Modifiers.ctrlaligns with the PR's goal of removing per-terminal special key parsing. Control keys are now conveyed as modified runes.
103-104: RGB packing is now correct.The red component is properly shifted by 16 bits (
int(r) << 16 | int(g) << 8 | int(b)), producing the expected 0xRRGGBB format forfromHex.
167-168: Typo fix acknowledged.The error message correction from "errror received" to "error received" is a good cleanup.
source/dcell/event.d (2)
27-27: Clean addition of focus event type to the enum.The new
focusmember follows the existing naming convention and placement inEventType.
66-71: Well-structured FocusEvent definition.The
FocusEventstruct with a singlefocusedboolean is appropriately minimal and follows the pattern of other event structs in this file.demos/mouse/source/mouse.d (4)
112-112: Focus reporting enabled correctly.The call to
s.enableFocus(true)at startup enables focus event reporting, aligning with the new feature introduced in this PR.
128-140: UI properly expanded to display focus state.The box height increased from 7 to 8 (Coord(42, 8)) and the focus state is displayed using the
focusFmtformat string. The layout accommodates the new field correctly.
286-288: Focus event handling integrated correctly.The
EventType.focuscase properly updates thefocusedstate from the event payload.
188-192: Ctrl+L handling updated consistently with colors demo.The rune-based detection for Ctrl+L redraw follows the same pattern as in colors.d, using
ev.key.ch == 'l' && ev.key.mod == Modifiers.ctrl.source/dcell/ttyscreen.d (4)
228-232: Focus reporting implementation uses standard escape sequences.The implementation correctly uses
\x1b[?1004hto enable and\x1b[?1004lto disable focus reporting, which is the de-facto standard (DECSET/DECRST mode 1004) used by xterm and compatible terminals.
94-94: Focus properly disabled during stop sequence.Calling
enableFocus(false)before cleanup ensures focus reporting is disabled when the screen stops, which is important for proper terminal state restoration.
591-595: Parser initialization simplified.The removal of the
ParseKeysparameter and use ofnew Parser()aligns with the PR's objective to eliminate per-terminal special key parsing. The new Parser handles input processing without terminal-specific key tables.
609-627: Improved parse completion handling.Capturing the
finishedreturn value fromp.parse(s)and using it in the blocking decision (!p.empty() || !finished) ensures the input loop continues processing when the parser is in the middle of a multi-byte sequence, preventing incomplete escape sequence handling.mkinfo/source/mkinfo.d (3)
345-358: Critical bug fix: RGB color count now correctly uses bitshift.The change from
1 < 24(comparison, yieldingtrue/1) to1 << 24(bitshift, yielding 16,777,216) fixes a significant bug in the RGB color path. TheTcflag path at line 348 was already correct; this brings the-RGBflag path in line.
304-304: Minor formatting adjustment.The cast spacing change is stylistic only.
435-435: Minor formatting adjustment in foreach.The variable declaration formatting change is stylistic only.
source/dcell/key.d (1)
219-231: Modifier flags andKeyEvent.toStringwiring look consistentThe added
hyperbit and the updatedtoStringlogic (Ctrl/Shift/Meta/Alt/Hyper prefixes plus rune naming rules) are coherent with the new modifier model and the parser’scalcModifierbehavior. The UTF‑8 rune handling and control‑rune mapping also look correct.No changes needed here.
Also applies to: 242-291
source/dcell/parser.d (4)
681-858: CSI handling for focus, mouse, kitty CSI‑u, win32, and modified keys looks coherentThe
handleCsiimplementation correctly:
- Rejects intermediates for now.
- Routes
<...m/MtohandleMouse.- Emits focus in/out events for
CSI I/CSI O.- Supports linux
CSI [ ...F‑key mode.- Decodes kitty CSI‑u, win32
_sequences, XTerm bracketed paste 200/201, and xtermmodifyOtherKeys.Parameter parsing with
split/to!intand the use ofcsiAllKeys,ss3Keys, andcsiUKeyslooks consistent with the key tables, and the fallback logic indefaultavoids swallowing unknown sequences silently.No functional issues spotted here.
860-947: Mouse handler matches XTerm protocol and debouncing behavior
handleMousecorrectly:
- Normalizes coordinates to 0‑based.
- Handles motion vs scroll vs release semantics, using
buttonDownto debounce bogus motion events.- Decodes buttons and wheel directions from
btn & 0x43.- Extracts Shift/Alt/Ctrl modifiers from the corresponding bits.
- Emits a single
newMouseEventwith position, button, and modifiers.The logic matches XTerm/SGR expectations; nothing to change here.
1051-1085: Hyper bit integration incalcModifieris consistent withModifiersenum
calcModifiermaps the CSI modifier parameter bits onto:
shift,alt,ctrlmeta(for both kitty “Super” and “super2” bits)hyper(bit 16)This lines up with the
Modifiersenum (including the newhyperflag) and the prefixes emitted byKeyEvent.toString.No changes needed.
1284-1363: Unittest exercises key parsing, ESC timeout, paste, mouse, and Unicode correctlyThe updated unittest:
- Instantiates
Parseras a class (new Parser()), then checks basic CSI right‑arrow decoding.- Verifies ESC+SS3 timeout behavior (
Thread.sleep(msecs(200))vsseqTime == 50ms).- Confirms lone ESC handling, bracketed paste CSI 200/201, mouse event decoding, and UTF‑8 rune parsing.
Given the fixes above, this provides solid coverage of the new parser behavior. No additional test changes needed.
This is a complete redesign of the input scanner, using logic derived from tcell. It eliminates the per-terminal special parsing for keys, so that we can process keys from almost anything. This adds parsing support (not enabled yet) for CSI-u (kitty protocol), Xterm modifierOtherKeys, and win32-input-mode protocols. (These will be enabled in follow up.) As a bonus, this adds suppot for focus reporting, so that we get to now when the application receives or loses focus. The mouse demo is updated to reflect that. One consequence of this is that the key definitions for all the various control keys are gone, as these are now conveyed as a modified Key rune. The key definitions (and also PadChar) are removed from the terminfo definitions. This is a breaking change, but we are still pre-1.0 so we didn't have any promises anyway.
39c5d7e to
712e16a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
source/dcell/parser.d (1)
1044-1044: Verify typo fix at line 1044.The past review comment indicates that line 1044 had a typo (
key != key.runeshould beKey.rune), and it was supposedly addressed in commits 848742a to 05c8925. However, the code still shows:if (key != key.rune || chr != 0)This should be:
if (key != Key.rune || chr != 0)Please verify that the fix was properly applied or if this represents a regression.
🧹 Nitpick comments (1)
demos/colors/source/colors.d (1)
13-18: Nestedstd.randomimport is redundant with module‑level importSince
std.randomis already imported at the module level, the innerimport std.random;insideColorBoxesis unnecessary. You can drop the nested import to keep imports a bit leaner, though it’s purely cosmetic.Also applies to: 22-22
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (26)
demos/colors/source/colors.d(2 hunks)demos/mouse/source/mouse.d(2 hunks)mkinfo/source/mkinfo.d(4 hunks)source/dcell/database.d(0 hunks)source/dcell/event.d(4 hunks)source/dcell/key.d(7 hunks)source/dcell/parser.d(5 hunks)source/dcell/screen.d(3 hunks)source/dcell/termcap.d(0 hunks)source/dcell/terminfo/aixterm.d(0 hunks)source/dcell/terminfo/alacritty.d(0 hunks)source/dcell/terminfo/ansi.d(0 hunks)source/dcell/terminfo/dtterm.d(0 hunks)source/dcell/terminfo/gnome.d(0 hunks)source/dcell/terminfo/konsole.d(0 hunks)source/dcell/terminfo/linux.d(0 hunks)source/dcell/terminfo/rxvt.d(0 hunks)source/dcell/terminfo/screen.d(0 hunks)source/dcell/terminfo/vt100.d(0 hunks)source/dcell/terminfo/vt102.d(0 hunks)source/dcell/terminfo/vt220.d(0 hunks)source/dcell/terminfo/vt320.d(0 hunks)source/dcell/terminfo/vt420.d(0 hunks)source/dcell/terminfo/xfce.d(0 hunks)source/dcell/terminfo/xterm.d(0 hunks)source/dcell/ttyscreen.d(7 hunks)
💤 Files with no reviewable changes (18)
- source/dcell/terminfo/vt102.d
- source/dcell/terminfo/konsole.d
- source/dcell/terminfo/xfce.d
- source/dcell/terminfo/vt320.d
- source/dcell/terminfo/aixterm.d
- source/dcell/terminfo/ansi.d
- source/dcell/terminfo/vt100.d
- source/dcell/terminfo/alacritty.d
- source/dcell/terminfo/vt420.d
- source/dcell/terminfo/linux.d
- source/dcell/database.d
- source/dcell/terminfo/screen.d
- source/dcell/terminfo/xterm.d
- source/dcell/terminfo/gnome.d
- source/dcell/terminfo/dtterm.d
- source/dcell/terminfo/rxvt.d
- source/dcell/terminfo/vt220.d
- source/dcell/termcap.d
🔇 Additional comments (23)
demos/colors/source/colors.d (3)
22-48: RNG state, color components, and initialization look solidFields,
flip(), and the constructor correctly seed and use the RNG, initialize RGB channels and step sizes, and bias green changes as intended; no functional issues spotted here.
50-105: Color stepping and RGB packing intofromHexare now correctThe incremental RGB stepping with bounds checks keeps components in range and sensibly flips direction, and the background color now packs as
int(r) << 16 | int(g) << 8 | int(b), matching a standard 0xRRGGBB layout and addressing the prior off‑by‑one shift.
135-175: Updated Ctrl+L handling via rune+modifier matches the new key modelSwitching from
Key.ctrlLto checking forKey.runewithev.key.ch == 'l' && ev.key.mod == Modifiers.ctrlaligns this demo with the new parser’s rune+modifier representation while still enforcing “Ctrl‑L with no other modifiers” as the resize trigger; the rest of the event loop logic remains consistent.source/dcell/event.d (1)
4-71: LGTM! Focus event integration is well-structured.The new
FocusEventstruct and its integration into theEventunion follow the established pattern for other event types. The focused boolean field clearly tracks focus state.source/dcell/key.d (3)
24-122: LGTM! Control key handling refactored cleanly.The explicit ASCII values for common keys (backspace, tab, esc, enter, del) are clear and standard. The approach of translating control encodings to runes with the ctrl modifier (as noted in the comments) simplifies the key model.
219-231: LGTM! Hyper modifier added consistently.The hyper modifier follows the established bitmask pattern (1 << 4) and fits naturally into the modifier scheme.
242-291: LGTM! toString() improvements enhance key event display.The updated logic handles modifiers systematically (Ctrl-, Shift-, Hyper- prefixes), and the rune-handling refinements are sensible:
- Raw character when no modifiers present
- "Space" label for space with modifiers
- Uppercase for other characters with modifiers
source/dcell/parser.d (6)
29-309: LGTM! Comprehensive key mapping tables.The key mapping tables are well-organized and cover a wide range of terminal types and protocols:
- CSI sequences with composite keys (mode + parameter)
- SS3 application mode keys
- Linux console F-keys
- Kitty CSI-u protocol
- Windows virtual key codes
The use of immutable tables is appropriate for this static data.
311-388: LGTM! Parser class structure is well-designed.The public API is minimal and clear (
events(),parse(),empty()), and the internalParseStateenum comprehensively covers all parsing states. ThepostKey()helper correctly distinguishes between pasting mode (accumulating in buffer) and normal mode (emitting events).
390-664: LGTM! State machine implementation is thorough and correct.The parsing state machine properly handles:
- UTF-8 multi-byte sequences with accumulation and decoding
- Control key translation to runes with ctrl modifier
- Escape sequence state transitions
- ESC timeout using
seqTime(the past issue withmsecs(0)has been correctly fixed)The logic is sound and comprehensive.
681-858: LGTM! CSI handler covers modern terminal protocols.The
handleCsi()method comprehensively handles:
- Focus in/out events (lines 740-745)
- Kitty CSI-u keyboard protocol
- Win32-input-mode
- XTerm modifyOtherKeys
- Bracketed paste mode (CSI 200/201)
- Standard CSI sequences with parameter-based lookups
The implementation correctly uses
calcModifier()for modifier parsing and properly generates focus and paste events.
1051-1181: LGTM! Event generation helpers are well-implemented.The helper methods (
calcModifier(),newFocusEvent(),newKeyEvent(),newMouseEvent(),newPasteEvent()) correctly:
- Map CSI modifier parameters to the Modifiers enum (including hyper)
- Handle Alt-escaped keys via the
escapedflag- Create properly-structured Event instances with timestamps
1284-1363: LGTM! Comprehensive unittest coverage.The unittest validates:
- SS3 sequence parsing (right arrow)
- ESC timeout handling for Alt-escaped keys and lone ESC
- Bracketed paste mode
- SGR mouse events
- UTF-8 decoding (Euro symbol)
The test properly uses
Thread.sleep()to validate timeout behavior.source/dcell/screen.d (1)
4-130: LGTM! Focus support added to Screen interface.The new
enableFocus(bool)method is well-documented and provides the expected interface for enabling focus reporting. The formatting adjustment toopDollaris cosmetic and doesn't affect behavior.demos/mouse/source/mouse.d (2)
92-141: LGTM! Focus tracking integrated into demo.The demo properly:
- Enables focus reporting via
s.enableFocus(true)- Tracks focus state with the
focusedboolean- Displays focus status in the UI
The initial assumption of
focused = trueis reasonable for a newly started application.
170-292: LGTM! Event handling enhanced with focus and precise modifier checking.The event handling improvements:
- Ctrl-L now correctly validates
mod == Modifiers.ctrl(line 189), preventing unintended trigger from other modifier combinations- Hyper modifier display added for completeness (line 210-211)
- Focus event properly updates the
focusedstate (lines 286-288)source/dcell/ttyscreen.d (3)
56-102: LGTM! Parser refactoring simplifies screen initialization.The removal of the
ParseKeysparameter fromspawn()simplifies the initialization, and the addition ofenableFocus(false)instop()ensures proper cleanup of focus reporting.
228-232: LGTM! Focus reporting implementation is standard-compliant.The
enableFocus()method correctly uses the XTerm focus reporting sequences (\x1b[?1004hto enable,\x1b[?1004lto disable) and flushes immediately for proper effect.
591-643: LGTM! Input loop updated for new Parser API.The
inputLoop()refactoring:
- Removes
ParseKeysdependency, using the newParserclass- Captures
parse()return value infinishedto track parsing state- Correctly uses
!p.empty() || !finishedto determine when to use non-blocking I/O (line 627)The blocking/non-blocking logic properly optimizes I/O by only blocking when the parser buffer is empty and parsing is complete.
mkinfo/source/mkinfo.d (4)
1-1: Copyright header year update is appropriateHeader reflects 2025 while keeping license text intact; no issues here.
300-307: Alias cast remains a safe zero‑copy handoff
tc.aliases = cast(immutable(string)[]) caps.aliases;continues to avoid reallocating alias strings while enforcing the desired immutability on theTermcapside. Given thatcaps.aliasesultimately points into GC‑managedinfocmpoutput, the lifetime is sufficient for this use.
345-356:tc.colors = 1 << 24correctly signals 24‑bit truecolorUsing
1 << 24for bothTcandRGBflags is a clear and conventional sentinel for 24‑bit color support, and it cooperates correctly with the latertc.colors < 8guard and the explicitsetFg/setBgoverrides.
435-462: mkTermSource iteration stays resilient to Termcap layout changesThe spacing tweak in
foreach (num, Termcap* tc; tcs)is cosmetic, and the combination ofFieldNameTuple!Termcapwith the type‑basedstatic ifblocks keeps the generator aligned with the currentTermcapfields (including the recent removals) without manual field maintenance.
This is a complete redesign of the input scanner, using logic derived from tcell. It eliminates the per-terminal special parsing for keys, so that we can process keys from almost anything.
This adds parsing support (not enabled yet) for CSI-u (kitty protocol), Xterm modifierOtherKeys, and win32-input-mode protocols. (These will be enabled in follow up.)
As a bonus, this adds suppot for focus reporting, so that we get to now when the application receives or loses focus. The mouse demo is updated to reflect that.
One consequence of this is that the key definitions for all the various control keys are gone, as these are now conveyed as a modified Key rune.
The key definitions (and also PadChar) are removed from the terminfo definitions.
This is a breaking change, but we are still pre-1.0 so we didn't have any promises anyway.
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.