tty 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/README.md +75 -19
  2. data/lib/tty.rb +7 -0
  3. data/lib/tty/shell/question.rb +3 -3
  4. data/lib/tty/shell/response.rb +5 -5
  5. data/lib/tty/table.rb +51 -19
  6. data/lib/tty/table/column_set.rb +42 -1
  7. data/lib/tty/table/columns.rb +167 -0
  8. data/lib/tty/table/field.rb +2 -2
  9. data/lib/tty/table/indentation.rb +54 -0
  10. data/lib/tty/table/operation/escape.rb +1 -1
  11. data/lib/tty/table/operation/filter.rb +0 -1
  12. data/lib/tty/table/operation/padding.rb +95 -0
  13. data/lib/tty/table/operation/wrapped.rb +6 -3
  14. data/lib/tty/table/operations.rb +3 -2
  15. data/lib/tty/table/orientation/horizontal.rb +27 -1
  16. data/lib/tty/table/orientation/vertical.rb +17 -1
  17. data/lib/tty/table/padder.rb +142 -0
  18. data/lib/tty/table/renderer/basic.rb +101 -31
  19. data/lib/tty/table/validatable.rb +0 -7
  20. data/lib/tty/terminal/color.rb +36 -20
  21. data/lib/tty/text/truncation.rb +16 -1
  22. data/lib/tty/text/wrapping.rb +31 -10
  23. data/lib/tty/version.rb +1 -1
  24. data/spec/tty/shell/question/argument_spec.rb +1 -1
  25. data/spec/tty/shell/question/modify_spec.rb +2 -2
  26. data/spec/tty/shell/response/read_email_spec.rb +0 -1
  27. data/spec/tty/table/border/ascii/rendering_spec.rb +34 -7
  28. data/spec/tty/table/border/null/rendering_spec.rb +34 -7
  29. data/spec/tty/table/column_set/extract_widths_spec.rb +1 -1
  30. data/spec/tty/table/column_set/widths_from_spec.rb +52 -0
  31. data/spec/tty/table/columns/enforce_spec.rb +68 -0
  32. data/spec/tty/table/columns/widths_spec.rb +33 -0
  33. data/spec/tty/table/indentation/insert_indent_spec.rb +27 -0
  34. data/spec/tty/table/operation/wrapped/call_spec.rb +2 -1
  35. data/spec/tty/table/operation/wrapped/wrap_spec.rb +3 -2
  36. data/spec/tty/table/operations/new_spec.rb +3 -5
  37. data/spec/tty/table/orientation_spec.rb +68 -22
  38. data/spec/tty/table/padder/parse_spec.rb +45 -0
  39. data/spec/tty/table/padding_spec.rb +120 -0
  40. data/spec/tty/table/renderer/ascii/indentation_spec.rb +41 -0
  41. data/spec/tty/table/renderer/ascii/padding_spec.rb +61 -0
  42. data/spec/tty/table/renderer/ascii/resizing_spec.rb +114 -0
  43. data/spec/tty/table/renderer/basic/alignment_spec.rb +18 -19
  44. data/spec/tty/table/renderer/basic/coloring_spec.rb +45 -0
  45. data/spec/tty/table/renderer/basic/indentation_spec.rb +46 -0
  46. data/spec/tty/table/renderer/basic/options_spec.rb +2 -2
  47. data/spec/tty/table/renderer/basic/padding_spec.rb +52 -0
  48. data/spec/tty/table/renderer/basic/resizing_spec.rb +96 -0
  49. data/spec/tty/table/renderer/render_spec.rb +36 -0
  50. data/spec/tty/table/renderer/unicode/indentation_spec.rb +41 -0
  51. data/spec/tty/table/renderer/unicode/padding_spec.rb +61 -0
  52. data/spec/tty/table/renderer_spec.rb +19 -0
  53. data/spec/tty/table/rotate_spec.rb +20 -6
  54. data/spec/tty/text/truncation/truncate_spec.rb +18 -3
  55. data/spec/tty/text/wrapping/wrap_spec.rb +24 -7
  56. metadata +56 -18
