command_line_reporter 1.1.0 → 2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -4,6 +4,9 @@ This gem provides an simple way to add RSpec like formatting of the output of yo
4
4
  eliminates the need to litter your code with *puts* statements instead providing a cleaner, more
5
5
  ruby like way of reporting progress to the user throught the command line interface.
6
6
 
7
+ With the release of Version 2.0, it is now possible to produce tables with and without borders. See
8
+ the section on *Tables* for more examples.
9
+
7
10
  ### Installation
8
11
 
9
12
  It is up on rubygems.org so add it to your bundle or do it the old fashioned way:
@@ -20,7 +23,7 @@ The gem provides a mixin that can be included in your scripts.
20
23
  include CommandLineReporter
21
24
  ```
22
25
 
23
- #### Standard Methods
26
+ ##### Standard Methods
24
27
 
25
28
  There are several methods the mixin provides that do not depend on the formatter used:
26
29
 
@@ -58,6 +61,18 @@ There are several methods the mixin provides that do not depend on the formatter
58
61
  * _text_ - String to display
59
62
  * _:align_ - 'left'|'right'|'center' align the string text. _Default: 'left'_
60
63
  * _:width_ - The width in characters of the string text. _Default: 100_
64
+ * _table(hash) {block}_
65
+ * The first argument is a hash that defines properties of the table.
66
+ * _:border_ - true|false indicates whether to include borders around the table cells
67
+ * The second argument is a block which includes calls the to the _row_ method
68
+ * _row {block}_
69
+ * Only argument is a block with calls to _column_ allowed
70
+ * _column(string, hash)_
71
+ * _text_ - String to display in the table cell
72
+ * _options_ - The options to define the column
73
+ * :width - defines the width of the column
74
+ * :padding - The number of spaces to put on both the left and right of the text.
75
+ * :align - Allowed values are left|right|center
61
76
 
62
77
  ### Progress Formatter
63
78
 
@@ -228,7 +243,108 @@ report(:message => 'running', :complete => 'finished', :type => 'inline', :inden
228
243
  end
229
244
  ```
230
245
 
246
+ ### Tables
247
+
248
+ Examples are always helpful so let's look at the following:
249
+
250
+ ```ruby
251
+ require 'command_line_reporter'
252
+
253
+ class Example
254
+ include CommandLineReporter
255
+
256
+ def run
257
+ table(:border => true) do
258
+ row do
259
+ column('NAME', :width => 20)
260
+ column('ADDRESS', :width => 30, :align => 'right', :padding => 5)
261
+ column('CITY', :width => 15)
262
+ end
263
+ row do
264
+ column('Ceaser')
265
+ column('1 Appian Way')
266
+ column('Rome')
267
+ end
268
+ row do
269
+ column('Richard Feynman')
270
+ column('1 Golden Gate')
271
+ column('Quantum Field')
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+ Example.new.run
278
+ ```
279
+
280
+ This produces the very simple output with 2 rows and 3 columns of data:
281
+
282
+ ```bash
283
+ +----------------------+--------------------------------+-----------------+
284
+ | NAME | ADDRESS | CITY |
285
+ +----------------------+--------------------------------+-----------------+
286
+ | Ceaser | 1 Appian Way | Rome |
287
+ +----------------------+--------------------------------+-----------------+
288
+ | Richard Feynman | 1 Golden Gate | Quantum Field |
289
+ +----------------------+--------------------------------+-----------------+
290
+ ```
291
+
292
+ Notice how the properties of the columns for the second and third rows have been inherited from the
293
+ first like in HTML. This makes it a lot easier to write in freeform. What if you have data to
294
+ iterate over and have text that is wider than the column width you have selected? Not a problem as
295
+ the following example demonstrates all of the combinations of the various options:
296
+
297
+ ```ruby
298
+ require 'command_line_reporter'
299
+
300
+ class Example
301
+ include CommandLineReporter
302
+
303
+ def run
304
+ table(:border => true) do
305
+ 3.times do
306
+ row do
307
+ i = 0
308
+ 3.times do
309
+ i += 10
310
+ column('x' * (0 + rand(50)), :align => %w[left right center][rand(3)], :width => i, :padding => rand(5))
311
+ end
312
+ end
313
+ end
314
+ end
315
+ end
316
+ end
317
+ ```
318
+
319
+ This randomly produces a table with a border that has 3 rows and 3 columns. Each column gets wider
320
+ by 10 characters. The alignment of the column is demonstrated and you can see where some data
321
+ elements have padding around them.
322
+
323
+ ```bash
324
+ +------------+----------------------+--------------------------------+
325
+ | xxxxxxxxxx | xxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxx |
326
+ | xxxxxx | xxxxxxxxx | xxxxxx |
327
+ +------------+----------------------+--------------------------------+
328
+ | xxxxxxxxxx | xxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxx |
329
+ | xxxxxxxxxx | xxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxx |
330
+ | xxxxxxxxxx | xxxxxxxxxxxxxx | |
331
+ | xxxxxxx | xxxx | |
332
+ +------------+----------------------+--------------------------------+
333
+ | xxxxxxxxxx | xxxx | xxxxxxxxxxxxxxxxxxx |
334
+ | xxxxxx | | |
335
+ +------------+----------------------+--------------------------------+
336
+ ```
337
+
338
+ This is all generated randomly to illustrate the features but you get the idea of how to use
339
+ alignment, width and padding.
340
+
341
+ The best feature is *wrapping*. If the text you are display in a cell is larger than the width it
342
+ was given, it will automatically wrap it for you. Padding and alignment are preserved. It palso
343
+ properly handles the case where the data in one cell causes the wrapping but other cells my not have
344
+ the same number of lines to wrap.
345
+
231
346
  ### To Do
