Class: Rubino::UI::PrinterBase
- Inherits:
-
Base
- Object
- Base
- Rubino::UI::PrinterBase
show all
- Defined in:
- lib/rubino/ui/printer_base.rb
Overview
Shared printing behaviour for terminal-based UI adapters.
Subclasses must implement #color_for(role) returning a Pastel method name (e.g. :cyan, :green) so that message formatting stays here while each adapter controls its own color scheme.
Direct Known Subclasses
CLI
Instance Method Summary
collapse
Methods inherited from Base
#ask, #assistant_text, #blocking_human_input?, #body, #box_close, #box_open, #confirm, #confirm_destructive, #hint_row, #input_injected, #interactive?, #note, #panel_line, #queued, #replay_user_input, #select, #separator, #table, #thinking_started, #tool_body, #turn_interrupted
Constructor Details
Returns a new instance of PrinterBase.
13
14
15
|
# File 'lib/rubino/ui/printer_base.rb', line 13
def initialize
@pastel = Pastel.new
end
|
Instance Method Details
#blank_line ⇒ Object
58
|
# File 'lib/rubino/ui/printer_base.rb', line 58
def blank_line = emit_blank
|
#compression_finished(metadata, at: nil) ⇒ Object
49
50
51
52
|
# File 'lib/rubino/ui/printer_base.rb', line 49
def compression_finished(metadata, at: nil)
saved = metadata[:saved_tokens] || 0
puts_colored(color_for(:muted), " ⟳ Context compacted (saved #{saved} tokens)")
end
|
#compression_started(at: nil) ⇒ Object
45
46
47
|
# File 'lib/rubino/ui/printer_base.rb', line 45
def compression_started(at: nil)
puts_colored(color_for(:muted), " ⟳ Compacting context...")
end
|
#emit(text, style: nil) ⇒ Object
Also known as:
emit_line
PATH 1. Untrusted text → strip ALL escapes → apply style → write. style is a semantic Pastel method symbol (:dim, :cyan, :red, …), an Array of them for a compound decoration (e.g. [:red, :bold]), or nil for no colour. The text is treated as hostile; escapes become visible caret notation, and the style is applied AFTER sanitizing so it can only wrap already-inert text.
110
111
112
113
|
# File 'lib/rubino/ui/printer_base.rb', line 110
def emit(text, style: nil)
safe = Rubino::Util::Output.sanitize_terminal(text.to_s)
write_line(style ? @pastel.decorate(safe, *Array(style)) : safe)
end
|
#emit_blank ⇒ Object
A blank line. Routed through the funnel so $stdout stays private to it.
125
|
# File 'lib/rubino/ui/printer_base.rb', line 125
def emit_blank = write_line
|
#emit_frame(raw) ⇒ Object
A rubino-built CURSOR-CONTROL frame for the live region / status spinner / stream tail (Cat 4 — the hot path). These legitimately carry rubino’s OWN cursor escapes (‘r`, `e[2K`, cursor moves) that a defang would strip, so this writes raw THROUGH the single $stdout seam WITHOUT stripping cursor control, then flushes (transient frames must paint immediately — they are not committed lines).
CONTRACT: the caller has ALREADY defanged every UNTRUSTED span it interpolated (model tail text via #sanitize_terminal at #margined_tail / #show_reasoning_tail; the status label/hint via #safe at build time). Only rubino’s own frame escapes pass here. This exists so even the live/stream writes go through ONE seam — there is no direct $stdout.print left in the render path — without changing the print+flush timing the smooth-cadence measurement depends on.
161
162
163
|
# File 'lib/rubino/ui/printer_base.rb', line 161
def emit_frame(raw)
write_raw(raw.to_s)
end
|
#emit_glyph(prefix, body, style: nil) ⇒ Object
PATH 1 (compose). A TRUSTED rubino-built prefix (a coloured glyph rubino chose, e.g. ‘@pastel.cyan(“●”)`) + an UNTRUSTED body that gets the full PATH-1 defang before its own style wrap. The two are joined and written through the single seam.
Cat 2 of the phase-2 migration: the ‘● <name>` activity/delegation rows interpolate a trusted cyan glyph next to a model-chosen name/preview. A plain #emit(“#glyph #name”) would defang the glyph’s OWN colour (the caret leak); #emit_styled(“#glyph #Rubino::UI::PrinterBase.@pastel@pastel.dim(name)”) would KEEP the untrusted name’s SGR (the injection leak). This composes correctly: the glyph keeps its trusted colour, the body is stripped of every escape and THEN wrapped in style, and the join is written verbatim — the glyph’s SGR and the body style are the only escapes that survive. prefix must be rubino-built (never untrusted); body is always treated as hostile.
141
142
143
144
145
|
# File 'lib/rubino/ui/printer_base.rb', line 141
def emit_glyph(prefix, body, style: nil)
safe = Rubino::Util::Output.sanitize_terminal(body.to_s)
styled = style ? @pastel.decorate(safe, *Array(style)) : safe
write_line("#{prefix}#{styled}")
end
|
#emit_styled(prebuilt) ⇒ Object
PATH 2. rubino’s OWN pre-built styled prebuilt → strip dangerous control bytes, KEEP rubino’s SGR colour → write. For markdown render output, the live region, and rows that interpolate a rubino-coloured glyph. NEVER pass untrusted text here.
#error(message) ⇒ Object
20
|
# File 'lib/rubino/ui/printer_base.rb', line 20
def error(message) = puts_colored(color_for(:error), "✗ #{message}")
|
#info(message) ⇒ Object
17
|
# File 'lib/rubino/ui/printer_base.rb', line 17
def info(message) = puts_colored(color_for(:info), message)
|
#job_enqueued(_type) ⇒ Object
54
|
# File 'lib/rubino/ui/printer_base.rb', line 54
def job_enqueued(_type) = nil
|
#job_finished(_type) ⇒ Object
56
|
# File 'lib/rubino/ui/printer_base.rb', line 56
def job_finished(_type) = nil
|
#job_started(_type) ⇒ Object
55
|
# File 'lib/rubino/ui/printer_base.rb', line 55
def job_started(_type) = nil
|
#mode_changed(name, previous: nil) ⇒ Object
Default fallback. CLI overrides to render the ‘┄ HH:MM · mode → plan ┄` free-line variant.
62
63
64
65
|
# File 'lib/rubino/ui/printer_base.rb', line 62
def mode_changed(name, previous: nil)
arrow = previous && previous != name ? " #{previous} → #{name}" : " #{name}"
puts_colored(color_for(:muted), " ⟳ mode#{arrow}")
end
|
#status(message) ⇒ Object
21
|
# File 'lib/rubino/ui/printer_base.rb', line 21
def status(message) = puts_colored(color_for(:status), message)
|
#stream_end ⇒ Object
32
33
34
|
# File 'lib/rubino/ui/printer_base.rb', line 32
def stream_end
emit_blank
end
|
#success(message) ⇒ Object
18
|
# File 'lib/rubino/ui/printer_base.rb', line 18
def success(message) = puts_colored(color_for(:success), "✓ #{message}")
|
40
41
42
43
|
# File 'lib/rubino/ui/printer_base.rb', line 40
def tool_finished(name, result: nil)
suffix = result ? " (#{result.truncated_preview})" : ""
puts_colored(color_for(:tool), " ← #{name} done#{suffix}")
end
|
36
37
38
|
# File 'lib/rubino/ui/printer_base.rb', line 36
def tool_started(name, arguments: nil, at: nil, call_id: nil)
puts_colored(color_for(:tool), " → Running tool: #{name}")
end
|
#warning(message) ⇒ Object
19
|
# File 'lib/rubino/ui/printer_base.rb', line 19
def warning(message) = puts_colored(color_for(:warning), "⚠ #{message}")
|