@@ -13,6 +13,8 @@ module TTY
13
13
 
14
14
  attr_reader :indent
15
15
 
16
+ attr_reader :padding
17
+
16
18
  # Initialize a Wrapping
17
19
  #
18
20
  # @param [String] text
@@ -31,11 +33,12 @@ module TTY
31
33
  #
32
34
  # @api private
33
35
  def initialize(text, *args)
34
- options = Utils.extract_options!(args)
35
- @text = text
36
- @length = options.fetch(:length) { DEFAULT_WIDTH }
37
- @indent = options.fetch(:indent) { 0 }
38
- @length = args[0] unless args.empty?
36
+ options = Utils.extract_options!(args)
37
+ @text = text
38
+ @length = options.fetch(:length) { DEFAULT_WIDTH }
39
+ @indent = options.fetch(:indent) { 0 }
40
+ @padding = options.fetch(:padding) { [] }
41
+ @length = args[0] unless args.empty?
39
42
  end
40
43
 
41
44
  # Wrap a text into lines no longer than length
@@ -47,9 +50,8 @@ module TTY
47
50
  return text unless length && length > 0
48
51
 
49
52
  as_unicode do
50
- text.split(NEWLINE).map do |line|
51
- modified_line = wrap_line line
52
- indent_line modified_line
53
+ text.split(NEWLINE, -1).map do |line|
54
+ pad_line(indent_line(wrap_line(line)))
53
55
  end * NEWLINE
54
56
  end
55
57
  end
@@ -74,8 +76,9 @@ module TTY
74
76
  # @api private
75
77
  def wrap_line(line)
76
78
  wrap_at = actual_length line
