tty-progressbar 0.11.0 → 0.12.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/README.md +302 -57
  4. data/examples/failure.rb +14 -0
  5. data/examples/iterator.rb +7 -0
  6. data/examples/multi/main_bar.rb +17 -0
  7. data/examples/multi/simple.rb +15 -0
  8. data/examples/threaded.rb +16 -0
  9. data/lib/tty-progressbar.rb +3 -2
  10. data/lib/tty/progressbar.rb +221 -58
  11. data/lib/tty/progressbar/configuration.rb +4 -0
  12. data/lib/tty/progressbar/converter.rb +2 -1
  13. data/lib/tty/progressbar/formatter.rb +2 -1
  14. data/lib/tty/progressbar/formatter/bar.rb +3 -1
  15. data/lib/tty/progressbar/formatter/byte_rate.rb +2 -1
  16. data/lib/tty/progressbar/formatter/current.rb +2 -1
  17. data/lib/tty/progressbar/formatter/current_byte.rb +2 -1
  18. data/lib/tty/progressbar/formatter/elapsed.rb +2 -1
  19. data/lib/tty/progressbar/formatter/estimated.rb +2 -1
  20. data/lib/tty/progressbar/formatter/mean_byte.rb +2 -1
  21. data/lib/tty/progressbar/formatter/mean_rate.rb +2 -1
  22. data/lib/tty/progressbar/formatter/percent.rb +2 -1
  23. data/lib/tty/progressbar/formatter/rate.rb +2 -1
  24. data/lib/tty/progressbar/formatter/total.rb +2 -1
  25. data/lib/tty/progressbar/formatter/total_byte.rb +2 -1
  26. data/lib/tty/progressbar/meter.rb +2 -1
  27. data/lib/tty/progressbar/multi.rb +221 -0
  28. data/lib/tty/progressbar/version.rb +1 -1
  29. data/spec/unit/events_spec.rb +35 -0
  30. data/spec/unit/formatter/elapsed_spec.rb +0 -1
  31. data/spec/unit/head_spec.rb +34 -0
  32. data/spec/unit/inspect_spec.rb +1 -1
  33. data/spec/unit/iterate_spec.rb +48 -0
  34. data/spec/unit/multi/advance_spec.rb +139 -0
  35. data/spec/unit/multi/events_spec.rb +64 -0
  36. data/spec/unit/multi/finish_spec.rb +19 -0
  37. data/spec/unit/multi/line_inset_spec.rb +67 -0
  38. data/spec/unit/multi/register_spec.rb +36 -0
  39. data/spec/unit/multi/stop_spec.rb +17 -0
  40. data/spec/unit/new_spec.rb +6 -0
  41. data/spec/unit/reset_spec.rb +0 -2
  42. data/spec/unit/stop_spec.rb +21 -0
  43. data/spec/unit/update_spec.rb +24 -0
  44. data/tty-progressbar.gemspec +1 -0
  45. metadata +44 -2
@@ -3,7 +3,7 @@
3
3
  RSpec.describe TTY::ProgressBar, '#inspect' do
4
4
  it "inspects bar properties" do
5
5
  bar = described_class.new("downloading [:bar] :total", total: 30)
