Class: Rubino::UI::IndentedIO

Inherits:
Object
  • Object
show all
Defined in:
lib/rubino/ui/indented_io.rb

Overview

Output decorator that left-pads everything written through it by a fixed indent, so a TTY::Prompt menu renders in the SAME column as the card above it (P7) instead of flush-left at column 0.

tty-prompt repaints its frame by moving the cursor up, clearing lines, and re-printing — so “start of line” is not only “after a newline”: a carriage return or a cursor column-reset escape (‘e[<n>G`) also restart the line. The transform tracks that state ACROSS writes and injects the indent before the first visible character of every line, leaving all escape sequences untouched.

Resolves the underlying IO from the given block on every call (default: the current $stdout) so a composer/proxy swap can never strand a stale handle. Everything else (tty?, winsize, …) delegates to that IO.

Constant Summary collapse

TOKEN_RE =

ANSI CSI/OSC sequences pass through unindented; any other single character is a candidate for the line-start indent.

/\e\[[\d;?]*[A-Za-z]|\e\][^\a\e]*(?:\a|\e\\)|./m

Instance Method Summary collapse

Constructor Details

#initialize(indent: " ", io: nil) ⇒ IndentedIO

Returns a new instance of IndentedIO.



24
25
26
27
28
# File 'lib/rubino/ui/indented_io.rb', line 24

def initialize(indent: "  ", io: nil)
  @indent        = indent
  @resolve       = io ? -> { io } : -> { $stdout }
  @at_line_start = true
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object



56
57
58
# File 'lib/rubino/ui/indented_io.rb', line 56

def method_missing(name, *, &)
  io.respond_to?(name) ? io.public_send(name, *, &) : super
end

Instance Method Details

#<<(text) ⇒ Object



47
48
49
50
# File 'lib/rubino/ui/indented_io.rb', line 47

def <<(text)
  write(text)
  self
end

#flushObject



52
53
54
# File 'lib/rubino/ui/indented_io.rb', line 52

def flush
  io.flush
end


30
31
32
# File 'lib/rubino/ui/indented_io.rb', line 30

def print(*args)
  io.print(*args.map { |a| transform(a.to_s) })
end

#puts(*args) ⇒ Object



38
39
40
41
42
43
44
45
# File 'lib/rubino/ui/indented_io.rb', line 38

def puts(*args)
  if args.empty?
    @at_line_start = true
    io.puts
  else
    print("#{args.join("\n")}\n")
  end
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/rubino/ui/indented_io.rb', line 60

def respond_to_missing?(name, include_private = false)
  io.respond_to?(name, include_private) || super
end

#write(*args) ⇒ Object



34
35
36
# File 'lib/rubino/ui/indented_io.rb', line 34

def write(*args)
  io.write(*args.map { |a| transform(a.to_s) })
end