class HighLine::ListRenderer

This class is a utility for quickly and easily laying out lists to be used by HighLine.

Attributes

highline[R]

@return [HighLine] context

items[R]

Items list @return [Array]

mode[R]

@return [Symbol] the current mode the List is being rendered @see initialize for more details see mode parameter of initialize

option[R]

Changes the behaviour of some modes. Example, in :inline mode the option is treated as the 'end separator' (defaults to “ or ”) @return option parameter that changes the behaviour of some modes.

row_join_string[W]

Public Class Methods

new(items, mode = :rows, option = nil, highline) click to toggle source

The only required parameters are items and highline. @param items [Array] the Array of items to list @param mode [Symbol] controls how that list is formed @param option has different effects, depending on the mode. @param highline [HighLine] a HighLine instance to direct the output to.

Recognized modes are:

:columns_across

items will be placed in columns, flowing from left to right. If given, option is the number of columns to be used. When absent, columns will be determined based on wrap_at or a default of 80 characters.

:columns_down

Identical to :columns_across, save flow goes down.

:uneven_columns_across

Like :columns_across but each column is sized independently.

:uneven_columns_down

Like :columns_down but each column is sized independently.

:inline

All items are placed on a single line. The last two items are separated by option or a default of “ or ”. All other items are separated by “, ”.

:rows

The default mode. Each of the items is placed on its own line. The option parameter is ignored in this mode.

Each member of the items Array is passed through ERb and thus can contain their own expansions. Color escape expansions do not contribute to the final field width.

# File lib/highline/list_renderer.rb, line 61
def initialize(items, mode = :rows, option = nil, highline)
  @highline = highline
  @mode     = mode
  @option   = option
  @items    = render_list_items(items)
end

Public Instance Methods

render() click to toggle source

Render the list using the appropriate mode and options. @return [String] rendered list as String

# File lib/highline/list_renderer.rb, line 70
def render
  return "" if items.empty?

  case mode
  when :inline
    list_inline_mode
  when :columns_across
    list_columns_across_mode
  when :columns_down
    list_columns_down_mode
  when :uneven_columns_across
    list_uneven_columns_mode
  when :uneven_columns_down
    list_uneven_columns_down_mode
  else
    list_default_mode
  end
end

Private Instance Methods

actual_length(text) click to toggle source
# File lib/highline/list_renderer.rb, line 211
def actual_length(text)
  HighLine::Wrapper.actual_length text
end
actual_lengths_for(line) click to toggle source
# File lib/highline/list_renderer.rb, line 194
def actual_lengths_for(line)
  line.map do |item|
    actual_length(item)
  end
end
col_count() click to toggle source
# File lib/highline/list_renderer.rb, line 242
def col_count
  option || col_count_calculate
end
col_count_calculate() click to toggle source
# File lib/highline/list_renderer.rb, line 237
def col_count_calculate
  (line_size_limit + row_join_str_size) /
    (items_max_length + row_join_str_size)
end
get_col_widths(lines) click to toggle source
# File lib/highline/list_renderer.rb, line 179
def get_col_widths(lines)
  lines = transpose(lines)
  get_segment_widths(lines)
end
get_row_widths(lines) click to toggle source
# File lib/highline/list_renderer.rb, line 184
def get_row_widths(lines)
  get_segment_widths(lines)
end
get_segment_widths(lines) click to toggle source
# File lib/highline/list_renderer.rb, line 188
def get_segment_widths(lines)
  lines.map do |col|
    actual_lengths_for(col).max
  end
end
inside_line_size_limit?(widths) click to toggle source
# File lib/highline/list_renderer.rb, line 206
def inside_line_size_limit?(widths)
  line_size = widths.reduce(0) { |sum, n| sum + n + row_join_str_size }
  line_size <= line_size_limit + row_join_str_size
end
items_max_length() click to toggle source
# File lib/highline/list_renderer.rb, line 215
def items_max_length
  @items_max_length ||= max_length(items)
end
line_size_limit() click to toggle source
# File lib/highline/list_renderer.rb, line 223
def line_size_limit
  @line_size_limit ||= (highline.wrap_at || 80)
