tty-table 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/README.md +458 -142
  4. data/lib/tty-table.rb +6 -6
  5. data/lib/tty/table.rb +34 -34
  6. data/lib/tty/table/alignment_set.rb +73 -0
  7. data/lib/tty/table/border.rb +54 -36
  8. data/lib/tty/table/border/null.rb +4 -4
  9. data/lib/tty/table/{columns.rb → column_constraint.rb} +30 -32
  10. data/lib/tty/table/column_set.rb +18 -17
  11. data/lib/tty/table/field.rb +50 -25
  12. data/lib/tty/table/header.rb +6 -2
  13. data/lib/tty/table/indentation.rb +7 -12
  14. data/lib/tty/table/operation/alignment.rb +59 -0
  15. data/lib/tty/table/operation/escape.rb +1 -1
  16. data/lib/tty/table/operation/filter.rb +1 -1
  17. data/lib/tty/table/operation/padding.rb +12 -61
  18. data/lib/tty/table/operation/truncation.rb +2 -2
  19. data/lib/tty/table/operation/wrapped.rb +2 -5
  20. data/lib/tty/table/operations.rb +35 -17
  21. data/lib/tty/table/orientation/vertical.rb +4 -4
  22. data/lib/tty/table/renderer.rb +1 -7
  23. data/lib/tty/table/renderer/basic.rb +69 -63
  24. data/lib/tty/table/version.rb +1 -1
  25. data/spec/spec_helper.rb +3 -4
  26. data/spec/unit/access_spec.rb +8 -8
  27. data/spec/unit/{operation/alignment_set → alignment_set}/each_spec.rb +1 -1
  28. data/spec/unit/{operation/alignment_set → alignment_set}/new_spec.rb +4 -4
  29. data/spec/unit/{operation/alignment_set → alignment_set}/to_ary_spec.rb +1 -1
  30. data/spec/unit/alignment_spec.rb +71 -0
  31. data/spec/unit/border/ascii/rendering_spec.rb +12 -12
  32. data/spec/unit/border/new_spec.rb +2 -2
  33. data/spec/unit/border/null/rendering_spec.rb +2 -2
  34. data/spec/unit/border/unicode/rendering_spec.rb +10 -10
  35. data/spec/unit/{columns → column_constraint}/enforce_spec.rb +15 -12
  36. data/spec/unit/{columns → column_constraint}/widths_spec.rb +6 -6
  37. data/spec/unit/column_set/extract_widths_spec.rb +39 -6
  38. data/spec/unit/data_spec.rb +4 -6
  39. data/spec/unit/each_spec.rb +8 -23
  40. data/spec/unit/each_with_index_spec.rb +27 -33
  41. data/spec/unit/field/length_spec.rb +23 -9
  42. data/spec/unit/field/width_spec.rb +1 -1
  43. data/spec/unit/filter_spec.rb +7 -8
  44. data/spec/unit/header/new_spec.rb +6 -15
  45. data/spec/unit/indentation/indent_spec.rb +21 -0
  46. data/spec/unit/new_spec.rb +73 -0
  47. data/spec/unit/operation/{alignment_set → alignment}/call_spec.rb +1 -1
  48. data/spec/unit/operation/escape/call_spec.rb +2 -3
  49. data/spec/unit/operation/filter/call_spec.rb +2 -3
  50. data/spec/unit/operation/truncation/call_spec.rb +6 -8
  51. data/spec/unit/operation/wrapped/call_spec.rb +15 -8
  52. data/spec/unit/operations/new_spec.rb +1 -1
  53. data/spec/unit/orientation_spec.rb +6 -6
  54. data/spec/unit/padding_spec.rb +29 -32
  55. data/spec/unit/properties_spec.rb +4 -4
  56. data/spec/unit/render_repeat_spec.rb +42 -0
  57. data/spec/unit/render_spec.rb +1 -1
  58. data/spec/unit/render_with_spec.rb +3 -3
  59. data/spec/unit/renderer/ascii/coloring_spec.rb +70 -0
  60. data/spec/unit/renderer/ascii/multiline_spec.rb +101 -0
  61. data/spec/unit/renderer/ascii/padding_spec.rb +37 -10
  62. data/spec/unit/renderer/ascii/render_spec.rb +4 -4
  63. data/spec/unit/renderer/ascii/resizing_spec.rb +22 -22
  64. data/spec/unit/renderer/ascii/separator_spec.rb +1 -1
  65. data/spec/unit/renderer/basic/alignment_spec.rb +20 -20
  66. data/spec/unit/renderer/basic/coloring_spec.rb +43 -28
  67. data/spec/unit/renderer/basic/filter_spec.rb +3 -3
  68. data/spec/unit/renderer/basic/multiline_spec.rb +74 -0
  69. data/spec/unit/renderer/basic/options_spec.rb +9 -9
  70. data/spec/unit/renderer/basic/padding_spec.rb +26 -2
  71. data/spec/unit/renderer/basic/render_spec.rb +4 -4
  72. data/spec/unit/renderer/basic/resizing_spec.rb +18 -18
  73. data/spec/unit/renderer/basic/separator_spec.rb +1 -1
  74. data/spec/unit/renderer/basic/truncation_spec.rb +6 -6
  75. data/spec/unit/renderer/basic/wrapping_spec.rb +3 -3
  76. data/spec/unit/renderer/border_spec.rb +4 -4
  77. data/spec/unit/renderer/unicode/coloring_spec.rb +70 -0
  78. data/spec/unit/renderer/unicode/indentation_spec.rb +1 -1
  79. data/spec/unit/renderer/unicode/padding_spec.rb +26 -26
  80. data/spec/unit/renderer/unicode/render_spec.rb +4 -4
  81. data/spec/unit/renderer/unicode/separator_spec.rb +1 -1
  82. data/spec/unit/to_s_spec.rb +4 -11
  83. data/spec/unit/utf_spec.rb +33 -0
  84. data/tty-table.gemspec +2 -1
  85. metadata +52 -32
  86. data/lib/tty/table/operation/alignment_set.rb +0 -103
  87. data/lib/tty/table/padder.rb +0 -180
  88. data/lib/tty/table/renderer/color.rb +0 -12
  89. data/spec/unit/indentation/insert_indent_spec.rb +0 -27
  90. data/spec/unit/initialize_spec.rb +0 -88
  91. data/spec/unit/padder/parse_spec.rb +0 -45
  92. data/spec/unit/padder/to_s_spec.rb +0 -14
  93. data/spec/unit/renderer/basic/multiline_content_spec.rb +0 -135
  94. data/spec/unit/renderer/style_spec.rb +0 -72
