Class: Terminal::Ansi::ScreenViewer

Inherits:
Object
  • Object
show all
Defined in:
lib/terminal/ansi/screen_viewer.rb

Overview

A scrollable text viewer for the terminal.

Renders word-wrapped content and supports paging, line-by-line scrolling, and terminal resize. Intended for use with the alternate screen buffer.

Examples:

Basic pager

viewer = Terminal::Ansi::ScreenViewer.new(lines, footer_rows: 1)
Terminal.show_alt_screen
viewer.draw
Terminal.on_key_event do |event|
  case event.key
  when :Up then viewer.up
  when :Down then viewer.down
  when :PageUp then viewer.page_up
  when :PageDown then viewer.page_down
  when 'q' then break
  end
end
Terminal.hide_alt_screen

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lines, footer_rows: 0, bbcode: true) ⇒ ScreenViewer

Create a new screen viewer.

Parameters:

  • lines (Array<#to_s>)

    content lines to display

  • footer_rows (Integer) (defaults to: 0)

    number of rows reserved at the bottom (not scrolled with content)

  • bbcode (true, false) (defaults to: true)

    whether to process BBCode markup



179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/terminal/ansi/screen_viewer.rb', line 179

def initialize(lines, footer_rows: 0, bbcode: true)
  @footer_rows = footer_rows.to_i
  @rows, @columns = Terminal.size
  @rows_visible = @rows - @footer_rows
  @fmt =
    Text::Formatter.new(
      *lines,
      bbcode: bbcode,
      ansi: true,
      eol: true,
      spaces: true
    )
end

Instance Attribute Details

#columnsInteger

Total number of terminal columns.

Returns:

  • (Integer)


40
41
42
# File 'lib/terminal/ansi/screen_viewer.rb', line 40

def columns
  @columns
end

#line_bottomInteger (readonly)

Index of the line just below the last visible line.

Returns:

  • (Integer)


67
# File 'lib/terminal/ansi/screen_viewer.rb', line 67

def line_bottom = (@line_top + @rows_visible if @line_top)

#line_countInteger? (readonly)

Total number of lines.

Returns:

  • (Integer, nil)

    +nil+ when not already calculated



56
# File 'lib/terminal/ansi/screen_viewer.rb', line 56

def line_count = @buf&.size

#line_topInteger (readonly)

Index of the topmost visible line.

Returns:

  • (Integer)


61
62
63
# File 'lib/terminal/ansi/screen_viewer.rb', line 61

def line_top
  @line_top
end

#rowsInteger

Total number of terminal rows.

Returns:

  • (Integer)


30
31
32
# File 'lib/terminal/ansi/screen_viewer.rb', line 30

def rows
  @rows
end

#rows_visibleInteger (readonly)

Number of rows available for content (rows minus footer).

Returns:

  • (Integer)


50
51
52
# File 'lib/terminal/ansi/screen_viewer.rb', line 50

def rows_visible
  @rows_visible
end

Instance Method Details

#beginself?

Scroll to the beginning of the content.

Returns:

  • (self, nil)

    +nil+ when already on begin



103
104
105
106
107
108
# File 'lib/terminal/ansi/screen_viewer.rb', line 103

def begin
  return draw unless @buf
  return if @line_top == 0
  @line_top = 0
  draw
end

#down(count = 1) ⇒ self?

Scroll down by the given number of lines.

Parameters:

  • count (Integer) (defaults to: 1)

    number of lines to scroll

Returns:

  • (self, nil)

    +nil+ when already on end



143
144
145
146
147
148
149
150
151
# File 'lib/terminal/ansi/screen_viewer.rb', line 143

def down(count = 1)
  return draw unless @buf
  lidx = @line_top + @rows_visible
  return if (count = [count, @buf.size - lidx].min) <= 0
  @line_top += count
  Terminal.raw_write(Ansi.screen_scroll_up(count))
  Terminal.raw_write(Ansi.cursor_pos(@rows_visible - count + 1))
  _draw(lidx, count)
end

#drawself

Render the current viewport to the terminal.

Returns:

  • (self)


90
91
92
93
94
95
96
97
98
# File 'lib/terminal/ansi/screen_viewer.rb', line 90

def draw
  recalculate unless @buf
  if @buf.empty?
    Terminal.raw_write(SCREEN_ERASE)
    return self
  end
  Terminal.raw_write(CURSOR_HOME)
  _draw(@line_top, @rows_visible)
end

#endself?

Scroll to the end of the content.

Returns:

  • (self, nil)

    +nil+ when already on end



113
114
115
116
117
118
119
# File 'lib/terminal/ansi/screen_viewer.rb', line 113

def end
  return draw unless @buf
  idx = @buf.size - @rows_visible
  return if idx < 0 || @line_top == idx
  @line_top = idx
  draw
end

#half_downself?

Scroll down by half a page.

Returns:

  • (self, nil)

    +nil+ when already on end



171
# File 'lib/terminal/ansi/screen_viewer.rb', line 171

def half_down = down(@rows_visible / 2)

#half_upself?

Scroll up by half a page.

Returns:

  • (self, nil)

    +nil+ when already on begin



161
# File 'lib/terminal/ansi/screen_viewer.rb', line 161

def half_up = up(@rows_visible / 2)

#page_downself?

Scroll down by one full page.

Returns:

  • (self, nil)

    +nil+ when already on end



166
# File 'lib/terminal/ansi/screen_viewer.rb', line 166

def page_down = down(@rows_visible)

#page_upself?

Scroll up by one full page.

Returns:

  • (self, nil)

    +nil+ when already on begin



156
# File 'lib/terminal/ansi/screen_viewer.rb', line 156

def page_up = up(@rows_visible)

#resize(rows, columns) ⇒ self?

Resize to specific dimensions (clamped to terminal bounds) and redraw.

Parameters:

  • rows (Integer)

    new row count

  • columns (Integer)

    new column count

Returns:

  • (self, nil)

    +nil+ when resize is not required



80
81
82
83
84
85
# File 'lib/terminal/ansi/screen_viewer.rb', line 80

def resize(rows, columns)
  _resize(
    rows.clamp(1, Terminal.rows),
    columns.clamp(1, Terminal.columns)
  )
end

#resize_to_screenself?

Resize to the current terminal dimensions and redraw.

Returns:

  • (self, nil)

    +nil+ when resize is not required



72
# File 'lib/terminal/ansi/screen_viewer.rb', line 72

def resize_to_screen = _resize(*Terminal.size)

#up(count = 1) ⇒ self?

Scroll up by the given number of lines.

Parameters:

  • count (Integer) (defaults to: 1)

    number of lines to scroll

Returns:

  • (self, nil)

    +nil+ when already on begin



125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/terminal/ansi/screen_viewer.rb', line 125

def up(count = 1)
  return draw unless @buf
  return if @line_top == 0
  if (nidx = @line_top - count) < 0
    count = @line_top
    @line_top = 0
  else
    @line_top = nidx
  end
  Terminal.raw_write(Ansi.screen_scroll_down(count))
  Terminal.raw_write(CURSOR_HOME)
  _draw(@line_top, count)
end