Class: TuiTui::Screen

Inherits:
Object
  • Object
show all
Defined in:
lib/tui_tui/screen.rb

Overview

Terminal-facing screen owner: session lifecycle, event stream, and rendering.

Constant Summary collapse

DEFAULT_SIZE =
Size.new(rows: 24, cols: 80)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(console, input, output, depth, mouse: true, box: nil) ⇒ Screen

Returns a new instance of Screen.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/tui_tui/screen.rb', line 38

def initialize(console, input, output, depth, mouse: true, box: nil)
  @input = input
  @output = output
  @box_override = box
  # ASCII until start probes a real TTY; safe for non-TTY/StringIO callers.
  @chrome = BoxChrome::ASCII
  @compositor = CanvasCompositor.new(depth: depth)
  @term_size = TerminalSize.new(console, default: DEFAULT_SIZE)
  @events = EventStream.new(input: input, size: @term_size)
  @session = TerminalSession.new(console: console, output: output, events: @events, mouse: mouse)
  @previous = nil
  # the cursor position last written (the session starts it hidden)
  @cursor = nil
end

Instance Attribute Details

#chromeObject (readonly)

Returns the value of attribute chrome.



53
54
55
# File 'lib/tui_tui/screen.rb', line 53

def chrome
  @chrome
end

#eventsObject (readonly)

Returns the value of attribute events.



53
54
55
# File 'lib/tui_tui/screen.rb', line 53

def events
  @events
end

Class Method Details

.mouse_defaultObject



34
35
36
# File 'lib/tui_tui/screen.rb', line 34

def self.mouse_default
  !%w[0 off false].include?(ENV["TUITUI_MOUSE"])
end

.run(input: $stdin, output: $stdout, depth: ColorDepth.detect, mouse: mouse_default, box: ENV["TUITUI_BOX"]) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/tui_tui/screen.rb', line 20

def self.run(input: $stdin, output: $stdout, depth: ColorDepth.detect, mouse: mouse_default, box: ENV["TUITUI_BOX"])
  console = IO.console
  # Let callers provide a non-interactive fallback for piped output.
  return yield(nil) if console.nil? || !output.tty?

  screen = new(console, input, output, depth, mouse: mouse, box: box)
  screen.start
  begin
    yield screen
  ensure
    screen.close
  end
end

Instance Method Details

#closeObject



92
# File 'lib/tui_tui/screen.rb', line 92

def close = @session.close

#copy(text) ⇒ Object



87
88
89
90
# File 'lib/tui_tui/screen.rb', line 87

def copy(text)
  @output.write(Ansi.clipboard(text))
  @output.flush
end

#invalidateObject



83
84
85
# File 'lib/tui_tui/screen.rb', line 83

def invalidate
  @previous = nil
end

#render(canvas) ⇒ Object

Render ‘canvas`: the compositor computes the (full or per-row diff) escape string, then the cursor is repositioned (or hidden). The cursor directive is appended only on a full repaint or when the cursor actually moved, so an idle identical re-render still writes nothing.



73
74
75
76
77
78
79
80
81
# File 'lib/tui_tui/screen.rb', line 73

def render(canvas)
  full = @previous.nil? || !@previous.same_size?(canvas)
  out = @compositor.render(@previous, canvas)
  out += cursor_directive(canvas) if full || canvas.cursor != @cursor
  @output.write(out)
  @output.flush
  @previous = canvas
  @cursor = canvas.cursor
end

#sizeObject



67
# File 'lib/tui_tui/screen.rb', line 67

def size = @term_size.size

#startObject



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tui_tui/screen.rb', line 55

def start
  @session.start
  # Probe box-drawing support once, after raw mode + alt screen, before the
  # first render/next_event so the DSR reply never reaches the key reader.
  @chrome = BoxChrome.resolve(
    input: @input,
    output: @output,
    term_cols: size.cols,
    env: {"TUITUI_BOX" => @box_override}
  )
end