@@ -3,13 +3,46 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Table::ColumnSet, '#extract_widths' do
6
- let(:header) { ['h1', 'h2', 'h3'] }
7
- let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
- let(:table) { TTY::Table.new header, rows }
9
-
10
- subject { described_class.new table }
6
+ let(:color) { Pastel.new(enabled: true) }
11
7
 
12
8
  it 'extract widths' do
13
- expect(subject.extract_widths).to eql([2,2,2])
9
+ header = ['h1', 'h2', 'h3']
10
+ rows = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']]
11
+ table = TTY::Table.new header, rows
12
+ column_set = TTY::Table::ColumnSet.new(table)
13
+ expect(column_set.extract_widths).to eql([2,2,2])
14
+ end
15
+
16
+ it "extracts widths from utf" do
17
+ header = ['h1', 'うなじ']
18
+ rows = [['こんにちは', 'a2'], ['b1','選択']]
19
+ table = TTY::Table.new header, rows
20
+ column_set = TTY::Table::ColumnSet.new(table)
21
+ expect(column_set.extract_widths).to eql([10,6])
22
+ end
23
+
24
+ it "extracts widths from multiline text" do
25
+ table = TTY::Table.new
26
+ table << ["Multi\nLine\nContent", "Text\nthat\nwraps"]
27
+ table << ["Some\nother\ntext", 'Simple']
28
+ column_set = TTY::Table::ColumnSet.new(table)
29
+ expect(column_set.extract_widths).to eq([7,6])
30
+ end
31
+
32
+ it "extracts widths from multiline text" do
33
+ table = TTY::Table.new
34
+ table << ["Multi\\nLine\\nContent", "Text\\nthat\\nwraps"]
35
+ table << ["Some\\nother\\ntext", 'Simple']
36
+ column_set = TTY::Table::ColumnSet.new(table)
37
+ expect(column_set.extract_widths).to eq([20, 17])
38
+ end
39
+
40
+ it "extracts widths from ANSI text" do
41
+ header = [color.green('h1'), 'h2']
42
+ table = TTY::Table.new header: header
43
+ table << [color.green.on_blue('a1'), 'a2']
44
+ table << ['b1', color.red.on_yellow('b2')]
45
+ column_set = TTY::Table::ColumnSet.new(table)
46
+ expect(column_set.extract_widths).to eq([2,2])
14
47
  end
