Module: Charming::Presentation::UI
- Defined in:
- lib/charming/presentation/ui.rb,
lib/charming/presentation/ui/style.rb,
lib/charming/presentation/ui/theme.rb,
lib/charming/presentation/ui/width.rb,
lib/charming/presentation/ui/border.rb,
lib/charming/presentation/ui/canvas.rb,
lib/charming/presentation/ui/ansi_codes.rb,
lib/charming/presentation/ui/ansi_slicer.rb,
lib/charming/presentation/ui/border_painter.rb
Overview
UI is a module of layout primitives for composing and positioning ANSI-styled terminal text. It provides functions to join blocks horizontally or vertically, place content on fixed-size canvases, overlay elements, and slice strings that contain ANSI escape sequences while preserving their styling.
Defined Under Namespace
Modules: Width Classes: ANSICodes, ANSISlicer, Border, BorderPainter, Canvas, Style, Theme
Class Method Summary collapse
-
.block_height(blocks) ⇒ Object
Returns the height in rows of each normalised block, taking the maximum across all blocks.
-
.block_width(lines) ⇒ Object
Returns the maximum visual character width across all lines, accounting for multi-column characters (e.g., full-width CJK glyphs) and invisible ANSI escape sequences.
-
.block_widths(blocks) ⇒ Object
Measures the displayed (visual) width of each normalised block, returning an array of integer widths.
-
.center(block, width:, height:, background: nil) ⇒ Object
Centers a block within a canvas of the given width and height, then returns the result.
-
.horizontal_line(blocks, widths, index) ⇒ Object
Builds a single horizontal row by concatenating one line from each block at index index, padding every segment to its corresponding width in spaces.
-
.join_horizontal(*blocks, gap: 0) ⇒ Object
Horizontally concatenates blocks into a single multi-line string, padding each block’s rows to match the widest row.
-
.join_vertical(*blocks, gap: 0) ⇒ Object
Stacks blocks vertically separated by one or more blank lines.
-
.normalize_blocks(blocks) ⇒ Object
Normalizes an array of mixed objects into arrays of lines by calling ‘#to_s` on each element.
-
.overlay(base, overlay, top: :center, left: :center) ⇒ Object
Draws overlay on top of a base at the specified top (row) and left (column) coordinates, defaulting to center in both directions.
-
.place(block, width:, height:, top: 0, left: 0, background: nil) ⇒ Object
Places block onto a blank canvas of width × height at an offset determined by top (row) and left (column).
-
.style ⇒ Object
Builds a new Style instance for chaining color, padding, alignment, and other visual properties.
-
.visible_slice(line, start_column, width) ⇒ Object
Returns a visible-slice of line starting at start_column spanning width characters, preserving any ANSI escape sequences that were active at the start of the slice.
Class Method Details
.block_height(blocks) ⇒ Object
Returns the height in rows of each normalised block, taking the maximum across all blocks.
77 78 79 |
# File 'lib/charming/presentation/ui.rb', line 77 def block_height(blocks) blocks.map(&:length).max || 0 end |
.block_width(lines) ⇒ Object
Returns the maximum visual character width across all lines, accounting for multi-column characters (e.g., full-width CJK glyphs) and invisible ANSI escape sequences.
72 73 74 |
# File 'lib/charming/presentation/ui.rb', line 72 def block_width(lines) lines.map { |line| Width.measure(line) }.max || 0 end |
.block_widths(blocks) ⇒ Object
Measures the displayed (visual) width of each normalised block, returning an array of integer widths.
66 67 68 |
# File 'lib/charming/presentation/ui.rb', line 66 def block_widths(blocks) blocks.map { |lines| lines.map { |line| Width.measure(line) }.max || 0 } end |
.center(block, width:, height:, background: nil) ⇒ Object
Centers a block within a canvas of the given width and height, then returns the result.
50 51 52 |
# File 'lib/charming/presentation/ui.rb', line 50 def center(block, width:, height:, background: nil) place(block, width: width, height: height, top: :center, left: :center, background: background) end |
.horizontal_line(blocks, widths, index) ⇒ Object
Builds a single horizontal row by concatenating one line from each block at index index, padding every segment to its corresponding width in spaces. Returns the assembled array of padded segments.
83 84 85 86 87 88 |
# File 'lib/charming/presentation/ui.rb', line 83 def horizontal_line(blocks, widths, index) blocks.each_with_index.map do |lines, block_index| line = lines[index] || "" line + (" " * (widths[block_index] - Width.measure(line))) end end |
.join_horizontal(*blocks, gap: 0) ⇒ Object
Horizontally concatenates blocks into a single multi-line string, padding each block’s rows to match the widest row. A gap argument (in spaces) can separate adjacent columns.
19 20 21 22 23 24 25 26 27 |
# File 'lib/charming/presentation/ui.rb', line 19 def join_horizontal(*blocks, gap: 0) normalized = normalize_blocks(blocks) widths = block_widths(normalized) separator = " " * gap Array.new(block_height(normalized)) do |index| horizontal_line(normalized, widths, index).join(separator) end.join("\n") end |
.join_vertical(*blocks, gap: 0) ⇒ Object
Stacks blocks vertically separated by one or more blank lines. A gap of N inserts N extra newline characters between blocks (1 gap = 1 blank line, 2 gaps = 2 blank lines, etc.).
31 32 33 |
# File 'lib/charming/presentation/ui.rb', line 31 def join_vertical(*blocks, gap: 0) blocks.join("\n" * (gap + 1)) end |
.normalize_blocks(blocks) ⇒ Object
Normalizes an array of mixed objects into arrays of lines by calling ‘#to_s` on each element.
61 62 63 |
# File 'lib/charming/presentation/ui.rb', line 61 def normalize_blocks(blocks) blocks.map { |block| block.to_s.lines(chomp: true) } end |
.overlay(base, overlay, top: :center, left: :center) ⇒ Object
Draws overlay on top of a base at the specified top (row) and left (column) coordinates, defaulting to center in both directions. ANSI styling on the base content is preserved underneath.
45 46 47 |
# File 'lib/charming/presentation/ui.rb', line 45 def (base, , top: :center, left: :center) Canvas.parse(base).(, top: top, left: left).to_s end |
.place(block, width:, height:, top: 0, left: 0, background: nil) ⇒ Object
Places block onto a blank canvas of width × height at an offset determined by top (row) and left (column). Non-:center values are treated as absolute positions. When background is given, the assembled frame is wrapped so the theme bg paints the entire canvas — overlay content with its own bg overrides per-cell; resets re-apply the canvas bg.
39 40 41 |
# File 'lib/charming/presentation/ui.rb', line 39 def place(block, width:, height:, top: 0, left: 0, background: nil) Canvas.new(width, height).place(block, top: top, left: left, background: background) end |
.style ⇒ Object
Builds a new Style instance for chaining color, padding, alignment, and other visual properties.
13 14 15 |
# File 'lib/charming/presentation/ui.rb', line 13 def style Style.new end |
.visible_slice(line, start_column, width) ⇒ Object
Returns a visible-slice of line starting at start_column spanning width characters, preserving any ANSI escape sequences that were active at the start of the slice. Non-positive widths return ‘“”`.
56 57 58 |
# File 'lib/charming/presentation/ui.rb', line 56 def visible_slice(line, start_column, width) ANSISlicer.slice(line, start_column, width) end |