Class: TableGen

Inherits:
Object
  • Object
show all
Defined in:
lib/tablegen.rb,
lib/tablegen/version.rb

Overview

TableGen is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Defined Under Namespace

Classes: Column, Error, Header, Line, WidthError

Constant Summary collapse

VERSION =
"0.1"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTableGen

Returns a new instance of TableGen.



32
33
34
35
36
37
# File 'lib/tablegen.rb', line 32

def initialize
  @border = "\x20"
  @columns = []
  @lines = []
  @collapsed = []
end

Instance Attribute Details

#borderString

The column separator. May be of any length. Defaults to a space.

Returns:

  • (String)


29
30
31
# File 'lib/tablegen.rb', line 29

def border
  @border
end

#heightFixnum (readonly)

Note:

Does not calculate wrapped text lines. If required, use #real_height instead.

The minimum height (in lines) of the table.

Returns:

  • (Fixnum)

See Also:



188
189
190
# File 'lib/tablegen.rb', line 188

def height
  @lines.count
end

#widthFixnum

The maximum width (in characters) of the table. If unspecified (nil), returns the space required to display every row and header.

Examples:

Fit the table in the terminal

if STDOUT.tty?
  table.width = STDOUT.winsize[1]
end

Returns:

  • (Fixnum)

See Also:



160
161
162
163
164
165
166
167
168
169
170
# File 'lib/tablegen.rb', line 160

def width
  return @width unless @width.nil?

  width = 0
  rows.each {|row|
    format = format_row row.data
    length = real_length format
    width = [width, length].max
  }
  width
end

Instance Method Details

#clearObject

Empty the table. Columns settings are conserved.

See Also:



137
138
139
# File 'lib/tablegen.rb', line 137

def clear
  @lines.clear
end

#clear!Object

Empty the table AND delete the columns.

See Also:



144
145
146
147
# File 'lib/tablegen.rb', line 144

def clear!
  clear
  @columns.clear
end

#column(index) {|Column column| ... } ⇒ Column

Yields and returns the column at the specified index.

Examples:

Change the alignment of the first column

table.column 0 do |col|
  col.alignment = :right
end

Parameters:

  • index (Fixnum)

Yields:

Returns:

  • (Column)

    the requested column

See Also:



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tablegen.rb', line 52

def column(index)
  unless col = @columns[index]
    if @columns.count < index
      # create columns so the holes are not filled with nil
      (@columns.count..index).each {|i| column i }
    end

    col = Column.new index
    @columns[index] = col
  end

  yield col if block_given?
  col
end

#columns(*indexes) {|Column column| ... } ⇒ Object

Shorthand to #column: Yields specified columns.

Examples:

Allow columns 6 and 8 to be collapsed

table.columns 6, 8 do |col|
  col.collapse = true
end

Parameters:

  • indexes (Array<Fixnum>)

Yields:

See Also:



79
80
81
82
83
# File 'lib/tablegen.rb', line 79

def columns(*indexes, &block)
  indexes.each {|index|
    column index, &block
  }
end

#header(*fields) ⇒ Object

Add a header row to the table. The fields are not formatted.

Examples:

table.header 'Product Name', 'Quantity', 'Price'

Parameters:

  • fields (Array<String>)

Raises:

  • (ArgumentError)

    at least one field is required

See Also:



115
116
117
# File 'lib/tablegen.rb', line 115

def header(*fields)
  row *fields.map {|name| Header.new name }
end

#real_heightFixnum

Calculates the exact height (in lines) of the table.

Returns:

  • (Fixnum)

See Also:



197
198
199
# File 'lib/tablegen.rb', line 197

def real_height
  to_s.lines.count
end

#real_widthFixnum

Calculates the exact width (in characters) of the entire table.

Returns:

  • (Fixnum)

See Also:



177
178
179
# File 'lib/tablegen.rb', line 177

def real_width
  to_s.each_line.map {|l| real_length l.chomp }.max || 0
end

#row(*fields) ⇒ Object

Add a row to the table. The fields are formatted with TableGen::Column#format.

Examples:

table.column 2 do |col|
  col.format = proc {|price|
    "$%.2f" % price
  }
end

# Product Name, Quantity, Price
table.row 'Table Generator', 42, 0

Parameters:

  • fields (Array<Object>)

Raises:

  • (ArgumentError)

    at least one field is required

See Also:



101
102
103
104
# File 'lib/tablegen.rb', line 101

def row(*fields)
  raise ArgumentError, 'wrong number of arguments (0 for 1+)' if fields.empty?
  @lines << Line.new(:row, fields)
end

#separator(char = '=') ⇒ Object

Add a separator to the table.

Parameters:

  • char (String) (defaults to: '=')

    the character to repeat



122
123
124
# File 'lib/tablegen.rb', line 122

def separator(char = '=')
  @lines << Line.new(:separator, char)
end

#text(line) ⇒ Object

Add a text line to the table. The text is wrapped automatically to fit into the table.

Parameters:

  • line (String)


130
131
132
# File 'lib/tablegen.rb', line 130

def text(line)
  @lines << Line.new(:text, line)
end

#to_sString

Generate the table.

begin
  puts table
rescue TableGen::WidthError
  puts 'Terminal is too small'
end

Returns:

  • (String)

    the table

Raises:

  • (WidthError)

    if the table is too large to fit in the #width constraint

  • (Error)

    if something is wrong (eg. invalid column alignment)



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/tablegen.rb', line 212

def to_s
  create_columns

  table = ''
  @collapsed.clear

  loop do
    table, missing_width = generate_table
    break if missing_width == 0

    candidates = []
    @columns.each_with_index {|col, index|
      if col.collapse && !@collapsed.include?(index)
        candidates << index
      end
    }

    if candidates.empty?
      raise WidthError, "insufficient width to generate the table"
    end

    @collapsed << candidates.min_by {|index|
      (column_width(index, false) - missing_width).abs
    }
  end

  table
end