tty 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/README.md +78 -12
  2. data/benchmarks/shell.rb +26 -0
  3. data/benchmarks/table.rb +35 -0
  4. data/lib/tty.rb +23 -1
  5. data/lib/tty/coercer.rb +13 -0
  6. data/lib/tty/coercer/boolean.rb +39 -0
  7. data/lib/tty/coercer/float.rb +23 -0
  8. data/lib/tty/coercer/integer.rb +23 -0
  9. data/lib/tty/coercer/range.rb +33 -0
  10. data/lib/tty/shell.rb +6 -2
  11. data/lib/tty/shell/question.rb +158 -138
  12. data/lib/tty/shell/reader.rb +92 -0
  13. data/lib/tty/shell/response.rb +219 -0
  14. data/lib/tty/shell/response_delegation.rb +53 -0
  15. data/lib/tty/table.rb +90 -16
  16. data/lib/tty/table/border.rb +34 -8
  17. data/lib/tty/table/border/ascii.rb +16 -25
  18. data/lib/tty/table/border/null.rb +0 -6
  19. data/lib/tty/table/border/unicode.rb +16 -25
  20. data/lib/tty/table/column_set.rb +1 -1
  21. data/lib/tty/table/error.rb +10 -0
  22. data/lib/tty/table/operation/wrapped.rb +0 -6
  23. data/lib/tty/table/orientation.rb +57 -0
  24. data/lib/tty/table/orientation/horizontal.rb +19 -0
  25. data/lib/tty/table/orientation/vertical.rb +19 -0
  26. data/lib/tty/table/renderer.rb +7 -0
  27. data/lib/tty/table/renderer/ascii.rb +1 -1
  28. data/lib/tty/table/renderer/basic.rb +2 -2
  29. data/lib/tty/table/renderer/unicode.rb +1 -1
  30. data/lib/tty/table/validatable.rb +20 -0
  31. data/lib/tty/terminal.rb +15 -14
  32. data/lib/tty/terminal/color.rb +1 -1
  33. data/lib/tty/terminal/echo.rb +41 -0
  34. data/lib/tty/terminal/home.rb +31 -0
  35. data/lib/tty/text.rb +85 -0
  36. data/lib/tty/text/truncation.rb +83 -0
  37. data/lib/tty/text/wrapping.rb +96 -0
  38. data/lib/tty/version.rb +1 -1
  39. data/spec/tty/coercer/boolean/coerce_spec.rb +113 -0
  40. data/spec/tty/coercer/float/coerce_spec.rb +32 -0
  41. data/spec/tty/coercer/integer/coerce_spec.rb +39 -0
  42. data/spec/tty/coercer/range/coerce_spec.rb +73 -0
  43. data/spec/tty/shell/ask_spec.rb +14 -1
  44. data/spec/tty/shell/question/argument_spec.rb +30 -0
  45. data/spec/tty/shell/question/character_spec.rb +16 -0
  46. data/spec/tty/shell/question/default_spec.rb +25 -0
  47. data/spec/tty/shell/question/in_spec.rb +23 -0
  48. data/spec/tty/shell/question/initialize_spec.rb +11 -211
  49. data/spec/tty/shell/question/modifier/whitespace_spec.rb +1 -1
  50. data/spec/tty/shell/question/modify_spec.rb +44 -0
  51. data/spec/tty/shell/question/valid_spec.rb +46 -0
  52. data/spec/tty/shell/question/validate_spec.rb +30 -0
  53. data/spec/tty/shell/reader/getc_spec.rb +40 -0
  54. data/spec/tty/shell/response/read_bool_spec.rb +41 -0
  55. data/spec/tty/shell/response/read_char_spec.rb +17 -0
  56. data/spec/tty/shell/response/read_date_spec.rb +20 -0
  57. data/spec/tty/shell/response/read_email_spec.rb +43 -0
  58. data/spec/tty/shell/response/read_multiple_spec.rb +24 -0
  59. data/spec/tty/shell/response/read_number_spec.rb +29 -0
  60. data/spec/tty/shell/response/read_range_spec.rb +29 -0
  61. data/spec/tty/shell/response/read_spec.rb +68 -0
  62. data/spec/tty/shell/response/read_string_spec.rb +19 -0
  63. data/spec/tty/table/access_spec.rb +6 -0
  64. data/spec/tty/table/border/new_spec.rb +3 -3
  65. data/spec/tty/table/initialize_spec.rb +17 -1
  66. data/spec/tty/table/options_spec.rb +7 -1
  67. data/spec/tty/table/orientation_spec.rb +98 -0
  68. data/spec/tty/table/renders_with_spec.rb +76 -0
  69. data/spec/tty/table/rotate_spec.rb +72 -0
  70. data/spec/tty/table/to_s_spec.rb +13 -1
  71. data/spec/tty/table/validatable/validate_options_spec.rb +34 -0
  72. data/spec/tty/terminal/color/remove_spec.rb +34 -1
  73. data/spec/tty/terminal/echo_spec.rb +22 -0
  74. data/spec/tty/text/truncate_spec.rb +13 -0
  75. data/spec/tty/text/truncation/initialize_spec.rb +29 -0
  76. data/spec/tty/text/truncation/truncate_spec.rb +73 -0
  77. data/spec/tty/text/wrap_spec.rb +14 -0
  78. data/spec/tty/text/wrapping/initialize_spec.rb +25 -0
  79. data/spec/tty/text/wrapping/wrap_spec.rb +80 -0
  80. data/tty.gemspec +1 -0
  81. metadata +101 -8
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Shell::Question, '#initialize' do
6
+ let(:input) { StringIO.new }
7
+ let(:output) { StringIO.new }
8
+ let(:shell) { TTY::Shell.new(input, output) }
9
+
10
+ it 'reads string' do
11
+ name = "Piotr"
12
+ input << name
13
+ input.rewind
14
+ q = shell.ask("What is your name?")
15
+ answer = q.read_string
16
+ expect(answer).to be_kind_of String
17
+ expect(answer).to eql name
18
+ end
19
+ end
@@ -14,6 +14,12 @@ describe TTY::Table, 'access' do
14
14
 
