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 62
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 71
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 212
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 195
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 243
def col_count
  option || col_count_calculate
end
col_count_calculate() click to toggle source
# File lib/highline/list_renderer.rb, line 238
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 180
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 185
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 189
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 207
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 216
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 224
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 120
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 124
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 106
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 110
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 148
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 132
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 220
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 253
def pad_char
  " "
end
pad_uneven_rows(list, widths) click to toggle source
# File lib/highline/list_renderer.rb, line 153
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 92
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 174
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 168
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 247
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 257
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 234
def row_join_str_size
  row_join_string.size
end
row_join_string() click to toggle source
# File lib/highline/list_renderer.rb, line 228
def row_join_string
  @row_join_string ||= "  "
end
row_to_s(row) click to toggle source
# File lib/highline/list_renderer.rb, line 164
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 160
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 201
def transpose(lines)
  lines = Array(lines)
  first_line = lines.shift
  first_line.zip(*lines)
end