-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add convenience methods for writing to screen (fixes #3 fixes #4) #51
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
WalkthroughAdds Screen style/position properties and write overloads; extends CellBuffer with style, position, put/write methods and safety annotations; updates TtyScreen to use the new API; updates hello demo to center text via Screen.position and Screen.write. Changes
Sequence Diagram(s)mermaid Demo->>Screen: set position, set style Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 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: 1
🧹 Nitpick comments (1)
demos/hello/source/hello.d (1)
34-37: Remove redundant position and style assignments.Lines 34-35 set
positionandstyle, butcenterStrimmediately overwrites both. These assignments have no effect.Apply this diff:
- s.position = Coord(size.x / 2 - 9, size.y / 2 - 1); - s.style = style; centerStr(s, size.y / 2 - 1, style, " Hello There! "); centerStr(s, size.y / 2 + 1, def, " Press ESC to exit. ");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
demos/hello/source/hello.d(2 hunks)source/dcell/cell.d(20 hunks)source/dcell/screen.d(2 hunks)source/dcell/ttyscreen.d(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-08T19:10:45.993Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:763-766
Timestamp: 2025-12-08T19:10:45.993Z
Learning: In source/dcell/ttyscreen.d, the newTtyScreen() factory function intentionally does not accept a term parameter because the TtyScreen constructor handles environment variable resolution internally with an optional term parameter. Users needing to override the terminal type should call the constructor directly: new TtyScreen(newDevTty(), "custom-term").
Applied to files:
source/dcell/ttyscreen.d
🔇 Additional comments (11)
source/dcell/cell.d (7)
16-16: LGTM!The
std.uniimport is necessary for the grapheme-aware text handling introduced in thewritemethod.
51-51: LGTM!Adding
nothrowto these simple accessor methods is correct and strengthens the safety guarantees.Also applies to: 76-76
162-176: LGTM!The safety annotations on these helper methods are appropriate—they perform simple calculations without unsafe operations, allocations, or exceptions.
444-450: LGTM!The addition of stateful
styleandpositionfields enables the simplified write API mentioned in the PR objectives. The fields will be default-initialized appropriately.
495-498: LGTM!The character overload correctly delegates to the grapheme version, enabling formatted writer support for simple use cases.
502-508: LGTM!The grapheme-aware iteration ensures proper handling of complex Unicode, including combining characters and emoji sequences.
623-660: LGTM!Comprehensive unit tests covering the new functionality including wrapping behavior, double-width character handling, and style application.
source/dcell/screen.d (2)
14-15: LGTM!These imports support the new write method implementations and string type constraints.
228-245: LGTM!The interface additions cleanly extend the Screen API with stateful style/position and simplified write methods, aligning with the PR objectives.
demos/hello/source/hello.d (1)
18-23: LGTM!The refactored
centerStrfunction cleanly demonstrates the new write API, calculating the centered position and usings.writefor output.source/dcell/ttyscreen.d (1)
508-547: LGTM!The implementation correctly delegates to the underlying
CellBuffer, providing a clean implementation of the Screen interface methods.
a39a14b to
d03e6c6
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: 2
♻️ Duplicate comments (1)
source/dcell/cell.d (1)
452-488: Previous issue resolved -size_.xnow used correctly.The field access
size_.xis now properly used on lines 467 and 481 instead of the incorrectsize.xmethod call flagged in the previous review.The
put(Grapheme)method correctly handles:
- Zero-width characters (no position change)
- Single-width characters (advance and wrap)
- Double-width characters (clear following cell, advance by 2, wrap)
🧹 Nitpick comments (1)
source/dcell/screen.d (1)
14-15: Unused imports in interface file.
std.rangeandstd.traitsare imported but don't appear to be used in this interface file. These may have been added in anticipation of future use or copied from the implementation.Consider removing unused imports:
-import std.range; -import std.traits;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
demos/hello/source/hello.d(2 hunks)source/dcell/cell.d(20 hunks)source/dcell/screen.d(2 hunks)source/dcell/ttyscreen.d(5 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:763-766
Timestamp: 2025-12-08T19:10:45.993Z
Learning: In source/dcell/ttyscreen.d, the newTtyScreen() factory function intentionally does not accept a term parameter because the TtyScreen constructor handles environment variable resolution internally with an optional term parameter. Users needing to override the terminal type should call the constructor directly: new TtyScreen(newDevTty(), "custom-term").
📚 Learning: 2025-12-08T19:10:45.993Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:763-766
Timestamp: 2025-12-08T19:10:45.993Z
Learning: In source/dcell/ttyscreen.d, the newTtyScreen() factory function intentionally does not accept a term parameter because the TtyScreen constructor handles environment variable resolution internally with an optional term parameter. Users needing to override the terminal type should call the constructor directly: new TtyScreen(newDevTty(), "custom-term").
Applied to files:
source/dcell/ttyscreen.d
📚 Learning: 2025-12-08T19:17:33.678Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:448-494
Timestamp: 2025-12-08T19:17:33.678Z
Learning: In source/dcell/ttyscreen.d, Color.reset is defined as a value above the range of valid colors. In the sendColors() function, after emitting the reset sequence (vt.resetFgBg), Color.reset values naturally skip all subsequent color-setting logic (isRGB checks and palette range checks < 8, < 256) because they are out of range, which is the correct behavior by design.
Applied to files:
source/dcell/ttyscreen.d
🔇 Additional comments (6)
source/dcell/screen.d (1)
222-240: LGTM - well-designed interface additions.The new
styleandpositionproperties with correspondingwriteoverloads provide a clean stateful API for screen writing. The@safeannotations are consistent and appropriate.demos/hello/source/hello.d (1)
33-34: LGTM - Clean use of new Screen API.The refactored code demonstrates the new stateful
style,position, andwriteAPI effectively.source/dcell/ttyscreen.d (2)
503-542: LGTM - Clean delegation to CellBuffer.The
style,position, andwritemethods properly delegate to the underlyingCellBuffer, maintaining a single source of truth. The@safeannotations are appropriate.
666-668: Correct use of style property for reading.Reading
styleto pass tosendColorsandsendAttrsworks correctly since a copy is sufficient for these read-only operations.source/dcell/cell.d (2)
500-508: LGTM - Clean write implementation.The
writemethod properly iterates through graphemes usingbyGrapheme, ensuring correct handling of combining characters and grapheme clusters. The documentation comment appropriately warns about theput(Char)limitation with formatted writers.
624-660: Comprehensive unit tests for new functionality.The tests cover key scenarios including:
- Basic character output and positioning
- Style application
- Line wrapping behavior
- Double-width character handling (full-width yen sign)
- Placeholder cell for wide characters
d03e6c6 to
65e90c4
Compare
This adds a nice string-aware, grapheme-aware mechansim for writing to the screen. A stateful cursor and a stateful style are used, which then allows write to be used simply. The setStyle method is replaced by just a normal style property. A range API is also provided, but only works for simple cases that do not use grapheme clusters (however most interfaces don't need grapheme clusters, and indeed many terminal emulators don't treat them properly anyway.) While here, a number of methods were marked `@safe`, although this is not comprehensive.
65e90c4 to
18bfa88
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)
demos/hello/source/hello.d (1)
18-23: Clean use of the new Screen API.The
centerStrhelper demonstrates the newstyle,position, andwriteAPI effectively.Note: As flagged in a previous review,
str.lengthgives byte count rather than display width, which works correctly here since the demo strings are ASCII. This is acceptable for a demo.
🧹 Nitpick comments (2)
source/dcell/screen.d (1)
221-238: LGTM! Clean interface additions for stateful writing.The new
styleandpositionproperties along with thewriteoverloads provide a convenient API for screen writing. The@safeannotations are appropriate.Consider adding doc comments for the
writemethods to maintain consistency with other methods in the interface, explaining the behavior (e.g., that position advances as content is written, wrapping behavior).source/dcell/cell.d (1)
452-488: Wide character handling: second cell style not set.In the width == 2 case (lines 474-486), the second cell's text is cleared but its style is not updated. If the second cell previously had a different style, it will retain that old style (though it displays nothing). This is likely benign since the cell displays no content, but for consistency, consider also setting the style:
case 2: position.x++; if (isLegal(position)) { cells[index(position)].text = ""; + cells[index(position)].style = style; }This ensures the "placeholder" cell for wide characters has consistent styling if it's ever inspected or if terminal behavior differs.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
demos/hello/source/hello.d(2 hunks)source/dcell/cell.d(20 hunks)source/dcell/screen.d(1 hunks)source/dcell/ttyscreen.d(4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-08T19:10:45.993Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:763-766
Timestamp: 2025-12-08T19:10:45.993Z
Learning: In source/dcell/ttyscreen.d, the newTtyScreen() factory function intentionally does not accept a term parameter because the TtyScreen constructor handles environment variable resolution internally with an optional term parameter. Users needing to override the terminal type should call the constructor directly: new TtyScreen(newDevTty(), "custom-term").
Applied to files:
source/dcell/ttyscreen.d
📚 Learning: 2025-12-08T19:17:33.678Z
Learnt from: gdamore
Repo: gdamore/dcell PR: 27
File: source/dcell/ttyscreen.d:448-494
Timestamp: 2025-12-08T19:17:33.678Z
Learning: In source/dcell/ttyscreen.d, Color.reset is defined as a value above the range of valid colors. In the sendColors() function, after emitting the reset sequence (vt.resetFgBg), Color.reset values naturally skip all subsequent color-setting logic (isRGB checks and palette range checks < 8, < 256) because they are out of range, which is the correct behavior by design.
Applied to files:
source/dcell/ttyscreen.d
🔇 Additional comments (11)
source/dcell/ttyscreen.d (4)
161-162: LGTM! Style initialization now correctly mutates the stored style.The initialization now correctly sets
cells.style.bgandcells.style.fgdirectly on the CellBuffer's style field, addressing the previous review feedback.
503-542: LGTM! Clean delegation to CellBuffer.The property implementations and write methods correctly delegate to the underlying
CellBuffer, maintaining a single source of truth for style and position state.
554-554: Potentially unused fieldstyle_.The private field
style_at line 554 appears to be superseded bycells.stylefor the public API. However, it's still used internally indrawCell(line 755, 774) andclearScreen(line 668) to track the terminal's current style state (what was last sent to the terminal), which is distinct from the buffer's default style (cells.style).Please verify this is intentional:
style_tracks what the terminal currently displays, whilecells.styleis the default for new writes. If so, consider adding a comment to clarify the distinction.
666-668: Verify:clearScreenuses buffer style, assigns to terminal style.This correctly sends the buffer's current
styleto the terminal and then updatesstyle_to match. The logic is sound for resetting the terminal state during a clear operation.demos/hello/source/hello.d (1)
33-34: LGTM!The usage of
centerStrfor displaying the two messages is clean and demonstrates the intended API.source/dcell/cell.d (6)
16-16: LGTM!The
std.uniimport is needed forGraphemeandbyGraphemeused in the newputandwritemethods.
51-51: LGTM!Adding
nothrowtotext()getter is appropriate since it only returns a field.
76-76: LGTM!Adding
nothrowtowidth()getter is appropriate since it only returns a field.
444-450: Public fields for mutable state.The
styleandpositionfields are public, which is simple but allows external code to modify them inconsistently. This is acceptable for the current design where these are explicitly documented as stateful cursor properties. The simplicity is appropriate for the use case.
500-508: LGTM! Grapheme-aware string writing.The
writemethod correctly iterates by grapheme usingbyGrapheme, ensuring proper handling of grapheme clusters (combining characters, emoji sequences, etc.). This aligns with the PR objective of providing grapheme-aware screen writing.
623-660: Comprehensive unit tests for new functionality.The tests cover:
- Basic
putoperations- Position and style state management
- Wrapping behavior at line boundaries
- Wide character (full-width yen) handling including the placeholder cell
Good coverage of the new API.
This adds a nice string-aware, grapheme-aware mechansim for writing to the screen. A stateful cursor and a stateful style are used, which then allows write to be used simply.
A range API is also provided, but only works for simple cases that do not use grapheme clusters (however most interfaces don't need grapheme clusters, and indeed many terminal emulators don't treat them properly anyway.)
While here, a number of methods were marked
@safe, although this is not comprehensive.Summary by CodeRabbit
New Features
Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.