15
15
  its([0,0]) { should == 'a1'}
16
16
 
17
+ its([0]) { should == rows[0] }
18
+
19
+ its([5]) { should be_nil }
20
+
21
+ its([-1]) { should == rows[-1] }
22
+
17
23
  its([5,5]) { should be_nil }
18
24
 
19
25
  it 'raises error for negative indices' do
@@ -5,13 +5,13 @@ require 'spec_helper'
5
5
  describe TTY::Table::Border, '#new' do
6
6
  subject { klass.new }
7
7
 
8
- context '' do
8
+ context 'when abstract' do
9
9
  let(:klass) { described_class }
10
10
 
11
- specify { expect {subject }.to raise_error(NotImplementedError) }
11
+ specify { expect { subject }.to raise_error(NotImplementedError) }
12
12
  end
13
13
 
14
- context '' do
14
+ context 'when concrete' do
15
15
  let(:klass) { Class.new }
16
16
 
17
17
  specify { expect {subject }.to_not raise_error(NotImplementedError) }
@@ -29,7 +29,7 @@ describe TTY::Table, '#initialize' do
29
29
  end
30
30
 
31
31
  it 'initializes table rows in a block with param' do
32
- table = TTY::Table.new do |t|
32
+ table = TTY::Table.new do |t|
33
33
  t << rows[0]
34
34
  t << rows[1]
35
35
  end
@@ -48,6 +48,22 @@ describe TTY::Table, '#initialize' do
48
48
  table << rows[0] << rows[1]
49
49
  table.to_a.should == rows
50
50
  end
51
+
52
+ context 'with data as hash' do
53
+ let(:data) { [ {'Header1' => ['a1','a2'], 'Header2' => ['b1', 'b2'] }] }
54
+
55
+ it 'extracts rows' do
56
+ table = TTY::Table.new data
57
+ expect(table.to_a).to include rows[0]
58
+ expect(table.to_a).to include rows[1]
59
+ end
60
+
61
+ it 'extracts header' do
62
+ table = TTY::Table.new data
63
+ expect(table.header).to include header[0]
64
+ expect(table.header).to include header[1]
65
+ end
66
+ end
51
67
  end
