Skip to content

Draw an element at the position passed to IConsoleProvider.Render [patch] - #204

Merged
matt-edmondson merged 2 commits into
mainfrom
fix/156-render-at-position
Oct 9, 2026
Merged

matt-edmondson merged 2 commits into
mainfrom
fix/156-render-at-position

Conversation

@matt-edmondson

@matt-edmondson matt-edmondson commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #156

What was wrong

SpectreConsoleProvider.Render(element, position) moved the cursor to position and then called element.Render(this). Every element draws through WriteAt at absolute coordinates taken from its own Position, and each WriteAt moves the cursor itself, so the requested position was silently ignored. The method then "restored" a cursor position read from System.Console, not from the injected IAnsiConsole, which moved the Spectre cursor somewhere unrelated.

Change

This takes the "honor the position" option from the issue, so it is not a breaking change:

  • New internal OffsetConsoleProvider forwards to another provider and shifts every position (WriteAt, SetCursorPosition, nested Render) by a fixed offset.
  • Render draws through it with offset = position - element.Position, or directly when the offset is zero. A container's children draw through the same provider, so the whole subtree moves together, and the element's Position and layout are left untouched.
  • The System.Console save and restore and the now-unused GetCursorPosition are removed.
  • The IConsoleProvider.Render docs now say that the element's top-left corner goes at position.

Tests (SpectreConsoleProviderTests)

  • RenderDrawsTheElementAtTheGivenPosition: the issue's repro. Hi is written at ESC[3;5H and nothing else, and the element's own position is unchanged.
  • RenderShiftsAContainerAndItsChildrenTogether: a BorderElement with a child, rendered elsewhere, matches the output of the same border laid out at that position.
  • RenderAtTheElementsOwnPositionDrawsItThere

With the fix reverted, all 3 fail. With it applied, the full suite passes (256/256). A trial merge (git merge-tree) shows this branch combines cleanly with #202 and #203.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GJ23oLAT8FnLaMo3MfBviR

…r [patch]

SpectreConsoleProvider.Render moved the cursor to the position and then let
the element draw, but every write moves the cursor itself from the element's
own Position, so the position was ignored. It then "restored" a cursor read
from System.Console rather than the injected console.

Render now draws through an OffsetConsoleProvider that shifts every write by
the difference between the requested position and the element's own, which
moves a container and its children together and leaves the element's layout
untouched. The System.Console save and restore is gone.

Fixes #156

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJ23oLAT8FnLaMo3MfBviR
matt-edmondson pushed a commit that referenced this pull request Oct 7, 2026
…f their files

Keeps this change clear of the lines #204 edits, so the two merge
in either order without a conflict. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJ23oLAT8FnLaMo3MfBviR
SonarCloud measured 40% coverage on the new code because the provider's
pass-through members were never exercised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GJ23oLAT8FnLaMo3MfBviR
@sonarqubecloud

sonarqubecloud Bot commented Oct 7, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 8460fb0 into main Oct 9, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/156-render-at-position branch October 9, 2026 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants