Class: Rigor::CLI::TraceRenderer
- Inherits:
-
Object
- Object
- Rigor::CLI::TraceRenderer
- Defined in:
- lib/rigor/cli/trace_renderer.rb
Overview
Replays a ‘Rigor::Inference::FlowTracer` event stream as a terminal animation for `rigor trace`. Each frame draws a box-drawn screen: the source panel (syntax-coloured, current node range underlined) side-by-side with the scope panel (locals accumulated from :bind events), and an event panel describing the current step and the expression stack.
The frame is fitted to the measured terminal: the source panel scrolls vertically (a window centred on the line under evaluation) instead of overflowing the screen height, over-long rows are clipped with an ellipsis instead of wrapping, and the event panel keeps a minimum height of EVENT_PANE_MIN rows so the narration never collapses to a sliver.
Pure ANSI + ‘io/console` (both stdlib) per ADR-0’s zero-runtime- dependency policy. When the output is not a TTY the frames are printed sequentially without cursor control against a default 80×24 layout, which keeps the renderer deterministic under test.
Constant Summary collapse
- RESET =
"\e[0m"- DIM =
"\e[90m"- BOLD =
"\e[1m"- HIGHLIGHT =
reverse video for the frame’s source range
"\e[7m"- EVENT_PANE_MIN =
minimum event-panel rows
2- SCOPE_WIDTH_MIN =
minimum scope-column width
19- BODY_HEIGHT_MIN =
never shrink the source window below this
3- DEFAULT_SIZE =
[24, 80].freeze
Instance Method Summary collapse
-
#initialize(out:, source:, file:) ⇒ TraceRenderer
constructor
A new instance of TraceRenderer.
- #play(events, delay: nil, interactive: false) ⇒ Object
Constructor Details
#initialize(out:, source:, file:) ⇒ TraceRenderer
Returns a new instance of TraceRenderer.
39 40 41 42 43 44 |
# File 'lib/rigor/cli/trace_renderer.rb', line 39 def initialize(out:, source:, file:) @out = out @source = source @file = file @lines = source.lines.map(&:chomp) end |
Instance Method Details
#play(events, delay: nil, interactive: false) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rigor/cli/trace_renderer.rb', line 51 def play(events, delay: nil, interactive: false) @rows, @cols = interactive ? terminal_size : DEFAULT_SIZE @interactive = interactive locals_per_frame = accumulate_locals(events) events.each_with_index do |event, index| @out.print("\e[H\e[2J") if interactive render_frame(event, index: index, total: events.size, locals: locals_per_frame[index]) @out.puts unless interactive next if index == events.size - 1 if delay sleep(delay) elsif interactive break unless next_frame? end end end |