15
48
  end
@@ -2,13 +2,11 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe TTY::Table, '#data' do
6
- let(:header) { ['h1', 'h2', 'h3'] }
7
- let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
-
9
- subject(:table) { described_class.new header, rows }
10
-
5
+ RSpec.describe TTY::Table, '.data' do
11
6
  it 'gets all table data' do
7
+ header = ['h1', 'h2', 'h3']
8
+ rows = [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']]
9
+ table = described_class.new header, rows
12
10
  expect(table.data).to eql([header] + rows)
13
11
  end
14
12
  end
@@ -3,39 +3,24 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Table, '#each' do
6
- let(:table) { described_class.new header, rows }
7
6
  let(:header) { ['Header1'] }
8
7
  let(:rows) { [['a1'], ['b1']] }
9
- let(:field) { TTY::Table::Field }
10
8
 
11
- context 'with no block' do
12
- subject { table.each }
9
+ subject(:table) { described_class.new(header, rows) }
13
10
 
14
- it { is_expected.to be_instance_of(to_enum.class) }
11
+ context 'with no block' do
12
+ it { expect(table.each).to be_instance_of(to_enum.class) }
15
13
 
16
14
  it 'yields the expected values' do
17
- expect(subject.to_a).to eql(table.to_a)
15
+ expect(table.each.to_a).to eql(table.to_a)
18
16
  end
19
17
  end
20
18
 
21
19
  context 'with block' do
22
- let(:yields) { [] }
23
-
24
- subject { table.each { |row| yields << row } }
25
-
26
- it 'yields header and rows' do
27
- subject
28
- expect(yields.first).to be_instance_of(TTY::Table::Header)
29
- expect(yields.last).to be_instance_of(TTY::Table::Row)
30
- end
31
-
32
- it 'yields header and rows with expected attributes' do
33
- subject
34
- expect(yields).to eql(table.data)
35
- end
36
-
37
- xit 'yields each row' do
38
- expect { subject }.to change { yields }.from([]).to(table.data)
20
+ it 'yields each row' do
21
+ yields = []
22
+ table.each { |row| yields << row }
23
+ expect(yields).to eql(table.to_a)
39
24
  end
40
25
  end
41
26
  end
@@ -3,54 +3,48 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Table, '.each_with_index' do
6
- let(:header) { ['Header1', 'Header2'] }
7
- let(:rows) { [['a1', 'a2'], ['b1', 'b2']] }
8
- let(:field) { TTY::Table::Field }
9
-
10
- let(:object) { described_class.new header, rows }
11
6
 
12
7
  context 'with no block' do
13
- subject { object.each_with_index }
14
-
15
- it { is_expected.to be_instance_of(to_enum.class) }
8
+ it 'returns enumerable' do
9
+ table = TTY::Table.new ['h1','h2'], [['a1','a2'],['b1','b2']]
10
+ expect(table.each_with_index).to be_instance_of(to_enum.class)
11
+ end
16
12
 
17
13
  it 'yields the expected values' do
18
- expect(subject.to_a).to eql(object.to_a)
14
+ table = TTY::Table.new ['h1','h2'], [['a1','a2'],['b1','b2']]
15
+ expect(table.each_with_index.to_a).to eql(table.to_a)
19
16
  end
20
17
  end
21
18
 
22
19
  context 'with block' do
23
- let(:yields) { [] }
24
-
25
- subject { object.each_with_index { |el, row, col| yields << [el, row, col]}}
26
-
27
20
  context 'without header' do
28
- let(:header) { nil }
29
-
30
- let(:expected) {
31
- [ [field.new('a1'), 0, 0], [field.new('a2'), 0, 1],
32
- [field.new('b1'), 1, 0], [field.new('b2'), 1, 1] ]
33
- }
34
-
35
21
  it "yields rows with expected data" do
36
- expect { subject }.to change { yields }.
37
- from( [] ).
38
- to( expected )
22
+ yields = []
23
+ table = TTY::Table.new [['a1','a2'],['b1','b2']]
24
+ expected = [
25
+ [['a1','a2'], 0],
26
+ [['b1','b2'], 1]
27
+ ]
28
+ expect {
29
+ table.each_with_index { |row, indx| yields << [row, indx] }
30
+ }.to change { yields }.from([]).to(expected)
39
31
  end
40
32
  end
41
33
 
42
34
  context 'with header' do
43
-
44
- let(:expected) {
45
- [ [field.new('Header1'), 0, 0], [field.new('Header2'), 0, 1],
46
- [field.new('a1'), 1, 0], [field.new('a2'), 1, 1],
47
- [field.new('b1'), 2, 0], [field.new('b2'), 2, 1] ]
48
- }
49
-
50
35
  it "yields header and rows with expected data" do
51
- expect { subject }.to change { yields }.
52
- from( [] ).
53
- to( expected )
36
+ yields = []
37
+ table = TTY::Table.new ['h1','h2'], [['a1','a2'],['b1','b2']]
38
+
39
+ expected = [
40
+ [['h1','h2'], 0],
41
+ [['a1','a2'], 1],
42
+ [['b1','b2'], 2]
43
+ ]
44
+
45
+ expect {
46
+ table.each_with_index { |row, indx| yields << [row, indx] }
47
+ }.to change { yields }.from( [] ).to( expected )
54
48
  end
55
49
  end
56
50
  end
@@ -2,20 +2,34 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe TTY::Table::Field, '#length' do
6
- let(:object) { described_class.new value }
5
+ RSpec.describe TTY::Table::Field, '.length' do
6
+ it "calculates length for nil string" do
7
+ field = described_class.new(nil)
8
+ expect(field.length).to eq(0)
9
+ end
7
10
 
8
- subject { object.length }
11
+ it "calculates length for empty string" do
12
+ field = described_class.new('')
13
+ expect(field.length).to eq(0)
14
+ end
9
15
 
10
- context 'with escaped value' do
11
- let(:value) { "Multi\nLine" }
16
+ it "calculates maximum length for multiline string" do
17
+ field = described_class.new("Multi\nLine\nContent")
18
+ expect(field.length).to eq(7)
19
+ end
12
20
 
13
- it { is_expected.to eql(5) }
21
+ it "calculates length for unicode string" do
22
+ field = described_class.new('こんにちは')
23
+ expect(field.length).to eq(10)
14
24
  end
15
25
 
16
- context 'with unescaped value' do
17
- let(:value) { "Multi\\nLine" }
26
+ it "calculates length for escaped string" do
27
+ field = described_class.new("Multi\\nLine")
28
+ expect(field.length).to eq(11)
29
+ end
18
30
 
19
- it { is_expected.to eql(11) }
31
+ it "calculates length for colored string" do
32
+ field = described_class.new("\e[32;41mgreen on red\e[0m")
33
+ expect(field.length).to eq(12)
20
34
  end
21
35
  end
@@ -18,6 +18,6 @@ RSpec.describe TTY::Table::Field, '#width' do
18
18
  context 'with hash value' do
19
19
  let(:value) { "foo\nbaar" }
20
20
 
21
- it { is_expected.to eql(8) }
21
+ it { is_expected.to eql(7) }
22
22
  end
23
23
  end
@@ -5,16 +5,15 @@ require 'spec_helper'
5
5
  RSpec.describe TTY::Table, '#filter' do
6
6
  let(:header) { ['h1', 'h2', 'h3'] }
7
7
  let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
- let(:table) { described_class.new(header, rows) }
9
- let(:filter) { Proc.new { |val, row, col|
10
- (col == 1 and row > 0) ? val.capitalize : val
11
- }
12
- }
13
8
 
14
- it 'filters rows' do
9
+ subject(:table) { described_class.new(header, rows) }
10
+
11
+ it 'filters fields' do
15
12
  expect(table.render do |renderer|
16
- renderer.filter = filter
17
- end).to eq <<-EOS.normalize
13
+ renderer.filter = proc do |val, row, col|
14
+ (col == 1 && row > 0) ? val.capitalize : val
15
+ end
16
+ end).to eq unindent(<<-EOS)
18
17
  h1 h2 h3