232
347
 
233
- 1. Add the progress method to the top level mixin so that there is no need to invoke through the
234
- formatter.
348
+ * Add the ability for a column to span across others
349
+ * Add the progress method to the top level mixin so that there is no need to invoke through the
350
+ formatter.
data/examples/table.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'command_line_reporter'
2
+
3
+ class Example
4
+ include CommandLineReporter
5
+
6
+ def run
7
+ header(:title => 'TABLE EXAMPLES - Borders, Wrapping, Alignment and Padding', :align => 'center', :width => 70)
8
+
9
+ 2.times do |j|
10
+ header(:title => "Table #{j}", :align => 'center', :width => 65)
11
+
12
+ table(:border => j % 2 == 0) do
13
+ 3.times do
14
+ row do
15
+ i = 0
16
+ 3.times do
17
+ i += 10
18
+ column('x' * (0 + rand(50)), :align => %w[left right center][rand(3)], :width => i, :padding => rand(5))
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ vertical_spacing(2)
25
+ end
26
+
27
+ header(:title => 'A simple example of how column properties are inhereted from the first row')
28
+
29
+ table(:border => true) do
30
+ row do
31
+ column('NAME', :width => 20)
32
+ column('ADDRESS', :width => 30, :align => 'right', :padding => 5)
33
+ column('CITY', :width => 15)
34
+ end
35
+ row do
36
+ column('Ceaser')
37
+ column('1 Appian Way')
38
+ column('Rome')
39
+ end
40
+ row do
41
+ column('Richard Feynman')
42
+ column('1 Golden Gate')
43
+ column('Quantum Field')
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ Example.new.run
data/lib/column.rb ADDED
@@ -0,0 +1,52 @@
1
+ require 'options_validator'
2
+
3
+ class Column
4
+ include OptionsValidator
5
+
6
+ VALID_OPTIONS = [:width, :padding, :align]
7
+ attr_accessor :text, :size, *VALID_OPTIONS
8
+
9
+ def initialize(text = nil, options = {})
10
+ self.validate_options(options, *VALID_OPTIONS)
11
+
12
+ self.text = text
13
+
14
+ self.width = options[:width] || 10
15
+ self.align = options[:align] || 'left'
16
+ self.padding = options[:padding] || 0
17
+
18
+ raise ArgumentError unless self.width > 0
19
+ raise ArgumentError unless self.padding.to_s.match(/^\d+$/)
20
+
21
+ self.size = self.width - 2 * self.padding
22
+
23
+ # self.freeze
24
+ end
25
+
26
+ def screen_rows
27
+ if self.text.nil? || self.text.empty?
28
+ [' ' * self.width]
29
+ else
30
+ self.text.scan(/.{1,#{self.size}}/m).map {|s| to_cell(s)}
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def to_cell(str)
37
+ cell = if str.empty?
38
+ ' ' * self.size
39
+ else
40
+ case self.align
41
+ when 'left'
42
+ str.ljust(self.size)
43
+ when 'right'
44
+ str.rjust(self.size)
45
+ when 'center'
46
+ str.ljust((self.size - str.size)/2.0 + str.size).rjust(self.size)
47
+ end
48
+ end
49
+
50
+ ' ' * self.padding + cell + ' ' * self.padding
51
+ end
52
+ end
@@ -1,6 +1,10 @@
1
+ require 'table'
2
+
1
3
  Dir[File.join(File.dirname(__FILE__), '*_formatter.rb')].each {|r| require r}
2
4
 
3
5
  module CommandLineReporter
6
+ include OptionsValidator
7
+
4
8
  attr_reader :formatter
5
9
 
6
10
  DEFAULTS = {
@@ -23,10 +27,8 @@ module CommandLineReporter
23
27
  end
24
28
 
25
29
  def report(options = {}, &block)
30
+ self.formatter ||= 'nested'
26
31
  self.formatter.format(options, block)
27
- rescue NoMethodError
28
- self.formatter = 'nested'
29
- retry
30
32
  end
31
33
 
32
34
  def footer(options = {})
@@ -80,12 +82,25 @@ module CommandLineReporter
80
82
  end
81
83
  end
82
84
 
83
- private
85
+ def table(options = {})
86
+ @table = Table.new(options)
87
+ yield
88
+ @table.to_s
89
+ end
84
90
 
85
- def validate_options(options, *allowed_keys)
86
- raise ArgumentError unless (options.keys - allowed_keys).empty?
91
+ def row(options = {})
92
+ @row = Row.new
93
+ yield
94
+ @table.add(@row)
87
95
  end
88
96
 
97
+ def column(text, options = {})
98
+ col = Column.new(text, options)
99
+ @row.add(col)
100
+ end
101
+
102
+ private
103
+
89
104
  def section(type, options)
90
105
  validate_options(options, :title, :width, :align, :spacing, :timestamp, :rule)
91
106
 
@@ -0,0 +1,5 @@
1
+ module OptionsValidator
2
+ def validate_options(provided, *allowed_keys)
3
+ raise(ArgumentError, "Valid options: #{allowed_keys}") unless (provided.keys - allowed_keys).empty?
4
+ end
5
+ end
data/lib/row.rb ADDED
@@ -0,0 +1,60 @@
1
+ require 'column'
2
+ require 'forwardable'
3
+
4
+ class Row
5
+ extend Forwardable
6
+
7
+ attr_accessor :columns, :border
8
+
9
+ def initialize(options = {})
10
+ self.columns = []
11
+ self.border = false
12
+ end
13
+
14
+ def_delegator :@columns, :push, :add
15
+
16
+ def separator
17
+ @sep ||= '+' + self.columns.map {|c| '-' * (c.width + 2)}.join('+') + '+'
18
+ end
19
+
20
+ def to_s
21
+ screen_count.times do |sr|
22
+ line = (self.border) ? '| ' : ''
23
+ self.columns.size.times do |mc|
24
+ col = self.columns[mc]
25
+ # Account for the fact that some columns will have more screen rows than their
26
+ # counterparts in the row. An example being:
27
+ # c1 = Column.new('x' * 50, :width => 10)
28
+ # c2 = Column.new('x' * 20, :width => 10)
29
+ #
30
+ # c1.screen_rows.size == 5
31
+ # c2.screen_rows.size == 2
32
+ #
33
+ # So when we don't have a screen row for c2 we need to fill the screen with the
34
+ # proper number of blanks so the layout looks like (parenthesis on the right just
35
+ # indicate screen row index)
36
+ #
37
+ # +-------------+------------+
38
+ # | xxxxxxxxxxx | xxxxxxxxxx | (0)
39
+ # | xxxxxxxxxxx | xxxxxxxxxx | (1)
40
+ # | xxxxxxxxxxx | | (2)
41
+ # | xxxxxxxxxxx | | (3)
42
+ # | xxxxxxxxxxx | | (4)
43
+ # +-------------+------------+
44
+ if col.screen_rows[sr].nil?
45
+ line << ' ' * col.width
46
+ else
47
+ line << self.columns[mc].screen_rows[sr]
48
+ end
49
+ line << ' ' + ((self.border) ? '| ' : '')
50
+ end
51
+ puts line
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def screen_count
58
+ @sc ||= self.columns.inject(0) {|max,column| column.screen_rows.size > max ? column.screen_rows.size : max}
59
+ end
60
+ end
data/lib/table.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'row'
2
+ require 'options_validator'
3
+
4
+ class Table
5
+ include OptionsValidator
6
+
7
+ VALID_OPTIONS = [:border]
8
+ attr_accessor :rows, *VALID_OPTIONS
9
+
10
+ def initialize(options = {})
11
+ self.validate_options(options, *VALID_OPTIONS)
12
+
13
+ self.border = options[:border] || false
14
+
15
+ @rows = []
16
+ end
17
+
18
+ def add(row)
19
+ # Inheritance from the table
20
+ row.border = self.border
21
+
22
+ # Inherit properties from the first row
23
+ if self.rows[0]
24
+ row.columns.each_with_index do |c,i|
25
+ c.align = self.rows[0].columns[i].align
26
+ c.padding = self.rows[0].columns[i].padding
27
+ c.width = self.rows[0].columns[i].width
28
+ c.size = c.width - 2 * c.padding
29
+ end
30
+ end
31
+
32
+ self.rows << row
33
+ end
34
+
35
+ def to_s
36
+ return if self.rows.size == 0 # we got here with nothing to print to the screen
37
+
38
+ puts self.rows[0].separator if self.border
39
+ self.rows.each do |row|
40
+ row.to_s
41
+ puts self.rows[0].separator if self.border
42
+ end
43
+ end
44
+ end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CommandLineReporter
2
- VERSION = '1.1.0'
2
+ VERSION = '2.0'
3
3
  end
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+ require 'column'
3
+
4
+ describe Column do
5
+ context 'creation' do
6
+ it 'rejects invalid options' do
7
+ expect {
8
+ Column.new('test', :asdf => '1234')
9
+ }.to raise_error ArgumentError
10
+ end
11
+
12
+ it 'defaults options hash' do
13
+ expect {
14
+ Column.new('test')
15
+ }.to_not raise_error
16
+ end
17
+
18
+ it 'defaults the width' do
19
+ Column.new('test').width.should == 10
20
+ end
21
+
22
+ it 'accepts the width' do
23
+ Column.new('test', :width => 50).width.should == 50
24
+ end
25
+
26
+ it 'requires valid width' do
27
+ expect {
28
+ Column.new('test', :width => 'asdf')
29
+ }.to raise_error ArgumentError
30
+ end
31
+
32
+ it 'accepts text' do
33
+ Column.new('asdf').text.should == 'asdf'
34
+ end
35
+
36
+ it 'defaults the padding' do
37
+ Column.new('test').padding.should == 0
38
+ end
39
+
40
+ it 'accepts the padding' do
41
+ Column.new('test', :padding => 5).padding.should == 5
42
+ end
43
+
44
+ it 'requires valid width' do
45
+ expect {
46
+ Column.new('test', :padding => 'asdf')
47
+ }.to raise_error ArgumentError
48
+ end
49
+
50
+ # it 'is immutable' do
51
+ # c = Column.new('test')
52
+
53
+ # expect {
54
+ # c.text = 'asdf'
55
+ # }.to raise_error RuntimeError, /frozen object/
56
+
57
+ # expect {
58
+ # c.width = 123
59
+ # }.to raise_error RuntimeError, /frozen object/
60
+
61
+ # expect {
62
+ # c.padding = 123
63
+ # }.to raise_error RuntimeError, /frozen object/
64
+ # end
65
+ end
66
+
67
+ describe '#screen_rows' do
68
+ context 'no wrapping' do
69
+ context 'no padding' do
70
+ it 'gives a single row' do
71
+ c = Column.new('x' * 5)
72
+ c.screen_rows.size == 1
73
+ end
74
+
75
+ it 'handles empty text' do
76
+ c = Column.new
77
+ c.screen_rows[0].should == ' ' * 10
78
+ end
79
+
80
+ it 'left justifies' do
81
+ c = Column.new('x' * 10, :width => 20)
82
+ c.screen_rows[0].should == 'x' * 10 + ' ' * 10
83
+ end
84
+
85
+ it 'right justifies' do
86
+ c = Column.new('x' * 10, :align => 'right', :width => 20)
87
+ c.screen_rows[0].should == ' ' * 10 + 'x' * 10
88
+ end
89
+
90
+ it 'center justifies' do
91
+ c = Column.new('x' * 10, :align => 'center', :width => 20)
92
+ c.screen_rows[0].should == ' ' * 5 + 'x' * 10 + ' ' * 5
93
+ end
94
+ end
95
+
96
+ context 'accounts for padding' do
97
+ it 'left justifies' do
98
+ c = Column.new('x' * 10, :padding => 5, :width => 30)
99
+ c.screen_rows[0].should == ' ' * 5 + 'x' * 10 + ' ' * 15
100
+ end
101
+ it 'right justifies' do
102
+ c = Column.new('x' * 10, :align => 'right', :padding => 5, :width => 30)
103
+ c.screen_rows[0].should == ' ' * 15 + 'x' * 10 + ' ' * 5
104
+ end
105
+ it 'right justifies' do
106
+ c = Column.new('x' * 10, :align => 'center', :padding => 5, :width => 30)
107
+ c.screen_rows[0].should == ' ' * 10 + 'x' * 10 + ' ' * 10
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'with wrapping' do
113
+ context 'no padding' do
114
+ it 'left justifies' do
115
+ c = Column.new('x' * 25, :width => 10)
116
+ c.screen_rows.should == ['x' * 10, 'x' * 10, 'x' * 5 + ' ' * 5]
117
+ end
118
+
119
+ it 'left justifies' do
120
+ c = Column.new('x' * 25, :align => 'right', :width => 10)
121
+ c.screen_rows.should == ['x' * 10, 'x' * 10, ' ' * 5 + 'x' * 5]
122
+ end
123
+
124
+ it 'left justifies' do
125
+ c = Column.new('x' * 25, :align => 'center', :width => 10)
126
+ c.screen_rows.should == ['x' * 10, 'x' * 10, ' ' * 3 + 'x' * 5 + ' ' * 2]
127
+ end
128
+ end
129
+
130
+ context 'account for padding' do
131
+ it 'left justifies' do
132
+ c = Column.new('x' * 25, :padding => 2, :width => 20)
133
+ c.screen_rows.should == [' ' * 2 + 'x' * 16 + ' ' * 2, ' ' * 2 + 'x' * 9 + ' ' * 9]
134
+ end
135
+
136
+ it 'right justifies' do
137
+ c = Column.new('x' * 25, :padding => 2, :align => 'right', :width => 20)
138
+ c.screen_rows.should == [' ' * 2 + 'x' * 16 + ' ' * 2, ' ' * 9 + 'x' * 9 + ' ' * 2]
139
+ end
140
+
141
+ it 'center justifies' do
142
+ c = Column.new('x' * 25, :padding => 2, :align => 'center', :width => 20)
143
+ c.screen_rows.should == [' ' * 2 + 'x' * 16 + ' ' * 2, ' ' * 6 + 'x' * 9 + ' ' * 5]
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -49,6 +49,14 @@ describe CommandLineReporter do
49
49
 
50
50
  subject.formatter.class.should == CommandLineReporter::ProgressFormatter
51
51
  end
52
+
53
+ it 'does not mask other application errors when a formatter is not set' do
54
+ capture_stdout {
55
+ subject.report {
56
+ lambda {self.some_method_that_does_not_exist}.should raise_error(NoMethodError)
57
+ }
58
+ }
59
+ end
52
60
  end
53
61
 
54
62
  describe '#header' do
@@ -509,4 +517,76 @@ describe CommandLineReporter do
509
517
  end
510
518
  end
511
519
  end
520
+
521
+ describe '#table' do
522
+ it 'instantiates the table class' do
523
+ subject.should_receive(:puts).any_number_of_times
524
+ subject.should_receive(:table).once
525
+ subject.table { }
526
+ # subject.instance_variable_get(:@table).should_not be_nil
527
+ end
528
+
529
+ it 'requires a row to be defined' do
530
+ expect {
531
+ subject.table
532
+ }.to raise_error LocalJumpError
533
+ end
534
+
535
+ it 'accepts valid options' do
536
+ expect {
537
+ subject.table(:border => true) { }
538
+ }.to_not raise_error
539
+ end
540
+
541
+ it 'rejects invalid options' do
542
+ expect {
543
+ subject.table(:asdf => '100') { }
544
+ }.to raise_error ArgumentError
545
+ end
546
+ end
547
+
548
+ describe '#row' do
549
+ it 'instantiates a row class' do
550
+ subject.should_receive(:row).once
551
+ subject.should_receive(:puts).any_number_of_times
552
+
553
+ subject.table do
554
+ subject.row do
555
+ end
556
+ end
557
+ end
558
+ end
559
+
560
+ describe '#column' do
561
+ it 'instantiates multiple columns' do
562
+ subject.should_receive(:column).exactly(3).times
563
+ subject.should_receive(:puts).any_number_of_times
564
+
565
+ subject.table do
566
+ subject.row do
567
+ subject.column('asdf')
568
+ subject.column('qwer')
569
+ subject.column('zxcv')
570
+ end
571
+ end
572
+ end
573
+
574
+ it 'accepts valid options' do
575
+ subject.table do
576
+ subject.row do
577
+ subject.column('asdf', :width => 30)
578
+ end
579
+ end
580
+ end
581
+
582
+ it 'rejects invalid options' do
583
+ expect {
584
+ subject.table do
585
+ subject.row do
586
+ subject.column('asdf', :asdf => 30)
587
+ end
588
+ end
589
+ }.to raise_error ArgumentError
590
+ end
591
+ end
512
592
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'options_validator'
3
+
4
+ describe OptionsValidator do
5
+ subject { Class.new.extend(OptionsValidator) }
6
+
7
+ it 'accepts single key options' do
8
+ expect {
9
+ subject.validate_options({:valid => true}, :valid)
10
+ }.to_not raise_error
11
+ end
12
+
13
+ it 'rejects invalid option hashes' do
14
+ expect {
15
+ subject.validate_options({:wrong => true}, :valid)
16
+ }.to raise_error ArgumentError
17
+ end
18
+
19
+ it 'accepts multi-key options' do
20
+ expect {
21
+ valid = [:valid, :another]
22
+ subject.validate_options({:valid => true, :another => true}, *valid)
23
+ }.to_not raise_error
24
+ end
25
+ end
data/spec/row_spec.rb ADDED
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+ require 'row'
3
+
4
+ describe Row do
5
+ before :each do
6
+ @cols = 10.times.map {|v| Column.new("test#{v}")}
7
+ end
8
+
9
+ describe '#add' do
10
+ subject { Row.new }
11
+
12
+ it 'adds columns' do
13
+ subject.add(@cols[0])
14
+ subject.columns.size.should == 1
15
+ subject.columns[0].should == @cols[0]
16
+ subject.add(@cols[1])
17
+ subject.columns.should == @cols[0,2]
18
+ end
19
+ end
20
+
21
+ describe '#to_s' do
22
+ before :each do
23
+ @cols = [
24
+ Column.new('asdf'),
25
+ Column.new('qwer', :align => 'center'),
26
+ Column.new('zxcv', :align => 'right'),
27
+ Column.new('x' * 25, :align => 'left', :width => 10),
28
+ Column.new('x' * 25, :align => 'center', :width => 10),
29
+ Column.new('x' * 35, :align => 'left', :width => 10),
30
+ ]
31
+ end
32
+
33
+ before :all do
34
+ @one_space = ' '
35
+ @three_spaces = ' {3,3}'
36
+ @six_spaces = ' {6,6}'
37
+ @nine_spaces = ' {9,9}'
38
+ @five_xs = 'x{5,5}'
39
+ @ten_xs = 'x{10,10}'
40
+ end
41
+
42
+ context 'no border' do
43
+ context 'no wrap' do
44
+ it 'prints a single column' do
45
+ subject.add(@cols[0])
46
+ subject.should_receive(:puts).with(/^asdf#{@six_pieces}/)
47
+ subject.to_s
48
+ end
49
+ it 'prints three columns' do
50
+ subject.add(@cols[0])
51
+ subject.add(@cols[1])
52
+ subject.add(@cols[2])
53
+ subject.should_receive(:puts).with(/^asdf#{@six_spaces}#{@one_space}#{@three_spaces}qwer#{@three_spaces}#{@one_space}#{@six_spaces}zxcv $/)
54
+ subject.to_s
55
+ end
56
+ end
57
+
58
+ context 'with wrapping' do
59
+ it 'prints a single column' do
60
+ subject.add(@cols[3])
61
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}$/)
62
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}$/)
63
+ subject.should_receive(:puts).with(/^#{@five_xs}#{@six_spaces}$/)
64
+ subject.to_s
65
+ end
66
+
67
+ it 'prints multiple columns of the same size' do
68
+ subject.add(@cols[3])
69
+ subject.add(@cols[4])
70
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}#{@ten_xs}#{@one_space}$/)
71
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}#{@ten_xs}#{@one_space}$/)
72
+ subject.should_receive(:puts).with(/^#{@five_xs}#{@nine_spaces}#{@five_xs}#{@three_spaces}$/)
73
+ subject.to_s
74
+ end
75
+
76
+ it 'prints multiple columns with different size' do
77
+ subject.add(@cols[5])
78
+ subject.add(@cols[3])
79
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}#{@ten_xs}#{@one_space}$/)
80
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}#{@ten_xs}#{@one_space}$/)
81
+ subject.should_receive(:puts).with(/^#{@ten_xs}#{@one_space}#{@five_xs}#{@six_spaces}$/)
82
+ subject.should_receive(:puts).with(/^#{@five_xs} {5,17}$/)
83
+ subject.to_s
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
2
 
3
+ Dir[File.dirname(__FILE__) + "../lib/*.rb"].each {|f| require f}
3
4
  Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
@@ -0,0 +1,17 @@
1
+ RSpec::Matchers.define :accepts_argument do |expected|
2
+ match do
3
+ expected.call.should raise_exception ArgumentError
4
+ end
5
+
6
+ # failure_message_for_should do |actual|
7
+ # 'should raise an ArgumentError'
8
+ # end
9
+
10
+ # failure_message_for_should_not do |actual|
11
+ # 'should not raise ArgumentError'
12
+ # end
13
+
14
+ # description do
15
+ # 'validates options argument'
16
+ # end
17
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'table'
3
+
4
+ describe Table do
5
+ context 'creation' do
6
+ it 'defaults options hash' do
7
+ expect {
8
+ Table.new
9
+ }.to_not raise_error
10
+ end
11
+
12
+ it 'defaults the border' do
13
+ Table.new.border.should == false
14
+ end
15
+
16
+ it 'accepts the border' do
17
+ Table.new(:border => true).border.should == true
18
+ end
19
+ end
20
+
21
+ context 'rows' do
22
+ it 'allows addition' do
23
+ cols = [Column.new('test1'), Column.new('test2')]
24
+ row = Row.new
25
+ cols.each {|c| row.add(c)}
26
+ expect {
27
+ Table.new.add(row)
28
+ }.to_not raise_error
29
+ end
30
+
31
+ it 'normalizes all column width and sizes' do
32
+ cols = [Column.new('asdf', :width => 5), Column.new('qwer')]
33
+ row = Row.new
34
+ row.add(cols[0])
35
+ t = Table.new
36
+ t.add(row)
37
+ row = Row.new
38
+ row.add(cols[1])
39
+ t.add(row)
40
+ output = capture_stdout {
41
+ t.to_s
42
+ }
43
+ end
44
+ end
45
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: command_line_reporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: '2.0'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-12-01 00:00:00.000000000Z
13
+ date: 2012-01-11 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
17
- requirement: &2151943740 !ruby/object:Gem::Requirement
17
+ requirement: &2152892720 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,7 +22,7 @@ dependencies:
22
22
  version: 1.0.0
23
23
  type: :development
24
24
  prerelease: false
25
- version_requirements: *2151943740
25
+ version_requirements: *2152892720
26
26
  description: This gem makes it easy to provide a report while your ruby script is
27
27
  executing
28
28
  email: baywes@gmail.com
@@ -33,16 +33,26 @@ files:
33
33
  - examples/nested.rb
34
34
  - examples/progress.rb
35
35
  - examples/simple.rb
36
+ - examples/table.rb
37
+ - lib/column.rb
36
38
  - lib/command_line_reporter.rb
37
39
  - lib/nested_formatter.rb
40
+ - lib/options_validator.rb
38
41
  - lib/progress_formatter.rb
42
+ - lib/row.rb
43
+ - lib/table.rb
39
44
  - lib/version.rb
40
45
  - README.md
46
+ - spec/column_spec.rb
41
47
  - spec/command_line_reporter_spec.rb
42
48
  - spec/nested_formatter_spec.rb
49
+ - spec/options_validator_spec.rb
43
50
  - spec/progress_formatter_spec.rb
51
+ - spec/row_spec.rb
44
52
  - spec/spec_helper.rb
45
53
  - spec/support/helpers/stdout.rb
54
+ - spec/support/matchers/argument.rb
55
+ - spec/table_spec.rb
46
56
  homepage: http://github.com/wbailey/command_line_reporter
47
57
  licenses: []
48
58
  post_install_message:
@@ -57,7 +67,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
67
  version: '0'
58
68
  segments:
59
69
  - 0
60
- hash: -846505284794212082
70
+ hash: 3958532185567160349
61
71
  required_rubygems_version: !ruby/object:Gem::Requirement
62
72
  none: false
63
73
  requirements:
@@ -71,8 +81,13 @@ signing_key:
71
81
  specification_version: 3
72
82
  summary: A tool for providing interactive command line applications
73
83
  test_files:
84
+ - spec/column_spec.rb
74
85
  - spec/command_line_reporter_spec.rb
75
86
  - spec/nested_formatter_spec.rb
87
+ - spec/options_validator_spec.rb
76
88
  - spec/progress_formatter_spec.rb
89
+ - spec/row_spec.rb
77
90
  - spec/spec_helper.rb
78
91
  - spec/support/helpers/stdout.rb
92
+ - spec/support/matchers/argument.rb
93
+ - spec/table_spec.rb