class BBS::Petscii::Screen
The screen of one call on a line-by-line board, and the ways such a board talks: a reversed title bar, pages of text that wait for RETURN, numbered cursor lists (BBS::Selector), single-key and cursor menus, a line field (BBS::Field) and the full-screen editor (BBS::Editor).
It is made for a Commodore 64, a 40×25 screen on a session switched with session.petscii!, which makes PETSCII of what the screen writes. Given cols and rows it serves a modern terminal too: on a session that is not PETSCII, cls homes the cursor and the text is not made plain.
The colours are the ANSI constants of BBS::Petscii::Colors, included, so a subclass writes WH, LG … bare. A board subclasses it for methods of its own:
class Screen < BBS::Petscii::Screen def banner(text) = puts(" #{YE}#{text}#{LG}") end screen = Screen.new(runner.session) screen.title('the shelves', 'q: back') book = screen.pick('the shelves', books, &:title)
Constants
- CHROME
-
The rows above and below a page of text: the title bar, the line before the key prompt, the prompt and the screen’s last row.
- COLS
-
The width of the C64 screen.
- EMPTY
- MODERN_CLEAR
-
The clear screen of a modern terminal: colours reset, cursor home.
- PAGE
-
The lines of text on a C64 page (
page_sizeof a 40×25 screen). - PICK_HINT
-
The status row of
pick. - ROWS
-
The height of the C64 screen.
- WIDTH
-
The width of a wrapped paragraph on the C64: a column of margin on both sides.
Attributes
The screen’s width and height in characters.
The screen’s width and height in characters.
The session written to and read from (BBS::Session or one that quacks like it).
Public Class Methods
# File lib/bbs/petscii/screen.rb, line 61 def initialize(session, cols: COLS, rows: ROWS) @session = session @cols = cols @rows = rows @width = cols - 2 end
Creates the screen of session, cols × rows (default the C64’s 40×25).
Public Instance Methods
Source
# File lib/bbs/petscii/screen.rb, line 85 def cls = write(petscii? ? Petscii::CLEAR : MODERN_CLEAR)
Clears the screen: the C64’s CLR, or MODERN_CLEAR on a modern terminal.
# File lib/bbs/petscii/screen.rb, line 118 def fit(lines, width = @cols - 1) lines.flat_map do |l| next [''] if l.to_s.empty? indent = FrameBuffer.plain(l)[/\A */] first, *rest = wrap(l, width) next [first] if rest.empty? [first, *wrap(rest.join(' '), width - indent.size).map { |r| "#{indent}#{r}" }] end end
Every line of lines cut to width, the long ones wrapped under their own indent. An empty line stays one. Returns the lines.
Source
# File lib/bbs/petscii/screen.rb, line 140 def key(timeout: nil) k = @session.readkey(timeout: timeout) raise IOError, 'the caller hung up' if k.nil? k end
Reads a key (see BBS::Telnet#readkey): :idle after timeout seconds, when given. Raises IOError when the caller hangs up.
# File lib/bbs/petscii/screen.rb, line 159 def page(heading, lines, right: '', wait: true, room: 1, numbers: false) lines = fit(lines) lines = [" #{GR}#{EMPTY}#{LG}"] if lines.empty? chunks = lines.each_slice(wait ? page_size : page_size - room).to_a chunks.each_with_index do |chunk, i| title(heading, numbers ? "#{right}#{i + 1}/#{chunks.size}" : right) chunk.each { |l| puts l } break unless turn_page?(i == chunks.size - 1, wait) end nil end
Shows lines (fit to the screen) one page_size at a time, each page under the title of heading and right, waiting for RETURN after each; q, ← or RUN/STOP leave early.
- right
-
the right end of the title bar
- wait
-
false: the last page does not wait, and leaves
roomrows free for what follows (a command line) - room
-
the rows the last page leaves free with
waitfalse - numbers
-
true: the title bar shows the page,
2/5, afterright
Returns nil.
Source
# File lib/bbs/petscii/screen.rb, line 69 def page_size = @rows - CHROME
Source
# File lib/bbs/petscii/screen.rb, line 73 def petscii? = !@session.respond_to?(:petscii?) || @session.petscii?
Whether the session speaks PETSCII; true for a session that cannot tell.
Source
# File lib/bbs/petscii/screen.rb, line 114 def plain(text) = petscii? ? Petscii.plain(text) : text.to_s
text in characters the C64 shows one to a cell (BBS::Petscii.plain) on a PETSCII session; as it is on a modern one.
Source
# File lib/bbs/petscii/screen.rb, line 79 def puts(text = '') write("#{text}\r\n") end
Writes text and a line end.
Source
# File lib/bbs/petscii/screen.rb, line 106 def rule(color: DG) = puts("#{color}#{'─' * (@cols - 1)}#{LG}")
Writes a horizontal line in color, the screen’s width less one.
Source
# File lib/bbs/petscii/screen.rb, line 134 def say(text, color: LG) wrap(plain(text)).each { |l| puts " #{color}#{l}#{LG}" } end
Source
# File lib/bbs/petscii/screen.rb, line 91 def title(text, right = '') cls puts title_bar(text, right) end
Clears the screen and writes the title_bar of text and right.
Source
# File lib/bbs/petscii/screen.rb, line 99 def title_bar(text, right = '') room = @cols - right.length - 1 bar = " #{plain(text)}".ljust(room)[0, room] + "#{right} " "#{CY}#{RV}#{bar}#{RO}#{LG}" end
A reversed cyan bar the width of the screen less its last column: text (made plain) at the left, right at the right; text is cut where it would run into right.
Source
# File lib/bbs/petscii/screen.rb, line 110 def wrap(text, width = @width) = FrameBuffer.wrap_ansi(text.to_s, width)
text word-wrapped to width columns, ANSI colours kept: an Array of lines (BBS::FrameBuffer.wrap_ansi).
Source
# File lib/bbs/petscii/screen.rb, line 76 def write(text) = @session.write(text)
Writes text to the session as it is.