Class: Typr::Text
Overview
A vertically scrollable text viewer with word-wrapping, header bar, row selection via hint characters, and search.
Accepts String, IO, or StringIO input. Content is split into display rows by newlines and line width, then rendered as a sliding window.
Example
text = Typr::Text.new(
input: StringIO.new("Hello\nworld"),
header: "My Doc",
top: 2, left: 0.1, right: 0.9, bottom: -4,
border: :round,
colors: { header: [:yellow, :grey30] }
)
text.draw
Constant Summary
Constants included from Typr
COLORS, INPUT, KEY_ESCAPE, KEY_PAGEDOWN, KEY_PAGEUP, KEY_RETURN, KEY_TAB, MIMETYPES, MODES
Instance Attribute Summary collapse
-
#tabspace ⇒ Object
Tabstop width in spaces.
Attributes inherited from Stack
#header, #hints, #hints_start, #keymap, #selected, #separator, #start
Attributes inherited from Space
#borders, #bottom, #colors, #interval, #left, #margin, #right, #top
Instance Method Summary collapse
-
#build(input = nil) ⇒ Object
(also: #<<)
Rebuilds the internal line buffer from
input. -
#draw ⇒ Object
Full draw cycle: rebuilds on resize, computes visible lines, and renders the viewport with borders and hints.
-
#initialize(args = {}) ⇒ Text
constructor
Creates a new Text widget.
-
#positions(row) ⇒ Object
Returns word-boundary column offsets for a given page row.
-
#print(row = nil) ⇒ Object
Renders a single display row.
-
#rows ⇒ Object
Total number of text lines in the buffer.
Methods inherited from Stack
#cycle, #down, #draw_hints, #headspace, #height, #page, #page_down, #page_up, #pick, #reset, #send, #to_bottom, #to_top, #up
Methods inherited from Space
#border=, #draw_border, #height, #start, #stop, #width
Methods included from Typr
#background, clear, #coerce_type, #color, #color_code, column, exit, #fade, #foreground, #get_background, #get_foreground, height, init, #mode, #mode_code, #move, #move_code, on_resize, position, #prepare, #printables, read, #real_size, row, #show, size, width
Constructor Details
Instance Attribute Details
#tabspace ⇒ Object
Tabstop width in spaces. Default: 2.
26 27 28 |
# File 'lib/text.rb', line 26 def tabspace @tabspace end |
Instance Method Details
#build(input = nil) ⇒ Object Also known as: <<
Rebuilds the internal line buffer from input.
Splits text at newlines and word boundaries to fit the current width.
Pass nil to re-parse from the existing buffer (triggered on resize).
text.build("one\ntwo three") # => #<Typr::Text ...>
text << "appended line" # alias for build
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/text.rb', line 35 def build input=nil ( @lines = [0]; input = "" ) if rebuild = !input return self if rebuild && input == "" input = StringIO.new( input.to_s.dup ) unless input.respond_to?(:read) @tail = "" until input.closed? or input.eof? capacity = width - @margin.size - @tail.length chunk = (capacity < 1) ? "x" : capacity line = @tail + input.read(chunk) if line.empty? break else wrap_idx = line.index("\n") || line.rindex(" ") || line.length wrap = [wrap_idx, line.length].min + 1 @data += line[0...wrap] if wrap < line.length @tail = line[wrap..-1] @lines << @data.length else @tail = "" end end break if rebuild && line[-1] == "\n" end until @tail.empty? wrap_idx = @tail.index("\n") || @tail.rindex(" ") || @tail.length wrap = [wrap_idx, @tail.length].min + 1 @data += @tail[0...wrap] if wrap < @tail.length @lines << @data.length @tail = @tail[wrap..-1] else @tail = "" end end @lines << @data.length unless @lines.last == @data.length end |
#draw ⇒ Object
Full draw cycle: rebuilds on resize, computes visible lines, and renders the viewport with borders and hints.
text.draw
100 101 102 103 104 105 106 |
# File 'lib/text.rb', line 100 def draw (build; @lastwidth = width) if width != @lastwidth range = @lines[@start..@start+height] page = StringIO.new @data[range.first..range.last] @page=range[1..-1].map{|pos| page.read(pos-range.first-page.pos).rstrip} super end |
#positions(row) ⇒ Object
Returns word-boundary column offsets for a given page row. Used internally to place hint markers between words.
text.positions(2) # => [0, 6, 10, ...]
91 92 93 |
# File 'lib/text.rb', line 91 def positions row [0] + @page[row-1].chars.map.with_index{|c,i| i+1 if c == @separator}.compact end |
#print(row = nil) ⇒ Object
Renders a single display row. Pass an Integer for a content row
or :header for the header bar.
text.print(:header) # renders the header bar
text.print(3) # renders row 3 of the current page
80 81 82 83 84 |
# File 'lib/text.rb', line 80 def print row=nil header = ( row == :header ) return super unless row and @lines[ row + 1 ] unless header show prepare( ( header ? @header : @page[ row-@start ] ), width ) end |
#rows ⇒ Object
Total number of text lines in the buffer.
text.rows # => 42
112 |
# File 'lib/text.rb', line 112 def rows; @lines.count end |