Class: Railbow::Table::Renderer
- Inherits:
-
Object
- Object
- Railbow::Table::Renderer
- Includes:
- Railbow::TextUtils
- Defined in:
- lib/railbow/table/renderer.rb
Constant Summary collapse
- RESET =
"\e[0m"- WHITE =
"\e[97m"- GHOST_BG =
deep red/maroon background - stands out as abnormal
"\e[48;5;52m"- GHOST_FG =
warm pink foreground for contrast
"\e[38;5;217m"- DIMMED_FG =
muted grey - a row that is not currently in effect
"\e[38;5;242m"- MIN_LAST_COL =
The flexing last column never gets less than this from the terminal.
10- MIN_SHRINK_WIDTH =
Default floor for shrinkable columns that name no shrink_floor.
16
Instance Attribute Summary collapse
-
#columns ⇒ Object
readonly
Returns the value of attribute columns.
-
#theme ⇒ Object
readonly
Returns the value of attribute theme.
Instance Method Summary collapse
-
#column_widths(rows) ⇒ Object
The widths this table would resolve to on its own.
-
#fixed_width(widths) ⇒ Object
Width of everything left of the last column.
-
#initialize(columns:, theme:, compact: {}, aliases: {}, min_widths: nil, term_width: nil) ⇒ Renderer
constructor
min_widths raises the resolved width of each column to at least the given value, which is how several tables rendered in one run line their columns up with each other.
- #render(rows, separators: {}, highlight_rows: Set.new, ghost_rows: Set.new, dim_rows: Set.new, tick_rows: Set.new, tick_col: nil) ⇒ Object
Methods included from Railbow::TextUtils
#display_width, #strip_ansi, #truncate_ansi, #truncate_str
Constructor Details
#initialize(columns:, theme:, compact: {}, aliases: {}, min_widths: nil, term_width: nil) ⇒ Renderer
min_widths raises the resolved width of each column to at least the given value, which is how several tables rendered in one run line their columns up with each other. An explicit compact maxw still wins.
term_width overrides the detected terminal width; render re-invokes itself through a reduced renderer when the budget drops a column, and the width it fits must be the same one this instance measured.
31 32 33 34 35 36 37 38 39 |
# File 'lib/railbow/table/renderer.rb', line 31 def initialize(columns:, theme:, compact: {}, aliases: {}, min_widths: nil, term_width: nil) @compact = compact @aliases = aliases @min_widths = min_widths @term_width = term_width @reverse_col_aliases = aliases[:columns]&.invert || {} @columns = apply_hidden_columns(columns) @theme = theme end |
Instance Attribute Details
#columns ⇒ Object (readonly)
Returns the value of attribute columns.
22 23 24 |
# File 'lib/railbow/table/renderer.rb', line 22 def columns @columns end |
#theme ⇒ Object (readonly)
Returns the value of attribute theme.
22 23 24 |
# File 'lib/railbow/table/renderer.rb', line 22 def theme @theme end |
Instance Method Details
#column_widths(rows) ⇒ Object
The widths this table would resolve to on its own. Callers rendering several tables together take the per-column maximum and feed it back as min_widths.
44 45 46 47 48 |
# File 'lib/railbow/table/renderer.rb', line 44 def column_widths(rows) return [] if columns.empty? resolve_widths(prepare_rows(rows)) end |
#fixed_width(widths) ⇒ Object
Width of everything left of the last column. The last column flexes to the terminal, so this is where furniture drawn around the table (a section rule, say) can stop without running past it.
53 54 55 56 57 |
# File 'lib/railbow/table/renderer.rb', line 53 def fixed_width(widths) return 0 if columns.empty? || widths.nil? || widths.empty? compute_prefix_width(widths, columns.size - 1) end |
#render(rows, separators: {}, highlight_rows: Set.new, ghost_rows: Set.new, dim_rows: Set.new, tick_rows: Set.new, tick_col: nil) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/railbow/table/renderer.rb', line 59 def render(rows, separators: {}, highlight_rows: Set.new, ghost_rows: Set.new, dim_rows: Set.new, tick_rows: Set.new, tick_col: nil) return "" if columns.empty? rows = prepare_rows(rows) # Width budget: when even fully shrunk columns cannot bring the table # under the terminal width, sacrifice the most expendable column and # render without it. One column per pass - the reduced renderer asks # again with what is left. if (drop = drop_index_to_fit(rows)) return dropped_renderer(drop).render( rows.map { |row| row.reject.with_index { |_, i| i == drop } }, separators: separators, highlight_rows: highlight_rows, ghost_rows: ghost_rows, dim_rows: dim_rows, tick_rows: tick_rows, tick_col: shift_tick_col(tick_col, drop) ) end resolved = resolve_widths(rows) shrink_to_fit!(resolved, rows) # In oneline mode, truncate non-sticky non-last columns at resolved width if @compact[:oneline] rows = rows.map { |row| row.each_with_index.map { |cell, i| col = columns[i] if col && i < columns.size - 1 && !col.sticky && !col.truncate truncate_str(cell.to_s, resolved[i]) else cell end } } end lines = [] lines << render_header(resolved) unless @compact[:noheader] rows.each_with_index do |row, i| tc = (tick_rows.include?(i) && tick_col) ? tick_col : nil if separators.key?(i) && theme.format_separator lines << render_separator_row(separators[i], resolved, tick_col: tc) tc = nil # tick already shown on separator row end formatted = render_row(row, resolved, tick_col: tc, highlight: highlight_rows.include?(i), ghost: ghost_rows.include?(i), dim: dim_rows.include?(i)) lines << formatted end lines.join("\n") end |