class Riffer::Rig::Terminal::Frame
Constants
- CURSOR
-
Marks the cursor’s cell in the text handed to the wrapper, so the wrapped row and column can be read back off it: a private-use code point, which no terminal draws.
- DESCRIPTION_GAP
- ERASE
-
Sent from the top row the frame drew, so this wipes all of it.
- INDENT
- INPUT_ROWS
- LOADING
- PALETTE_ROWS
- PEEK_ROWS
- PROMPT
- PROMPT_COLUMNS
- QUEUED_GAP
-
The first column is the cursor’s own cell when it rests at the end of the text.
- SELECTED
- SPACER
- STATUS_INDENT
Public Class Methods
(IO io) → [ Integer, Integer ]?
Source
# File lib/riffer/rig/terminal/frame.rb, line 66 def self.measure(io) return nil unless io.tty? size = io.winsize size[1].positive? ? size : nil rescue SystemCallError nil end
winsize raises on ttys with no queryable window size and some pty wrappers report zero columns; output that cannot be fitted to the width would wrap mid-line (and strand a footer’s cursor), so neither gets one. @rbs io: IO @rbs return: [Integer, Integer]?
(io: IO, theme: Riffer::Rig::Terminal::Theme, ?editor: Riffer::Rig::Terminal::LineEditor, ?loading: bool, ?now: ^() → Time) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 81 def initialize(io:, theme:, editor: Riffer::Rig::Terminal::LineEditor.new, loading: false, now: -> { Time.now }) @io = io @theme = theme @editor = editor @completion = nil @status = '' @hint = nil @queued = 0 @jobs = 0 @peek = '' @rows_above = 0 @height = 0 @width = 0 @active = false @loading = loading @loading_line = LOADING @tally = nil @reasoning = nil @now = now @mutex = Mutex.new @previous_resize = nil end
@rbs io: IO @rbs theme: Riffer::Rig::Terminal::Theme @rbs editor: Riffer::Rig::Terminal::LineEditor @rbs loading: bool @rbs now: ^() -> Time @rbs return: void
Public Instance Methods
(String content) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 120 def append(content) lines = content.end_with?("\n") ? content : "#{content}\n" @mutex.synchronize do # The first content and the footer it draws go out in this one write, so # this is where the loading screen ends. @loading = false # The key pipeline's raw mode turns off output post-processing, so a # bare line feed would not return the carriage. @active ? draw("#{erase}#{lines.gsub(/\r?\n/, "\r\n")}") : write(lines) end end
@rbs content: String @rbs return: void
(Riffer::Rig::Terminal::Autocomplete completion) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 144 def complete(completion) @mutex.synchronize do @editor = completion.editor @completion = completion redraw end end
@rbs completion: Riffer::Rig::Terminal::Autocomplete @rbs return: void
(String? hint) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 179 def hint(hint) @mutex.synchronize do @hint = hint redraw end end
@rbs hint: String? @rbs return: void
() → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 216 def idle_tick @mutex.synchronize do redraw if idle_bar_showing? end end
@rbs return: void
(Riffer::Rig::Terminal::LineEditor editor) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 134 def input(editor) @mutex.synchronize do @editor = editor @completion = nil redraw end end
@rbs editor: Riffer::Rig::Terminal::LineEditor @rbs return: void
() → Integer
Source
# File lib/riffer/rig/terminal/frame.rb, line 228 def job_count @mutex.synchronize { @jobs } end
@rbs return: Integer
(Integer count) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 197 def jobs(count) @mutex.synchronize do @jobs = count redraw end end
@rbs count: Integer @rbs return: void
(String line) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 163 def loading(line) @mutex.synchronize do @loading_line = line # A tick still in flight once the banner drew would otherwise redraw the # footer under it. redraw if @loading end end
@rbs line: String @rbs return: void
() → bool
Source
# File lib/riffer/rig/terminal/frame.rb, line 173 def loading? @mutex.synchronize { @loading } end
@rbs return: bool
() → [ Integer, Integer ]?
Source
# File lib/riffer/rig/terminal/frame.rb, line 261 def measure self.class.measure(@io) end
@rbs return: [Integer, Integer]?
(String content) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 239 def peek(content) @mutex.synchronize do @peek = content redraw end end
@rbs content: String @rbs return: void
(Integer count) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 188 def queued(count) @mutex.synchronize do @queued = count redraw end end
@rbs count: Integer @rbs return: void
() → String?
Source
# File lib/riffer/rig/terminal/frame.rb, line 233 def reasoning @mutex.synchronize { @reasoning&.call } end
@rbs return: String?
(tally: ^() → Riffer::Providers::TokenUsage?, reasoning: ^() → String?) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 207 def session(tally:, reasoning:) @mutex.synchronize do @tally = tally @reasoning = reasoning redraw end end
@rbs tally: ^() -> Riffer::Providers::TokenUsage? @rbs reasoning: ^() -> String? @rbs return: void
() → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 105 def start @mutex.synchronize do size = measure return unless size @height, @width = size @active = true draw end # A trap handler may not take the mutex, so it hands the resize to a thread. @previous_resize = Signal.trap('WINCH') { Thread.new { resize } } end
@rbs return: void
(String status) → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 154 def status(status) @mutex.synchronize do @status = status redraw end end
@rbs status: String @rbs return: void
() → Integer
Source
# File lib/riffer/rig/terminal/frame.rb, line 223 def status_room @mutex.synchronize { [(@width - 1) - STATUS_INDENT.size, 0].max } end
@rbs return: Integer
() → void
Source
# File lib/riffer/rig/terminal/frame.rb, line 247 def stop @mutex.synchronize do return unless @active @active = false # Ends the loading animation's thread, which stops itself from its next # tick once the row it draws is gone. @loading = false write(erase) end Signal.trap('WINCH', @previous_resize) end
@rbs return: void