Permalink
Browse files

Merge pull request #14 from rrrene/master

Add Style class for width, borders and padding of cells
  • Loading branch information...
2 parents 87c4178 + 20c81f1 commit 66208ef27534ed5581ac4009f017329f1469c6c2 @scottjg scottjg committed Oct 19, 2011
View
@@ -6,6 +6,7 @@
puts
t = table ['a', 'b']
+t.style = {:padding_left => 2, :width => 80}
t << [1, 2]
t << [3, 4]
t << :separator
@@ -24,7 +25,7 @@
puts
user_table = table do |v|
- v.width = 80
+ v.style.width = 80
v.headings = 'First Name', 'Last Name', 'Email'
v << %w( TJ Holowaychuk tj@vision-media.ca )
v << %w( Bob Someone bob@vision-media.ca )
View
@@ -22,6 +22,6 @@
#++
$:.unshift File.dirname(__FILE__)
-%w(version core_ext table cell row table_helper).each do |file|
+%w(version core_ext table cell row style table_helper).each do |file|
require "terminal-table/#{file}"
end
@@ -56,7 +56,9 @@ def lines
# Render the cell.
def render(line = 0)
- " #{lines[line]} ".align(alignment, width + 2)
+ left = " " * @table.style.padding_left
+ right = " " * @table.style.padding_right
+ "#{left}#{lines[line]}#{right}".align(alignment, width + @table.cell_padding)
end
alias :to_s :render
@@ -75,7 +77,7 @@ def value_for_column_width_recalc
# Returns the width of this cell
def width
- padding = (colspan - 1) * (2 + @table.class::Y.length)
+ padding = (colspan - 1) * @table.cell_spacing
inner_width = (1..@colspan).to_a.inject(0) do |w, counter|
w + @table.column_width(@index + counter - 1)
end
@@ -53,7 +53,7 @@ def method_missing m, *args, &block
end
def render
- y = Terminal::Table::Y
+ y = @table.style.border_y
if separator?
@table.separator
else
@@ -0,0 +1,60 @@
+
+module Terminal
+ class Table
+ # A Style object holds all the formatting information for a Table object
+ #
+ # To create a table with a certain style, use either the constructor
+ # option <tt>:style</tt>, the Table#style object or the Table#style= method
+ #
+ # All these examples have the same effect:
+ #
+ # # by constructor
+ # @table = Table.new(:style => {:padding_left => 2, :width => 40})
+ #
+ # # by object
+ # @table.style.padding_left = 2
+ # @table.style.width = 40
+ #
+ # # by method
+ # @table.style = {:padding_left => 2, :width => 40}
+ #
+ # To set a default style for all tables created afterwards use Style.defaults=
+ #
+ # Terminal::Table::Style.defaults = {:width => 80}
+ #
+ class Style
+ @@defaults = {
+ :border_x => "-", :border_y => "|", :border_i => "+",
+ :padding_left => 1, :padding_right => 1
+ }
+
+ attr_accessor :border_x
+ attr_accessor :border_y
+ attr_accessor :border_i
+
+ attr_accessor :padding_left
+ attr_accessor :padding_right
+
+ attr_accessor :width
+
+
+ def initialize options = {}
+ apply self.class.defaults.merge(options)
+ end
+
+ def apply options
+ options.each { |m, v| __send__ "#{m}=", v }
+ end
+
+ class << self
+ def defaults
+ @@defaults
+ end
+
+ def defaults= options
+ @@defaults = defaults.merge(options)
+ end
+ end
+ end
+ end
+end
@@ -2,30 +2,18 @@
module Terminal
class Table
- #--
- # Exceptions
- #++
-
- Error = Class.new StandardError
-
- ##
- # Table characters, x axis, y axis, and intersection.
-
- X, Y, I = '-', '|', '+'
-
attr_reader :title
attr_reader :headings
- attr_accessor :width
##
# Generates a ASCII table with the given _options_.
def initialize options = {}, &block
@column_widths = []
+ self.style = options.fetch :style, {}
+ self.title = options.fetch :title, nil
self.headings = options.fetch :headings, []
- @rows = []
- @width = options[:width]
- options.fetch(:rows, []).each { |row| add_row row }
+ self.rows = options.fetch :rows, []
yield_or_eval(&block) if block
end
@@ -55,7 +43,15 @@ def add_row array
def add_separator
self << :separator
end
-
+
+ def cell_spacing
+ cell_padding + style.border_y.length
+ end
+
+ def cell_padding
+ style.padding_left + style.padding_right
+ end
+
##
# Return column _n_.
@@ -93,11 +89,7 @@ def column_width n
# Return total number of columns available.
def number_of_columns
- if rows.empty?
- raise Error, 'your table needs some rows'
- else
- rows.map { |r| r.size }.max
- end
+ headings_with_rows.map { |r| r.size }.max
end
##
@@ -139,6 +131,7 @@ def rows
end
def rows= array
+ @rows = []
array.each { |arr| self << arr }
end
@@ -147,12 +140,20 @@ def rows= array
def separator
@separator ||= begin
- I + (0...number_of_columns).to_a.map do |i|
- X * (column_width(i) + 2)
- end.join(I) + I
+ style.border_i + (0...number_of_columns).to_a.map do |i|
+ style.border_x * (column_width(i) + cell_padding)
+ end.join(style.border_i) + style.border_i
end
end
+ def style=(options)
+ style.apply options
+ end
+
+ def style
+ @style ||= Style.new
+ end
+
def title=(title)
@title = title
recalc_column_widths Row.new(self, [title])
@@ -171,12 +172,12 @@ def == other
private
def columns_width
- @column_widths.inject(0) { |s, i| s + i + 2 + Y.length } + Y.length
+ @column_widths.inject(0) { |s, i| s + i + cell_spacing } + style.border_y.length
end
def additional_column_widths
- return [] if @width.nil?
- spacing = @width - columns_width
+ return [] if style.width.nil?
+ spacing = style.width - columns_width
if spacing < 0
raise "Table width exceeds wanted width of #{wanted} characters."
else
@@ -197,7 +198,7 @@ def recalc_column_widths row
colspan.downto(1) do |j|
cell_length = cell_value.to_s.length
if colspan > 1
- spacing_length = (2 + Y.length) * (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
View
@@ -20,6 +20,14 @@ class String; include Term::ANSIColor; end
cell.alignment.should == :center
end
+ it "should allow :left, :right and :center for alignment" do
+ @cell = Cell.new :value => 'foo', :table => Terminal::Table.new, :index => 0
+ @cell.alignment = :left
+ @cell.alignment = :right
+ @cell.alignment = :center
+ lambda { @cell.alignment = "foo" }.should raise_error
+ end
+
it "should allow multiline content" do
cell = Cell.new :value => "foo\nbarrissimo", :table => Terminal::Table.new, :index => 0
cell.value.should == "foo\nbarrissimo"
@@ -34,5 +42,13 @@ class String; include Term::ANSIColor; end
cell.value_for_column_width_recalc.should == 'foo'
cell.render.should == " \e[31mfoo\e[0m "
end
+
+ it "should render padding properly" do
+ @table = Terminal::Table.new(:rows => [['foo', '2'], ['3', '4']], :style => {:padding_right => 3})
+ cell = @table.rows.first.cells.first
+ cell.value.should == 'foo'
+ cell.alignment.should == :left
+ cell.render.should == " foo "
+ end
end
View
@@ -95,8 +95,11 @@ module Terminal
@table.rows.size.should == 2
end
- it "should bitch and complain when you have no rows" do
- lambda { @table.render }.should raise_error(Terminal::Table::Error)
+ it "should render an empty table properly" do
+ @table.render.should == <<-EOF.deindent
+ ++
+ ++
+ EOF
end
it "should render properly" do
@@ -115,12 +118,30 @@ module Terminal
EOF
end
+ it "should render styles properly" do
+ @table.headings = ['Char', 'Num']
+ @table.style = {:border_x => "=", :border_y => ":", :border_i => "x", :padding_left => 0, :padding_right => 2}
+ @table << ['a', 1]
+ @table << ['b', 2]
+ @table << ['c', 3]
+ @table.style.padding_right.should == 2
+ @table.render.should == <<-EOF.deindent
+ x======x=====x
+ :Char :Num :
+ x======x=====x
+ :a :1 :
+ :b :2 :
+ :c :3 :
+ x======x=====x
+ EOF
+ end
+
it "should render width properly" do
@table.headings = ['Char', 'Num']
@table << ['a', 1]
@table << ['b', 2]
@table << ['c', 3]
- @table.width = 21
+ @table.style.width = 21
@table.render.should == <<-EOF.deindent
+---------+---------+
| Char | Num |
@@ -466,10 +487,8 @@ module Terminal
end
it "should render a table with only X cell borders" do
- Terminal::Table::X = "-"
- Terminal::Table::Y = ""
- Terminal::Table::I = ""
-
+ @table.style = {:border_x => "-", :border_y => "", :border_i => ""}
+
@table.headings = ['name', { :value => 'values', :alignment => :right, :colspan => 3}]
@table.headings = ['name', { :value => 'values', :colspan => 3}]
@table.rows = [['a', 1, 2, 3], ['b', 4, 5, 6], ['c', 7, 8, 9]]
@@ -483,16 +502,10 @@ module Terminal
c 7 8 9
---------------
EOF
-
- Terminal::Table::X = "-"
- Terminal::Table::Y = "|"
- Terminal::Table::I = "+"
end
it "should render a table without cell borders" do
- Terminal::Table::X = ""
- Terminal::Table::Y = ""
- Terminal::Table::I = ""
+ @table.style = {:border_x => "", :border_y => "", :border_i => ""}
@table.headings = ['name', { :value => 'values', :alignment => :right, :colspan => 3}]
@table.headings = ['name', { :value => 'values', :colspan => 3}]
@@ -506,10 +519,6 @@ module Terminal
b 4 5 6
c 7 8 9
EOF
-
- Terminal::Table::X = "-"
- Terminal::Table::Y = "|"
- Terminal::Table::I = "+"
end
end
end

0 comments on commit 66208ef

Please sign in to comment.