19
18
  a1 A2 a3
20
19
  b1 B2 b3
@@ -3,23 +3,14 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  RSpec.describe TTY::Table::Header, '#new' do
6
- let(:object) { described_class }
7
6
 
8
- context 'with no arguments' do
9
- subject { object.new }
10
-
11
- it { is_expected.to be_instance_of(object) }
12
-
13
- it { is_expected.to be_empty }
7
+ it "is empty without arguments" do
8
+ header = TTY::Table::Header.new
9
+ expect(header).to be_empty
14
10
  end
15
11
 
16
- context 'with attributes' do
17
- subject { object.new(attributes) }
18
-
19
- let(:attributes) { ['id', 'name', 'age'] }
20
-
21
- it { is_expected.to be_instance_of(object) }
22
-
23
- it { is_expected == attributes }
12
+ it "isn't empty with attributes" do
13
+ header = TTY::Table::Header.new [:id, :name, :age]
14
+ expect(header.to_a).to eq([:id, :name, :age])
24
15
  end
25
16
  end
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Table::Indentation, '.indent' do
6
+ let(:indent) { 2 }
7
+
8
+ subject(:indentation) { described_class.new(indent) }
9
+
10
+ context 'when enumerable' do
11
+ it 'inserts indentation for each element' do
12
+ expect(indentation.indent(['line1'])).to eql([' line1'])
13
+ end
14
+ end
15
+
16
+ context 'when string' do
17
+ it 'inserts indentation' do
18
+ expect(indentation.indent('line1')).to eql(' line1')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,73 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe TTY::Table, '#new' do
6
+ it { is_expected.to be_kind_of(Enumerable) }
7
+
8
+ it { is_expected.to be_kind_of(Comparable) }
9
+
10
+ context 'with rows only' do
11
+ it 'allows hash like syntax for rows' do
12
+ table = TTY::Table[['a1','a2'], ['b1', 'b2']]
13
+ expect(table.to_a).to eql([['a1','a2'], ['b1', 'b2']])
14
+ end
15
+
16
+ it 'allows for array' do
17
+ table = TTY::Table.new [['a1','a2'], ['b1','b2']]
18
+ expect(table.to_a).to eql([['a1','a2'], ['b1','b2']])
19
+ end
20
+
21
+ it 'allows for :rows key' do
22
+ table = TTY::Table.new rows: [['a1','a2'], ['b1','b2']]
23
+ expect(table.to_a).to eql([['a1','a2'], ['b1','b2']])
24
+ end
25
+
26
+ it 'allows for rows in a block' do
27
+ table = TTY::Table.new do |t|
28
+ t << ['a1', 'a2']
29
+ t << ['b1', 'b2']
30
+ end
31
+ expect(table.to_a).to eql([['a1','a2'],['b1','b2']])
32
+ end
33
+
34
+ it 'allows to add rows after initialization' do
35
+ table = TTY::Table.new
36
+ table << ['a1','a2']
37
+ table << ['b1','b2']
38
+ expect(table.to_a).to eql([['a1','a2'],['b1','b2']])
39
+ end
40
+
41
+ it 'allows for chaining rows' do
42
+ table = TTY::Table.new
43
+ table << ['a1','a2'] << ['b1','b2']
44
+ expect(table.to_a).to eql([['a1','a2'],['b1','b2']])
45
+ end
46
+ end
47
+
48
+ context 'with header and rows' do
49
+ it 'permits header and rows' do
50
+ table = TTY::Table.new ['h1','h2'], [['a1','a2'],['b1','b2']]
51
+ expect(table.to_a).to eql([['h1','h2'], ['a1','a2'], ['b1','b2']])
52
+ end
53
+
54
+ it 'permits only header with :header key' do
55
+ table = TTY::Table.new header: ['h1','h2']
56
+ expect(table.to_a).to eql([['h1','h2']])
57
+ end
58
+ end
59
+
60
+ context 'with header and rows as hash' do
61
+ it 'permits header as key and rows as hash values' do
62
+ table = TTY::Table.new [{'h1' => ['a1','a2'], 'h2' => ['b1','b2']}]
63
+ expect(table.to_a).to eql([['h1','h2'], ['a1','a2'], ['b1','b2']])
64
+ end
65
+ end
66
+
67
+ context 'coercion' do
68
+ it 'converts row arguments from hash to array' do
69
+ table = TTY::Table.new rows: {a: 1, b: 2}
70
+ expect(table.to_a).to eql([[:a,1],[:b,2]])
71
+ end
72
+ end
73
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe TTY::Table::Operation::AlignmentSet, '#call' do
5
+ RSpec.describe TTY::Table::Operation::Alignment, '#call' do
6
6
  let(:object) { described_class.new alignments, widths }