77
- line.strip.gsub(/\n/,' ').squeeze(' ').
78
- gsub(/(.{1,#{wrap_at}})(?:\s+|$\n?)|(.{1,#{wrap_at}})/, "\\1\\2\n").strip
79
+ line.strip.gsub(/\n/, ' ').squeeze(' ')
80
+ .gsub(/(.{1,#{wrap_at}})(?:\s+|$\n?)|(.{1,#{wrap_at}})/, "\\1\\2\n")
81
+ .strip
79
82
  end
80
83
 
81
84
  # Indent string by given value
@@ -91,6 +94,24 @@ module TTY
91
94
  end
92
95
  end
93
96
 
97
+ # Add padding to each line in wrapped text
98
+ #
99
+ # @param [String] text
100
+ # the wrapped text
101
+ #
102
+ # @return [String]
103
+ #
104
+ # @api private
105
+ def pad_line(text)
106
+ return text if text.empty? || padding.empty?
107
+
108
+ padding_left = ' ' * padding[3].to_i
109
+ padding_right = ' ' * padding[1].to_i
110
+ text.map! do |part|
111
+ part.insert(0, padding_left).insert(-1, padding_right)
112
+ end
113
+ end
114
+
94
115
  end # Wrapping
95
116
  end # Text
96
117
  end # TTY
data/lib/tty/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  module TTY
4
- VERSION = "0.0.10"
4
+ VERSION = "0.0.11"
5
5
  end
@@ -5,7 +5,7 @@ require 'spec_helper'
5
5
  describe TTY::Shell::Question, '#argument' do
6
6
  let(:input) { StringIO.new }
7
7
  let(:output) { StringIO.new }
8
- let(:shell) { TTY::Shell.new(input, output) }
8
+ let(:shell) { TTY::Shell.new(input, output) }
9
9
 
10
10
  it 'requires value to be present with helper' do
11
11
  input << ''
@@ -5,7 +5,7 @@ require 'spec_helper'
5
5
  describe TTY::Shell::Question, '#modify' do
6
6
  let(:input) { StringIO.new }
7
7
  let(:output) { StringIO.new }
8
- let(:shell) { TTY::Shell.new(input, output) }
8
+ let(:shell) { TTY::Shell.new(input, output) }
9
9
 
10
10
  it 'preserves answer for unkown modification' do
11
11
  input << 'piotr'
@@ -32,7 +32,7 @@ describe TTY::Shell::Question, '#modify' do
32
32
  input << " Some white\t space\t \there! \n"
33
33
  input.rewind
34
34
  q = shell.ask("Enter some text: ").modify(:collapse)
35
- expect(q.read_string).to eql " Some white space here! "
35
+ expect(q.read_string).to eql "Some white space here!"
36
36
  end
37
37
 
38
38
  it 'strips and collapses whitespace' do
@@ -39,5 +39,4 @@ describe TTY::Shell::Question, '#read_email' do
39
39
  expect(output.string).to eql "What is your email?\nWhat is your email?\n"
40
40
  end
41
41
  end
42
-
43
42
  end
@@ -49,15 +49,42 @@ describe TTY::Table::Border::ASCII, '#rendering' do
49
49
  end
50
50
 
51
51
  context 'with multiline row' do
52
- let(:row) { TTY::Table::Row.new(["a1\nb1\nc1", 'a2', 'a3']) }
53
52
  let(:column_widths) { [2,2,2]}
54
53
 
55
- it 'draws row line' do
56
- subject.row_line(row).should == <<-EOS.normalize
57
- |a1|a2|a3|
58
- |b1| | |
59
- |c1| | |
60
- EOS
54
+ context 'with mixed data' do
55
+ let(:row) { TTY::Table::Row.new(["a1\nb1\nc1", 'a2', 'a3']) }
56
+
57
+ it 'draws row line' do
58
+ subject.row_line(row).should == <<-EOS.normalize
59
+ |a1|a2|a3|
60
+ |b1| | |
61
+ |c1| | |
62
+ EOS
63
+ end
64
+ end
65
+
66
+ context 'with sparse data' do
67
+ let(:row) { TTY::Table::Row.new(["a1\n\n", "\na2\n", "\n\na3"]) }
68
+
69
+ it 'draws row line' do
70
+ subject.row_line(row).should == <<-EOS.normalize
71
+ |a1| | |
72
+ | |a2| |
73
+ | | |a3|
74
+ EOS
75
+ end
76
+ end
77
+
78
+ context 'with empty data' do
79
+ let(:row) { TTY::Table::Row.new(["\na1\n", "\na2\n", "\na3\n"]) }
80
+
81
+ it 'draws row line' do
82
+ subject.row_line(row).should == <<-EOS.normalize
83
+ | | | |
84
+ |a1|a2|a3|
85
+ | | | |
86
+ EOS
87
+ end
61
88
  end
62
89
  end
63
90
  end
@@ -50,15 +50,42 @@ describe TTY::Table::Border::Null, '#rendering' do
50
50
  end
51
51
 
52
52
  context 'with multiline row' do
53
- let(:row) { TTY::Table::Row.new(["a1\nb1\nc1", 'a2', 'a3']) }
54
53
  let(:column_widths) { [2,2,2] }
55
54
 
56
- it 'draws row line' do
57
- subject.row_line(row).should == <<-EOS.normalize
58
- a1 a2 a3
59
- b1
60
- c1
61
- EOS
55
+ context 'with mixed data' do
56
+ let(:row) { TTY::Table::Row.new(["a1\nb1\nc1", 'a2', 'a3']) }
57
+
58
+ it 'draws row line' do
59
+ subject.row_line(row).should == <<-EOS.normalize
60
+ a1 a2 a3
61
+ b1
62
+ c1
63
+ EOS
64
+ end
65
+ end
66
+
67
+ context 'with sparse data' do
68
+ let(:row) { TTY::Table::Row.new(["a1\n\n", "\na2\n", "\n\na3"]) }
69
+
70
+ it 'draws row line' do
71
+ subject.row_line(row).should == <<-EOS.chomp
72
+ a1
73
+ a2
74
+ a3
75
+ EOS
76
+ end
77
+ end
78
+
79
+ context 'with empty data' do
80
+ let(:row) { TTY::Table::Row.new(["\na1\n", "\na2\n", "\na3\n"]) }
81
+
82
+ it 'draws row line' do
83
+ subject.row_line(row).should == <<-EOS.chomp
84
+
85
+ a1 a2 a3
86
+
87
+ EOS
88
+ end
62
89
  end
63
90
  end
64
91
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe TTY::Table::ColumnSet, '#extract_widths!' do
5
+ describe TTY::Table::ColumnSet, '#extract_widths' do
6
6
  let(:header) { ['h1', 'h2', 'h3'] }
7
7
  let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
8
  let(:table) { TTY::Table.new header, rows }
@@ -0,0 +1,52 @@
1
+
2
+ # -*- encoding: utf-8 -*-
3
+
4
+ require 'spec_helper'
5
+
6
+ describe TTY::Table::ColumnSet, '#widths_from' do
7
+ let(:header) { ['h1', 'h2', 'h3'] }
8
+ let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
9
+ let(:table) { TTY::Table.new header, rows }
10
+
11
+ subject { described_class.widths_from(table, column_widths) }
12
+
13
+ context 'when empty array' do
14
+ let(:column_widths) { [] }
15
+
16
+ it 'raises an error' do
17
+ expect { subject }.to raise_error(TTY::InvalidArgument)
18
+ end
19
+ end
20
+
21
+ context 'when invalid size array' do
22
+ let(:column_widths) { [3,3] }
23
+
24
+ it 'raises an error' do
25
+ expect { subject }.to raise_error(TTY::InvalidArgument)
26
+ end
27
+ end
28
+
29
+ context 'when valid array' do
30
+ let(:column_widths) { [3,3,3] }
31
+
32
+ it 'converts into numbers' do
33
+ expect(subject).to eql(column_widths)
34
+ end
35
+ end
36
+
37
+ context 'when nil' do
38
+ let(:column_widths) { nil }
39
+
40
+ it 'extracts widths' do
41
+ expect(subject).to eql([2,2,2])
42
+ end
43
+ end
44
+
45
+ context 'when numeric' do
46
+ let(:column_widths) { 5 }
47
+
48
+ it 'generates widths' do
49
+ expect(subject).to eql([5,5,5])
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,68 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Table::Columns, '#enforce' do
6
+ let(:header) { ['h1', 'h2', 'h3', 'h4'] }
7
+ let(:rows) { [['a1', 'a2', 'a3', 'a4'], ['b1', 'b2', 'b3', 'b4']] }
8
+ let(:table) { TTY::Table.new(header, rows) }
9
+ let(:object) { described_class.new(renderer) }
10
+
11
+ subject { object.enforce }
12
+
13
+ context 'with width contraint' do
14
+ let(:renderer) { TTY::Table::Renderer::Basic.new(table, options) }
15
+ let(:options) { { width: 5 }}
16
+
17
+ it 'raises error when table width is too small' do
18
+ expect { subject }.to raise_error(TTY::ResizeError)
19
+ end
20
+ end
21
+
22
+ context 'with width contraint matching natural width' do
23
+ let(:renderer) { TTY::Table::Renderer::Basic.new(table, options) }
24
+ let(:options) { { width: 11, resize: true }}
25
+
26
+ it 'raises error when table width is too small' do
27
+ expect(object).to receive(:expand)
28
+ subject
29
+ end
30
+ end
31
+
32
+ context 'with table larger than allowed width' do
33
+ let(:renderer) { TTY::Table::Renderer::Basic.new(table, options) }
34
+
35
+ context 'with resize' do
36
+ let(:options) { { width: 8, resize: true } }
37
+
38
+ it 'calls shrink' do
39
+ expect(object).to receive(:shrink)
40
+ subject
41
+ end
42
+ end
43
+
44
+ context 'without resize' do
45
+ let(:options) { { width: 8, resize: false }}
46
+
47
+ it 'changes table orientation to vertical' do
48
+ TTY.shell.should_receive(:warn)
49
+ expect(renderer.column_widths).to eql([2,2,2,2])
50
+ expect(renderer.table.orientation.name).to eql(:horizontal)
51
+ subject
52
+ expect(renderer.column_widths).to eq([2,2])
53
+ expect(renderer.table.orientation.name).to eql(:vertical)
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'with table less than allowed width' do
59
+ let(:renderer) { TTY::Table::Renderer::Basic.new(table, options) }
60
+ let(:options) { { width: 15 }}
61
+
62
+ before { TTY.shell.stub(:warn) }
63
+
64
+ it "doesn't change original widths" do
65
+ expect(renderer.column_widths).to eq([2,2,2,2])
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe TTY::Table::Columns, 'column widths' do
4
+ let(:header) { ['h1', 'h2', 'h3', 'h4'] }
5
+ let(:rows) { [['a1', 'a2', 'a3', 'a4'], ['b1', 'b2', 'b3', 'b4']] }
6
+ let(:table) { TTY::Table.new(header, rows) }
7
+
8
+ subject { described_class.new(renderer) }
9
+
10
+ context 'with basic renderer' do
11
+ let(:renderer) { TTY::Table::Renderer::Basic.new(table) }
12
+
13
+ it 'calculates columns natural width' do
14
+ expect(subject.natural_width).to eq(11)
15
+ end
16
+
17
+ it 'calculates miminimum columns width' do
18
+ expect(subject.minimum_width).to eq(7)
19
+ end
20
+ end
21
+
22
+ context 'with ascii renderer' do
23
+ let(:renderer) { TTY::Table::Renderer::ASCII.new(table) }
24
+
25
+ it 'calculates columns natural width' do
26
+ expect(subject.natural_width).to eq(13)
27
+ end
28
+
29
+ it 'calculates miminimum columns width' do
30
+ expect(subject.minimum_width).to eq(9)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Table::Indentation, '#insert_indent' do
6
+ let(:indent) { 2 }
7
+ let(:renderer) { double(:renderer, indent: indent) }
8
+ let(:object) { described_class.new(renderer) }
9
+
10
+ subject { object.insert_indent(part) }
11
+
12
+ context 'when enumerable' do
13
+ let(:part) { ['line1'] }
14
+
15
+ it 'inserts indentation for each element' do
16
+ expect(subject[0]).to eql(' line1')
17
+ end
18
+ end
19
+
20
+ context 'when string' do
21
+ let(:part) { 'line1' }
22
+
23
+ it 'inserts indentation' do
24
+ expect(subject).to eql(' line1')
25
+ end
26
+ end
27
+ end
@@ -3,7 +3,8 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe TTY::Table::Operation::Wrapped, '#call' do
6
- let(:object) { described_class.new column_widths }
6
+ let(:padding) { TTY::Table::Padder.parse }
7
+ let(:object) { described_class.new(column_widths, padding) }
7
8
  let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
8
9
  let(:field) { TTY::Table::Field.new(text) }
9
10
 
@@ -3,8 +3,9 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe TTY::Table::Operation::Wrapped, '#wrap' do
6
- let(:instance) { described_class.new [] }
7
- let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
6
+ let(:padding) { TTY::Table::Padder.parse }
7
+ let(:instance) { described_class.new([], padding) }
8
+ let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
8
9
 
9
10
  subject { instance.wrap(text, width) }
10
11
 
@@ -4,8 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe TTY::Table::Operations, '#new' do
6
6
  let(:object) { described_class }
7
- let(:row) { [1,2,3] }
8
- let(:table) { TTY::Table.new :rows => [row] }
7
+ let(:row) { [1,2,3] }
8
+ let(:table) { TTY::Table.new :rows => [row] }
9
9
  let(:callable) {
10
10
  Class.new do
11
11
  def call(val, row, col)
@@ -17,9 +17,7 @@ describe TTY::Table::Operations, '#new' do
17
17
 
18
18
  subject { object.new table }
19
19
 
20
- before {
21
- subject.add_operation(:alignment, instance)
22
- }
20
+ before { subject.add(:alignment, instance) }
23
21
 
24
22
  it 'stores away operations' do
25
23
  expect(subject.operations[:alignment]).to include(instance)