tty 0.0.10 → 0.0.11

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.
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)