class Terminal::Table

Constants

VERSION

Attributes

headings[R]
title[R]

Public Class Methods

new(options = {}) click to toggle source

Generates a ASCII table with the given options.

# File lib/terminal-table/lib/terminal-table/table.rb, line 11
def initialize options = {}, &block
  @column_widths = []
  self.style = options.fetch :style, {}
  self.headings = options.fetch :headings, []
  self.rows = options.fetch :rows, []
  self.title = options.fetch :title, nil
  yield_or_eval(&block) if block
end

Public Instance Methods

<<(array)
Alias for: add_row
==(other) click to toggle source

Check if other is equal to self. other is considered equal if it contains the same headings and rows.

# File lib/terminal-table/lib/terminal-table/table.rb, line 154
def == other
  if other.respond_to? :render and other.respond_to? :rows
    self.headings == other.headings and self.rows == other.rows
  end
end
add_row(array) click to toggle source

Add a row.

# File lib/terminal-table/lib/terminal-table/table.rb, line 34
def add_row array
  row = array == :separator ? Separator.new(self) : Row.new(self, array)
  @rows << row
  recalc_column_widths row
end
Also aliased as: <<
add_separator() click to toggle source

Add a separator.

# File lib/terminal-table/lib/terminal-table/table.rb, line 44
def add_separator
  self << :separator
end
align_column(n, alignment) click to toggle source

Align column n to the given alignment of :center, :left, or :right.

# File lib/terminal-table/lib/terminal-table/table.rb, line 23
def align_column n, alignment
  r = rows
  column(n).each_with_index do |col, i|
    cell = r[i][n]
    cell.alignment = alignment unless cell.alignment?
  end
end
cell_padding() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 52
def cell_padding
  style.padding_left + style.padding_right
end
cell_spacing() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 48
def cell_spacing
  cell_padding + style.border_y.length
end
column(n, method = :value, array = rows) click to toggle source

Return column n.

# File lib/terminal-table/lib/terminal-table/table.rb, line 59
def column n, method = :value, array = rows
  array.map { |row| 
    cell = row[n]
    cell && method ? cell.__send__(method) : cell
  }.compact 
end
column_width(n) click to toggle source

Return length of column n.

# File lib/terminal-table/lib/terminal-table/table.rb, line 83
def column_width n
  width = @column_widths[n] || 0
  width + additional_column_widths[n].to_i
end
Also aliased as: length_of_column
column_with_headings(n, method = :value) click to toggle source

Return n column including headings.

# File lib/terminal-table/lib/terminal-table/table.rb, line 69
def column_with_headings n, method = :value
  column n, method, headings_with_rows
end
columns() click to toggle source

Return columns.

# File lib/terminal-table/lib/terminal-table/table.rb, line 76
def columns
  (0...number_of_columns).map { |n| column n } 
end
headings=(array) click to toggle source

Set the headings

# File lib/terminal-table/lib/terminal-table/table.rb, line 99
def headings= array
  @headings = Row.new(self, array)
  recalc_column_widths @headings
end
length_of_column(n)
Alias for: column_width
number_of_columns() click to toggle source

Return total number of columns available.

# File lib/terminal-table/lib/terminal-table/table.rb, line 92
def number_of_columns
  headings_with_rows.map { |r| r.cells.size }.max
end
render() click to toggle source

Render the table.

# File lib/terminal-table/lib/terminal-table/table.rb, line 107
def render
  adjust_widths
  separator = Separator.new(self)
  buffer = [separator]
  unless @title.nil?
    buffer << Row.new(self, [title_cell_options])
    buffer << separator
  end
  unless @headings.cells.empty?
    buffer << @headings
    buffer << separator
  end
  buffer += @rows
  buffer << separator
  buffer.map { |r| r.render }.join("\n")
end
Also aliased as: to_s
rows() click to toggle source

Return rows without separator rows.

# File lib/terminal-table/lib/terminal-table/table.rb, line 128
def rows
  @rows.reject { |row| row.is_a? Separator }
end
rows=(array) click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 132
def rows= array
  @rows = []
  array.each { |arr| self << arr }
end
style() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 141
def style
  @style ||= Style.new
end
style=(options) click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 137
def style=(options)
  style.apply options
end
title=(title) click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 145
def title=(title)
  @title = title
  recalc_column_widths Row.new(self, [title_cell_options])
end
to_s()
Alias for: render

Private Instance Methods

additional_column_widths() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 206
def additional_column_widths
  return [] if style.width.nil?
  spacing = style.width - columns_width
  if spacing < 0
    raise "Table width exceeds wanted width of #{style.width} characters."
  else
    per_col = spacing / number_of_columns
    arr = (1...number_of_columns).to_a.map { |i| per_col }
    other_cols = arr.inject(0) { |s, i| s + i }
    arr << spacing - other_cols
    arr
  end