6
- expect(bar.inspect).to eq(%q{#<TTY::ProgressBar @format="downloading [:bar] :total", @current="0", @total="30", @width="30", @complete="=", @incomplete=" ", @interval="">})
6
+ expect(bar.inspect).to eq(%q{#<TTY::ProgressBar @format="downloading [:bar] :total", @current="0", @total="30", @width="30", @complete="=", @head="=", @incomplete=" ", @interval="1">})
7
7
  end
8
8
 
9
9
  it "prints string format" do
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar, '#iterate' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "iterates over a collection and yields" do
7
+ bar = TTY::ProgressBar.new("[:bar]", output: output)
8
+ values = []
9
+ bar.iterate(5.times) { |val| values << val}
10
+
11
+ expect(bar.complete?).to eq(true)
12
+ output.rewind
13
+ expect(output.read).to eq([
14
+ "\e[1G[= ]",
15
+ "\e[1G[== ]",
16
+ "\e[1G[=== ]",
17
+ "\e[1G[==== ]",
18
+ "\e[1G[=====]\n"
19
+ ].join)
20
+ expect(values).to eq([0, 1, 2, 3, 4])
21
+ end
22
+
23
+ it "iterates over a collection with a step" do
24
+ bar = TTY::ProgressBar.new("[:bar]", output: output)
25
+ bar.iterate(20.times, 5) { }
26
+
27
+ expect(bar.complete?).to eq(true)
28
+ output.rewind
29
+ expect(output.read).to eq([
30
+ "\e[1G[===== ]",
31
+ "\e[1G[========== ]",
32
+ "\e[1G[=============== ]",
33
+ "\e[1G[====================]\n"
34
+ ].join)
35
+ end
36
+
37
+ it "iterates over a collection and returns enumerable" do
38
+ bar = TTY::ProgressBar.new("[:bar]", output: output)
39
+ values = []
40
+ progress = bar.iterate(5.times)
41
+
42
+ expect(bar.complete?).to eq(false)
43
+
44
+ progress.each { |v| values << v }
45
+
46
+ expect(values).to eq([0,1,2,3,4])
47
+ end
48
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar::Multi, 'advance' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+ let(:save) { TTY::Cursor.save }
6
+ let(:restore) { TTY::Cursor.restore }
7
+ let(:top) { TTY::ProgressBar::Multi::DEFAULT_INSET[:top] }
8
+ let(:middle) { TTY::ProgressBar::Multi::DEFAULT_INSET[:middle] }
9
+ let(:bottom) { TTY::ProgressBar::Multi::DEFAULT_INSET[:bottom] }
10
+
11
+ it "advances progress bars correctly under multibar" do
12
+ bars = TTY::ProgressBar::Multi.new(output: output)
13
+
14
+ bar1 = bars.register("[:bar] one", total: 5)
15
+ bar2 = bars.register("[:bar] two", total: 5)
16
+
17
+ bar2.advance
18
+ bar1.advance
19
+
20
+ output.rewind
21
+ expect(output.read).to eq([
22
+ "\e[1G[= ] two\n",
23
+ "\e[1G[= ] one\n"
24
+ ].join)
25
+
26
+ bar2.advance
27
+
28
+ output.rewind
29
+ expect(output.read).to eq([
30
+ "\e[1G[= ] two\n",
31
+ "\e[1G[= ] one\n",
32
+ save,
33
+ "\e[2A", # up 2 lines
34
+ "\e[1G[== ] two",
35
+ restore
36
+ ].join)
37
+
38
+ bar1.advance
39
+
40
+ output.rewind
41
+ expect(output.read).to eq([
42
+ "\e[1G[= ] two\n",
43
+ "\e[1G[= ] one\n",
44
+ save,
45
+ "\e[2A", # up 2 lines
46
+ "\e[1G[== ] two",
47
+ restore,
48
+ save,
49
+ "\e[1A", # up 1 line
50
+ "\e[1G[== ] one",
51
+ restore
52
+ ].join)
53
+ end
54
+
55
+ it "advances progress bars correctly under top level multibar" do
56
+ bars = TTY::ProgressBar::Multi.new("[:bar] main", output: output)
57
+
58
+ bar1 = bars.register("[:bar] one", total: 5)
59
+ bar2 = bars.register("[:bar] two", total: 5)
60
+
61
+ bars.start
62
+
63
+ bar2.advance
64
+ bar1.advance
65
+
66
+ output.rewind
67
+ expect(output.read).to eq([
68
+ "\e[1G#{top}[ ] main\n",
69
+ "\e[1G#{bottom}[= ] two\n",
70
+ save,
71
+ "\e[2A", # up 2 lines
72
+ "\e[1G#{top}[= ] main",
73
+ restore,
74
+ "\e[1G#{bottom}[= ] one\n",
75
+ save,
76
+ "\e[3A", # up 3 lines
77
+ "\e[1G#{top}[== ] main",
78
+ restore
79
+ ].join)
80
+
81
+ bar2.advance
82
+
83
+ output.rewind
84
+ expect(output.read).to eq([
85
+ "\e[1G#{top}[ ] main\n",
86
+ "\e[1G#{bottom}[= ] two\n",
87
+ save,
88
+ "\e[2A", # up 2 lines
89
+ "\e[1G#{top}[= ] main",
90
+ restore,
91
+ "\e[1G#{bottom}[= ] one\n",
92
+ save,
93
+ "\e[3A", # up 3 lines
94
+ "\e[1G#{top}[== ] main",
95
+ restore,
96
+ save,
97
+ "\e[2A", # up 2 lines,
98
+ "\e[1G#{middle}[== ] two",
99
+ restore,
100
+ save,
101
+ "\e[3A", # up 3 lines
102
+ "\e[1G#{top}[=== ] main",
103
+ restore
104
+ ].join)
105
+
106
+ bar1.advance
107
+
108
+ output.rewind
109
+ expect(output.read).to eq([
110
+ "\e[1G#{top}[ ] main\n",
111
+ "\e[1G#{bottom}[= ] two\n",
112
+ save,
113
+ "\e[2A", # up 2 lines
114
+ "\e[1G#{top}[= ] main",
115
+ restore,
116
+ "\e[1G#{bottom}[= ] one\n",
117
+ save,
118
+ "\e[3A", # up 3 lines
119
+ "\e[1G#{top}[== ] main",
120
+ restore,
121
+ save,
122
+ "\e[2A", # up 2 lines,
123
+ "\e[1G#{middle}[== ] two",
124
+ restore,
125
+ save,
126
+ "\e[3A", # up 3 lines
127
+ "\e[1G#{top}[=== ] main",
128
+ restore,
129
+ save,
130
+ "\e[1A", # up 1 line
131
+ "\e[1G#{bottom}[== ] one",
132
+ restore,
133
+ save,
134
+ "\e[3A", # up 3 lines
135
+ "\e[1G#{top}[==== ] main",
136
+ restore
137
+ ].join)
138
+ end
139
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar::Multi, 'events' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "emits :progress eent when any of the registerd bars advances" do
7
+ events = []
8
+ bars = TTY::ProgressBar::Multi.new("[:bar]", output: output, total: 5)
9
+ bars.on(:progress) { events << :progress }
10
+
11
+ bar = bars.register "one [:bar]"
12
+ bar.advance
13
+
14
+ expect(events).to eq([:progress])
15
+ end
16
+
17
+ it "emits :done event when all progress bars finished" do
18
+ events = []
19
+ bars = TTY::ProgressBar::Multi.new("[:bar]", output: output, total: 5)
20
+ bars.on(:done) { events << :done }
21
+
22
+ bar = bars.register "one [:bar]"
23
+
24
+ bar.finish
25
+
26
+ expect(events).to eq([:done])
27
+ end
28
+
29
+ it "emits :done event when top level bar finished" do
30
+ events = []
31
+ bars = TTY::ProgressBar::Multi.new("[:bar]", output: output, total: 5)
32
+ bars.on(:done) { events << :done }
33
+
34
+ bars.register "one [:bar]"
35
+
36
+ bars.finish
37
+
38
+ expect(events).to eq([:done])
39
+ end
40
+
41
+ it "emits :stopped event when all registerd bars are stopped" do
42
+ events = []
43
+ bars = TTY::ProgressBar::Multi.new("[:bar]", output: output, total: 5)
44
+ bars.on(:stopped) { events << :stopped }
45
+
46
+ bar = bars.register "one [:bar]"
47
+
48
+ bar.stop
49
+
50
+ expect(events).to eq([:stopped])
51
+ end
52
+
53
+ it "emits :stopped event when top level bar finished" do
54
+ events = []
55
+ bars = TTY::ProgressBar::Multi.new("[:bar]", output: output, total: 5)
56
+ bars.on(:stopped) { events << :stopped }
57
+
58
+ bars.register "one [:bar]"
59
+
60
+ bars.stop
61
+
62
+ expect(events).to eq([:stopped])
63
+ end
64
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar::Multi, '#finish' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "finishes all bars" do
7
+ bars = TTY::ProgressBar::Multi.new("main [:bar]", output: output)
8
+
9
+ bar1 = bars.register("[:bar]", total: 5)
10
+ bar2 = bars.register("[:bar]", total: 10)
11
+
12
+ expect(bars.complete?).to eq(false)
13
+
14
+ bar1.finish
15
+ bar2.finish
16
+
17
+ expect(bars.complete?).to eq(true)
18
+ end
19
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar::Multi, '#line_inset' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "doesn't create inset when no top level bar" do
7
+ bars = TTY::ProgressBar::Multi.new(output: output)
8
+
9
+ bar = bars.register 'example'
10
+
11
+ expect(bars.line_inset(bar)).to eq('')
12
+ end
13
+
14
+ it "defaults to the empty string for the top level bar" do
15
+ bars = TTY::ProgressBar::Multi.new("Top level spinner", output: output)
16
+
17
+ expect(bars.line_inset(bars.top_bar))
18
+ .to eq(TTY::ProgressBar::Multi::DEFAULT_INSET[:top])
19
+ end
20
+
21
+ it "returns middle character for a top level bar" do
22
+ bars = TTY::ProgressBar::Multi.new("Top level bar", output: output)
23
+
24
+ bar = bars.register 'middle', total: 10
25
+ bar2 = bars.register 'bottom', total: 10
26
+
27
+ bar.start
28
+ bar2.start
29
+
30
+ expect(bars.line_inset(bar))
31
+ .to eq(TTY::ProgressBar::Multi::DEFAULT_INSET[:middle])
32
+ end
33
+
34
+ it "decorates last bar" do
35
+ bars = TTY::ProgressBar::Multi.new("Top spinner", output: output)
36
+
37
+ bar1 = bars.register 'middle', total: 10
38
+ bar = bars.register 'bottom', total: 10
39
+
40
+ bar1.start
41
+ bar.start
42
+
43
+ expect(bars.line_inset(bar))
44
+ .to eq(TTY::ProgressBar::Multi::DEFAULT_INSET[:bottom])
45
+ end
46
+
47
+ it "allows customization" do
48
+ opts = {
49
+ output: output,
50
+ style: {
51
+ top: ". ",
52
+ middle: "--",
53
+ bottom: "---",
54
+ }
55
+ }
56
+ bars = TTY::ProgressBar::Multi.new("Top level spinner", opts)
57
+ middle_bar = bars.register "", total: 10
58
+ bottom_bar = bars.register "", total: 10
59
+
60
+ middle_bar.start
61
+ bottom_bar.start
62
+
63
+ expect(bars.line_inset(bars.top_bar)).to eq(". ")
64
+ expect(bars.line_inset(middle_bar)).to eq("--")
65
+ expect(bars.line_inset(bottom_bar)).to eq("---")
66
+ end
67
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar::Multi, '#register' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "registers a TTY::ProgressBar instance" do
7
+ bars = TTY::ProgressBar::Multi.new(output: output)
8
+ allow_any_instance_of(TTY::ProgressBar).to receive(:attach_to)
9
+ expect_any_instance_of(TTY::ProgressBar).to receive(:attach_to)
10
+
11
+ bar = bars.register("[:bar]")
12
+
13
+ expect(bar).to be_instance_of(TTY::ProgressBar)
14
+ expect(bars.length).to eq(1)
15
+ end
16
+
17
+ it "uses global options to register instance" do
18
+ bars = TTY::ProgressBar::Multi.new(output: output, total: 100)
19
+ bar = double(:bar, attach_to: nil)
20
+ allow(TTY::ProgressBar).to receive(:new).and_return(bar)
21
+
22
+ bars.register("[:bar]")
23
+
24
+ expect(TTY::ProgressBar).to have_received(:new).with("[:bar]", {total: 100, output: output})
25
+ end
26
+
27
+ it "registers bars with top level" do
28
+ bars = TTY::ProgressBar::Multi.new("main [:bar]", output: output)
29
+
30
+ bars.register("[:bar]", total: 5)
31
+ bars.register("[:bar]", total: 10)
32
+
33
+ expect(bars.total).to eq(15)
34
+ expect(bars.current).to eq(0)
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar::Multi, '#stop' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it "stops all bars when top level stops" do
7
+ bars = TTY::ProgressBar::Multi.new("main [:bar]", output: output)
8
+
9
+ bar1 = bars.register("[:bar]", total: 5)
10
+ bar2 = bars.register("[:bar]", total: 10)
11
+
12
+ bars.stop
13
+
14
+ expect(bar1.stopped?).to eq(true)
15
+ expect(bar2.stopped?).to eq(true)
16
+ end
17
+ end
@@ -3,6 +3,12 @@
3
3
  RSpec.describe TTY::ProgressBar, '::new' do
4
4
  let(:output) { StringIO.new('', 'w+') }
5
5
 
6
+ it "fails to initialize without formatting string" do
7
+ expect {
8
+ TTY::ProgressBar.new(output: output)
9
+ }.to raise_error(ArgumentError, /Expected bar formatting string, got `{:output=>#{output}}` instead\./)
10
+ end
11
+
6
12
  it "displays output where width == total" do
7
13
  progress = TTY::ProgressBar.new("[:bar]", output: output, total: 10)
8
14
  progress.advance
@@ -11,7 +11,6 @@ RSpec.describe TTY::ProgressBar, '#reset' do
11
11
  output.rewind
12
12
  expect(output.read).to eq([
13
13
  "\e[1G[===== ]",
14
- "\e[1G[ ]",
15
14
  "\e[1G[=== ]",
16
15
  "\e[1G[====== ]"
17
16
  ].join)
@@ -27,7 +26,6 @@ RSpec.describe TTY::ProgressBar, '#reset' do
27
26
  output.rewind
28
27
  expect(output.read).to eq([
29
28
  "\e[1G[==========]\n",
30
- "\e[1G[ ]",
31
29
  "\e[1G[=== ]",
32
30
  "\e[1G[====== ]"
33
31
  ].join)
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ RSpec.describe TTY::ProgressBar, '#stop' do
4
+ let(:output) { StringIO.new('', 'w+') }
5
+
6
+ it 'stops progress' do
7
+ progress = TTY::ProgressBar.new("[:bar]", output: output, total: 10)
8
+ 5.times { |i|
9
+ progress.stop if i == 3
10
+ progress.advance
11
+ }
12
+ expect(progress.complete?).to be(false)
13
+ output.rewind
14
+ expect(output.read).to eq([
15
+ "\e[1G[= ]",
16
+ "\e[1G[== ]",
17
+ "\e[1G[=== ]",
18
+ "\e[1G[=== ]\n"
19
+ ].join)
20
+ end
21
+ end