52
68
 
53
69
  context 'with header and rows' do
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe TTY::Table, 'options' do
6
6
  let(:rows) { [['a1', 'a2'], ['b1', 'b2']] }
7
- let(:widths) { [] }
7
+ let(:widths) { nil }
8
8
  let(:aligns) { [] }
9
9
  let(:object) {
10
10
  described_class.new rows,
@@ -29,6 +29,12 @@ describe TTY::Table, 'options' do
29
29
  its(:column_widths) { should == widths }
30
30
  end
31
31
 
32
+ context '#column_widths empty' do
33
+ let(:widths) { [] }
34
+
35
+ it { expect { subject }.to raise_error(TTY::InvalidArgument) }
36
+ end
37
+
32
38
  context '#column_aligns' do
33
39
  let(:aligns) { [:center, :center] }
34
40
 
@@ -0,0 +1,98 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Table, 'orientation' do
6
+ let(:header) { ['h1', 'h2', 'h3'] }
7
+ let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
+ let(:renderer) { :basic }
9
+ let(:options) { { :orientation => orientation, :renderer => renderer } }
10
+
11
+ subject { described_class.new header, rows, options }
12
+
13
+ context 'when illegal option' do
14
+ let(:orientation) { :accross }
15
+
16
+ it { expect { subject }.to raise_error(TTY::InvalidOrientationError) }
17
+ end
18
+
19
+ context 'when horizontal' do
20
+ let(:orientation) { :horizontal }
21
+
22
+ its(:orientation) { should be_kind_of TTY::Table::Orientation }
23
+
24
+ it { expect(subject.orientation.name).to eql :horizontal }
25
+
26
+ it { expect(subject.header).to eql header }
27
+
28
+ it 'preserves original rows' do
29
+ expect(subject.to_a).to eql rows
30
+ end
31
+
32
+ context 'without border' do
33
+ it 'displays table' do
34
+ subject.to_s.should == <<-EOS.normalize
35
+ h1 h2 h3
36
+ a1 a2 a3
37
+ b1 b2 b3
38
+ EOS
39
+ end
40
+ end
41
+
42
+ context 'with border' do
43
+ let(:renderer) { :ascii }
44
+
45
+ it 'diplays table' do
46
+ subject.to_s.should == <<-EOS.normalize
47
+ +--+--+--+
48
+ |h1|h2|h3|
49
+ +--+--+--+
50
+ |a1|a2|a3|
51
+ |b1|b2|b3|
52
+ +--+--+--+
53
+ EOS
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'when vertical' do
59
+ let(:orientation) { :vertical }
60
+
61
+ its(:orientation) { should be_kind_of TTY::Table::Orientation }
62
+
63
+ it { expect(subject.orientation.name).to eql :vertical }
64
+
65
+ it { expect(subject.header).to be_empty }
66
+
67
+ it 'rotates original rows' do
68
+ rotated_rows = []
69
+ (0..2).each {|n| rotated_rows << [header[n], rows[0][n], rows[1][n]] }
70
+ expect(subject.to_a).to eql rotated_rows
71
+ end
72
+
73
+ context 'without border' do
74
+ it 'displays table' do
75
+ subject.to_s.should == <<-EOS.normalize
76
+ h1 a1 b1
77
+ h2 a2 b2
78
+ h3 a3 b3
79
+ EOS
80
+ end
81
+ end
82
+
83
+ context 'with border' do
84
+ let(:renderer) { :ascii }
85
+
86
+ it 'diplays table' do
87
+ subject.to_s.should == <<-EOS.normalize
88
+ +--+--+--+
89
+ |h1|a1|b1|
90
+ |h2|a2|b2|
91
+ |h3|a3|b3|
92
+ +--+--+--+
93
+ EOS
94
+ end
95
+ end
96
+ end
97
+
98
+ end # orientation
@@ -0,0 +1,76 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Table, '#renders_with' do
6
+ let(:header) { ['h1', 'h2', 'h3'] }
7
+ let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
+ let(:table) { described_class.new header, rows }
9
+
10
+ context 'with complete border' do
11
+ let(:border_class) {
12
+ class MyBorder < TTY::Table::Border
13
+ def_border do
14
+ {
15
+ 'top' => '=',
16
+ 'top_mid' => '*',
17
+ 'top_left' => '*',
18
+ 'top_right' => '*',
19
+ 'bottom' => '=',
20
+ 'bottom_mid' => '*',
21
+ 'bottom_left' => '*',
22
+ 'bottom_right' => '*',
23
+ 'mid' => '=',
24
+ 'mid_mid' => '*',
25
+ 'mid_left' => '*',
26
+ 'mid_right' => '*',
27
+ 'left' => '$',
28
+ 'right' => '$'
29
+ }
30
+ end
31
+ end
32
+ }
33
+
34
+ it 'displays custom border' do
35
+ border_class
36
+ table.renders_with MyBorder
37
+ table.to_s.should == <<-EOS.normalize
38
+ *==*==*==*
39
+ $h1$h2$h3$
40
+ *==*==*==*
41
+ $a1$a2$a3$
42
+ $b1$b2$b3$
43
+ *==*==*==*
44
+ EOS
45
+ end
46
+ end
47
+
48
+ context 'with incomplete border' do
49
+ let(:border_class) {
50
+ class MyBorder < TTY::Table::Border
51
+ def_border do
52
+ {
53
+ 'bottom' => ' ',
54
+ 'bottom_mid' => '*',
55
+ 'bottom_left' => '*',
56
+ 'bottom_right' => '*',
57
+ 'left' => '$',
58
+ 'right' => '$'
59
+ }
60
+ end
61
+ end
62
+ }
63
+
64
+ it 'displays border' do
65
+ border_class
66
+ table.renders_with MyBorder
67
+ table.to_s.should == <<-EOS.normalize
68
+ $h1$h2$h3$
69
+ $a1$a2$a3$
70
+ $b1$b2$b3$
71
+ * * * *
72
+ EOS
73
+ end
74
+ end
75
+
76
+ end # renders_with
@@ -0,0 +1,72 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Table, '#rotate' do
6
+ let(:header) { ['h1', 'h2', 'h3'] }
7
+ let(:rows) { [['a1', 'a2', 'a3'], ['b1', 'b2', 'b3']] }
8
+
9
+ subject { described_class.new(header, rows) }
10
+
11
+ before { subject.orientation = :horizontal }
12
+
13
+ context 'with default' do
14
+ context 'without header' do
15
+ let(:header) { nil }
16
+
17
+ it 'preserves orientation' do
18
+ expect(subject.header).to be_nil
19
+ expect(subject.rotate.to_a).to eql rows
20
+ end
21
+ end
22
+
23
+ context 'with header' do
24
+ it 'preserves orientation' do
25
+ expect(subject.header).to eql header
26
+ expect(subject.rotate.to_a).to eql rows
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'with no header' do
32
+ let(:header) { nil }
33
+
34
+ it 'rotates the rows' do
35
+ subject.orientation = :vertical
36
+ expect(subject.rotate.to_a).to eql [
37
+ ['a1', 'b1'],
38
+ ['a2', 'b2'],
39
+ ['a3', 'b3'],
40
+ ]
41
+ expect(subject.header).to be_nil
42
+ end
43
+
44
+ it 'rotates the rows back' do
45
+ subject.orientation = :vertical
46
+ subject.rotate
47
+ subject.orientation = :horizontal
48
+ expect(subject.rotate.to_a).to eql rows
49
+ expect(subject.header).to eql header
50
+ end
51
+ end
52
+
53
+ context 'with header' do
54
+ it 'rotates the rows and merges header' do
55
+ subject.orientation = :vertical
56
+ expect(subject.rotate.to_a).to eql [
57
+ ['h1', 'a1', 'b1'],
58
+ ['h2', 'a2', 'b2'],
59
+ ['h3', 'a3', 'b3'],
60
+ ]
61
+ expect(subject.header).to be_empty
62
+ end
63
+
64
+ it 'rotates the rows and header back' do
65
+ subject.orientation = :vertical
66
+ subject.rotate
67
+ subject.orientation = :horizontal
68
+ expect(subject.rotate.to_a).to eql rows
69
+ expect(subject.header).to eql header
70
+ end
71
+ end
72
+ end
@@ -9,6 +9,18 @@ describe TTY::Table, '#to_s' do
9
9
 
10
10
  subject { described_class.new header, rows, :renderer => renderer }
11
11
 
12
+ context 'without renderer' do
13
+ let(:renderer) { nil }
14
+
15
+ it 'displayes basic table' do
16
+ subject.to_s.should == <<-EOS.normalize
17
+ h1 h2 h3
18
+ a1 a2 a3
19
+ b1 b2 b3
20
+ EOS
21
+ end
22
+ end
23
+
12
24
  context 'without border' do
13
25
  it 'displays table' do
14
26
  subject.to_s.should == <<-EOS.normalize
@@ -48,4 +60,4 @@ describe TTY::Table, '#to_s' do
48
60
  EOS
49
61
  end
50
62
  end
51
- end
63
+ end # to_s
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ describe TTY::Table::Validatable, '#validate_options!' do
6
+ let(:described_class) { Class.new { include TTY::Table::Validatable } }
7
+
8
+ subject { described_class.new.validate_options! options }
9
+
10
+ context 'with empty rows' do
11
+ let(:options) { {:rows => []} }
12
+
13
+ it { expect { subject }.not_to raise_error(TTY::InvalidArgument) }
14
+ end
15
+
16
+ context 'with invalid rows type' do
17
+ let(:options) { {:rows => 1 } }
18
+
19
+ it { expect { subject }.to raise_error(TTY::InvalidArgument) }
20
+ end
21
+
22
+ context 'with empty header' do
23
+ let(:options) { {:header => []} }
24
+
25
+ it { expect { subject }.to raise_error(TTY::InvalidArgument) }
26
+ end
27
+
28
+ context 'with invalid header type' do
29
+ let(:options) { {:header => 1} }
30
+
31
+ it { expect { subject }.to raise_error(TTY::InvalidArgument) }
32
+ end
33
+
34
+ end
@@ -3,10 +3,43 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe TTY::Terminal::Color, '#remove' do
6
+ let(:instance) { described_class.new }
7
+
6
8
  let(:string) { "This is a \e[1m\e[34mbold blue text\e[0m" }
7
9
 
10
+ subject { instance.remove string }
11
+
8
12
  it 'remove color from string' do
9
- subject.remove(string).should == "This is a bold blue text"
13
+ should == "This is a bold blue text"
14
+ end
15
+
16
+ context 'with octal in encapsulating brackets' do
17
+ let(:string) { "\[\033[01;32m\]u@h \[\033[01;34m\]W $ \[\033[00m\]" }
18
+
19
+ it { should == 'u@h W $ '}
20
+ end
21
+
22
+ context 'with octal without brackets' do
23
+ let(:string) { "\033[01;32mu@h \033[01;34mW $ \033[00m" }
24
+
25
+ it { should == 'u@h W $ '}
10
26
  end
11
27
 
28
+ context 'with octal with multiple colors' do
29
+ let(:string) { "\e[3;0;0;t\e[8;50;0t" }
30
+
31
+ it { should == "" }
32
+ end
33
+
34
+ context 'with' do
35
+ let(:string ) { "WARN. \x1b[1m&\x1b[0m ERR. \x1b[7m&\x1b[0m" }
36
+
37
+ it { should == 'WARN. & ERR. &' }
38
+ end
39
+
40
+ context 'with escape byte' do
41
+ let(:string) { "This is a \e[1m\e[34mbold blue text\e[0m" }
42
+
43
+ it { should == "This is a bold blue text"}
44
+ end
12
45
  end