✨ hardware cursor positioning via text() caret#103
Conversation
commit: |
22a27c2 to
cfc0338
Compare
cfc0338 to
4d7b8ca
Compare
Merging this PR will degrade performance by 11.58%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | WallTime | pack large list |
63.4 ms | 71.9 ms | -11.73% |
| ❌ | WallTime | pack complex layout |
47.8 ms | 53.9 ms | -11.43% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing cowboyd/text-caret (4d7b8ca) with main (9de7762)2
Footnotes
-
18 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
-
No successful run was found on
main(5e253a7) during the generation of this report, so 9de7762 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩
What does this PR do?
Adds a
caret?: numberproperty to thetext()directive. When declared, the renderer positions the terminal's native cursor at the code-point offset within the text and manages cursor visibility automatically across frames.Motivation: building a text input on top of the renderer requires the terminal cursor to track the insertion point and disappear when no input is focused. The cell where the caret sits depends on the text's layout and wrapping — information the renderer already has and the caller does not.
While painting a synthetic caret is always a possibility, the native caret is almost always going to be preferable.
Open questions
Clay emits no
CLAY_RENDER_COMMAND_TYPE_TEXTfor an empty string, sotext("", { caret: 0 })cannot resolve a cell and silently suppresses the cursor. Documented as a test that captures current behavior. The example works around this by rendering a single space when the field is empty — invisible against the input background, but the placeholder is not ideal. One possible fix is for the renderer to fall back to the caret's parent element's bounds, but unsure what the right call is.There are lurking edge cases around padding and fractional cell widths. Need to dive into those before merging.