end
adjust_widths() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 172
  def adjust_widths
    return if style.wrap == false or style.width.nil? or style.width > columns_width

    # Make a column index to column size mapping, then sort it
    current_index = -1
    total_column_widths = @column_widths.map { |s| current_index +=1; [current_index, s + cell_spacing] }
    total_column_widths = total_column_widths.sort_by { |a,b| b }

    packed_length = 0
    current_index = 0
    # Pack the smallest first, but make sure the remaining space is enough for
    # the rest of the columns to have at least style.wrap_minimum_width spaces
    # to wrap into.
    while (style.width - (packed_length + total_column_widths[current_index][1] + style.border_y.length)) >
          (style.wrap_minimum_width * (total_column_widths.size - current_index - 1)) do
      packed_length += total_column_widths[current_index][1]
      current_index += 1
    end

    # Calculate the remaining space and figure out how big to wrap the other columns to
    remaining_space = style.width - packed_length - style.border_y.length
    trim_to = (remaining_space / (total_column_widths.size - current_index)) - cell_spacing
    trim_to -= (1 + style.padding_left + style.padding_right)
    if trim_to < 1
      raise "Cannot fit a #{total_column_widths.size} column table in width #{style.width}."
    end

    # The remaining columns are then wrapped
    (current_index...total_column_widths.size).each do |i|
      wrap_column(total_column_widths[i][0], trim_to)
      @column_widths[total_column_widths[i][0]] = trim_to + cell_spacing
    end
  end

  def additional_column_widths
    return [] if style.width.nil?
    spacing = style.width - columns_width
    if spacing < 0
      raise "Table width exceeds wanted width of #{style.width} characters."
    else
      per_col = spacing / number_of_columns
      arr = (1...number_of_columns).to_a.map { |i| per_col }
      other_cols = arr.inject(0) { |s, i| s + i }
      arr << spacing - other_cols
      arr
    end
  end

  def recalc_column_widths row
    return if row.is_a? Separator
    i = 0
    row.cells.each do |cell|
      colspan = cell.colspan
      cell_value = cell.value_for_column_width_recalc
      colspan.downto(1) do |j|
        cell_length = cell_value.to_s.length
        if colspan > 1
          spacing_length = cell_spacing * (colspan - 1)
          length_in_columns = (cell_length - spacing_length)
          cell_length = (length_in_columns.to_f / colspan).ceil
        end
        if @column_widths[i].to_i < cell_length
          @column_widths[i] = cell_length
        end
        i = i + 1
      end
    end
  end
  
  ##
  # Return headings combined with rows.
  
  def headings_with_rows
    [@headings] + rows
  end
  
  def yield_or_eval &block
    return unless block
    if block.arity > 0
      yield self
    else
      self.instance_eval(&block)
    end
  end

  def title_cell_options
    {:value => @title, :alignment => :center, :colspan => number_of_columns}
  end
end
columns_width() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 162
def columns_width
  @column_widths.inject(0) { |s, i| s + i + cell_spacing } + style.border_y.length
end
headings_with_rows() click to toggle source

Return headings combined with rows.

# File lib/terminal-table/lib/terminal-table/table.rb, line 244
def headings_with_rows
  [@headings] + rows
end
recalc_column_widths(row) click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 220
def recalc_column_widths row
  return if row.is_a? Separator
  i = 0
  row.cells.each do |cell|
    colspan = cell.colspan
    cell_value = cell.value_for_column_width_recalc
    colspan.downto(1) do |j|
      cell_length = cell_value.to_s.length
      if colspan > 1
        spacing_length = cell_spacing * (colspan - 1)
        length_in_columns = (cell_length - spacing_length)
        cell_length = (length_in_columns.to_f / colspan).ceil
      end
      if @column_widths[i].to_i < cell_length
        @column_widths[i] = cell_length
      end
      i = i + 1
    end
  end
end
title_cell_options() click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 257
def title_cell_options
  {:value => @title, :alignment => :center, :colspan => number_of_columns}
end
wrap_column(index, new_width) click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 166
def wrap_column(index, new_width)
  @rows.each do |row|
    row.wrap_cell(index, new_width)
  end
end
yield_or_eval() { |self| ... } click to toggle source
# File lib/terminal-table/lib/terminal-table/table.rb, line 248
def yield_or_eval &block
  return unless block
  if block.arity > 0
    yield self
  else
    self.instance_eval(&block)
  end
end