end
list_columns_across_mode() click to toggle source
# File lib/highline/list_renderer.rb, line 119
def list_columns_across_mode
  HighLine::List.new(right_padded_items, cols: col_count).to_s
end
list_columns_down_mode() click to toggle source
# File lib/highline/list_renderer.rb, line 123
def list_columns_down_mode
  HighLine::List.new(
    right_padded_items,
    cols: col_count,
    col_down: true
  ).to_s
end
list_default_mode() click to toggle source
# File lib/highline/list_renderer.rb, line 105
def list_default_mode
  items.map { |i| "#{i}\n" }.join
end
list_inline_mode() click to toggle source
# File lib/highline/list_renderer.rb, line 109
def list_inline_mode
  end_separator = option || " or "

  if items.size == 1
    items.first
  else
    items[0..-2].join(", ") + "#{end_separator}#{items.last}"
  end
end
list_uneven_columns_down_mode() click to toggle source
# File lib/highline/list_renderer.rb, line 147
def list_uneven_columns_down_mode
  list = HighLine::List.new(items, col_down: true)
  list_uneven_columns_mode(list)
end
list_uneven_columns_mode(list = nil) click to toggle source
# File lib/highline/list_renderer.rb, line 131
def list_uneven_columns_mode(list = nil)
  list ||= HighLine::List.new(items)

  col_max = option || items.size
  col_max.downto(1) do |column_count|
    list.cols = column_count
    widths = get_col_widths(list)

    if column_count == 1 || # last guess
       inside_line_size_limit?(widths) || # good guess
       option # defined by user
      return pad_uneven_rows(list, widths)
    end
  end
end
max_length(items) click to toggle source
# File lib/highline/list_renderer.rb, line 219
def max_length(items)
  items.map { |item| actual_length(item) }.max
end
pad_char() click to toggle source
# File lib/highline/list_renderer.rb, line 252
def pad_char
  " "
end
pad_uneven_rows(list, widths) click to toggle source
# File lib/highline/list_renderer.rb, line 152
def pad_uneven_rows(list, widths)
  right_padded_list = Array(list).map do |row|
    right_pad_row(row.compact, widths)
  end
  stringfy_list(right_padded_list)
end
render_list_items(items) click to toggle source
# File lib/highline/list_renderer.rb, line 91
def render_list_items(items)
  items.to_ary.map do |item|
    item = String(item)
    template = if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
      ERB.new(item, trim_mode: "%")
    else
      ERB.new(item, nil, "%")
    end
    template_renderer =
      HighLine::TemplateRenderer.new(template, self, highline)
    template_renderer.render
  end
end
right_pad_field(field, width) click to toggle source
# File lib/highline/list_renderer.rb, line 173
def right_pad_field(field, width)
  field = String(field) # nil protection
  pad_size = width - actual_length(field)
  field + (pad_char * pad_size)
end
right_pad_row(row, widths) click to toggle source
# File lib/highline/list_renderer.rb, line 167
def right_pad_row(row, widths)
  row.zip(widths).map do |field, width|
    right_pad_field(field, width)
  end
end
right_padded_items() click to toggle source
# File lib/highline/list_renderer.rb, line 246
def right_padded_items
  items.map do |item|
    right_pad_field(item, items_max_length)
  end
end
row_count() click to toggle source
# File lib/highline/list_renderer.rb, line 256
def row_count
  (items.count / col_count.to_f).ceil
end
row_join_str_size() click to toggle source
# File lib/highline/list_renderer.rb, line 233
def row_join_str_size
  row_join_string.size
end
row_join_string() click to toggle source
# File lib/highline/list_renderer.rb, line 227
def row_join_string
  @row_join_string ||= "  "
end
row_to_s(row) click to toggle source
# File lib/highline/list_renderer.rb, line 163
def row_to_s(row)
  row.compact.join(row_join_string) + "\n"
end
stringfy_list(list) click to toggle source
# File lib/highline/list_renderer.rb, line 159
def stringfy_list(list)
  list.map { |row| row_to_s(row) }.join
end
transpose(lines) click to toggle source
# File lib/highline/list_renderer.rb, line 200
def transpose(lines)
  lines = Array(lines)
  first_line = lines.shift
  first_line.zip(*lines)
end