7
7
  let(:value) { 'a1' }
8
8
  let(:field) { TTY::Table::Field.new(value)}
@@ -7,10 +7,9 @@ RSpec.describe TTY::Table::Operation::Escape, '#call' do
7
7
  let(:text) { "太丸\nゴシ\tック体\r" }
8
8
  let(:field) { TTY::Table::Field.new(text) }
9
9
 
10
- subject { object.new }
10
+ subject(:operation) { object.new }
11
11
 
12
12
  it 'changes field value' do
13
- subject.call(field, 0, 0)
14
- expect(field.value).to eql("太丸\\nゴシ\\tック体\\r")
13
+ expect(operation.call(field, 0, 0)).to eql("太丸\\nゴシ\\tック体\\r")
15
14
  end
16
15
  end
@@ -8,10 +8,9 @@ RSpec.describe TTY::Table::Operation::Filter, '#call' do
8
8
  let(:filter) { Proc.new { |val, row, col| 'new' } }
9
9
  let(:value) { 'new' }
10
10
 
11
- subject { object.new(filter) }
11
+ subject(:operation) { object.new(filter) }
12
12
 
13
13
  it 'changes field value' do
14
- subject.call(field, 0, 0)
15
- expect(field.value).to eql(value)
14
+ expect(operation.call(field, 0, 0)).to eql(value)
16
15
  end
17
16
  end