progress_bar 1.0.5 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/progress_bar.rb CHANGED
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
1
2
 
2
- require 'options'
3
- require 'highline'
3
+ require "options"
4
+ require "highline"
4
5
 
5
6
  class ProgressBar
6
7
  Error = Class.new(StandardError)
@@ -9,34 +10,41 @@ class ProgressBar
9
10
  attr_accessor :count, :max, :meters
10
11
 
11
12
  def initialize(*args)
12
-
13
13
  @count = 0
14
14
  @max = 100
15
15
  @meters = [:bar, :counter, :percentage, :elapsed, :eta, :rate]
16
16
 
17
- @max = args.shift if args.first.is_a? Numeric
18
- raise ArgumentError, "Max must be a positive integer" unless @max > 0
17
+ @max = args.shift if args.first.is_a? Numeric
18
+ raise ArgumentError, "Max must be a positive integer" unless @max >= 0
19
19
 
20
- @meters = args unless args.empty?
20
+ @meters = args unless args.empty?
21
21
 
22
22
  @last_write = ::Time.at(0)
23
23
  @start = ::Time.now
24
24
 
25
- @hl = HighLine.new
25
+ @hl = HighLine.new
26
+ @terminal_width = 80
27
+ @last_width_adjustment = ::Time.at(0)
26
28
  end
27
29
 
28
30
  def increment!(count = 1)
29
- self.count += count
31
+ @count += count
30
32
  now = ::Time.now
31
- if (now - @last_write) > 0.2 || self.count >= max
33
+ if (now - @last_write) > 0.2 || @count >= max
32
34
  write
33
35
  @last_write = now
34
36
  end
35
37
  end
36
38
 
37
- def write
39
+ def puts(text)
38
40
  clear!
39
- print to_s
41
+ $stderr.write(text)
42
+ $stderr.puts
43
+ write
44
+ end
45
+
46
+ def write
47
+ print "\r" + to_s
40
48
  end
41
49
 
42
50
  def remaining
@@ -73,8 +81,8 @@ class ProgressBar
73
81
 
74
82
  def to_s
75
83
  self.count = max if count > max
76
- meters.inject("") do |text, meter|
77
- text << render(meter) + " "
84
+ meters.inject(String.new) do |text, meter|
85
+ text << "#{render(meter)} "
78
86
  end.strip
79
87
  end
80
88
 
@@ -85,7 +93,7 @@ class ProgressBar
85
93
  end
86
94
 
87
95
  def clear!
88
- print "\r"
96
+ print "\r" + " " * terminal_width + "\r"
89
97
  end
90
98
 
91
99
  def render(meter)
@@ -97,13 +105,11 @@ class ProgressBar
97
105
  end
98
106
 
99
107
  def render_bar
100
- return '' if bar_width < 2
108
+ return "" if bar_width < 2
109
+
101
110
  progress_width = (ratio * (bar_width - 2)).floor
102
111
  remainder_width = bar_width - 2 - progress_width
103
- "[" +
104
- "#" * progress_width +
105
- " " * remainder_width +
106
- "]"
112
+ "[#{'#' * progress_width}#{' ' * remainder_width}]"
107
113
  end
108
114
 
109
115
  def render_counter
@@ -124,20 +130,17 @@ class ProgressBar
124
130
  end
125
131
 
126
132
  def render_rate
127
- "[%#{max_width+3}.2f/s]" % rate
133
+ "[%#{max_width + 3}.2f/s]" % rate
128
134
  end
129
135
 
130
136
  def terminal_width
131
137
  # HighLine check takes a long time, so only update width every second.
132
- if @terminal_width.nil? || @last_width_adjustment.nil? ||
133
- ::Time.now - @last_width_adjustment > 1
134
-
135
- @last_width_adjustment = ::Time.now
136
- @terminal_width = @hl.output_cols.to_i
137
- if @terminal_width < 1
138
- @terminal_width = 80
139
- end
140
- @terminal_width
138
+ now = ::Time.now
139
+ if now - @last_width_adjustment > 1
140
+ @last_width_adjustment = now
141
+ new_width = @hl.output_cols.to_i
142
+ new_width = 80 if new_width < 1
143
+ @terminal_width = new_width
141
144
  else
142
145
  @terminal_width
143
146
  end
@@ -148,12 +151,12 @@ class ProgressBar
148
151
  end
149
152
 
150
153
  def non_bar_width
151
- meters.reject { |m| m == :bar }.inject(0) do |width, meter|
154
+ meters.reject { |meter| meter == :bar }.inject(0) do |width, meter|
152
155
  width += width_of(meter) + 1
153
156
  end
154
157
  end
155
158
 
156
- def counter_width # [ 1/100]
159
+ def counter_width # [ 1/100]
157
160
  max_width * 2 + 3
158
161
  end
159
162
 
@@ -181,12 +184,15 @@ class ProgressBar
181
184
  max.to_s.length
182
185
  end
183
186
 
187
+ HOUR = 3600
188
+ MINUTE = 60
184
189
  def format_interval(interval)
185
- if interval > 3600
186
- "%02i:%02i:%02i" % [interval/3600, interval%3600/60, interval%60]
190
+ if interval > HOUR
191
+ "%02i:%02i:%02i" % [interval / HOUR, interval % HOUR / MINUTE, interval % MINUTE]
187
192
  else
188
- "%02i:%02i" % [interval/60, interval%60]
193
+ "%02i:%02i" % [interval / MINUTE, interval % MINUTE]
189
194
  end
190
195
  end
191
-
192
196
  end
197
+
198
+ require_relative "progress_bar/with_progress"
data/progress_bar.gemspec CHANGED
@@ -1,6 +1,6 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "progress_bar/version"
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/progress_bar/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "progress_bar"
@@ -9,16 +9,20 @@ Gem::Specification.new do |s|
9
9
  s.authors = ["Paul Sadauskas"]
10
10
  s.email = ["psadauskas@gmail.com"]
11
11
  s.homepage = "http://github.com/paul/progress_bar"
12
- s.summary = %q{Simple Progress Bar for output to a terminal}
13
- s.description = %q{Give people feedback about long-running tasks without overloading them with information: Use a progress bar, like Curl or Wget!}
12
+ s.license = "WTFPL"
13
+ s.summary = "Simple Progress Bar for output to a terminal"
14
+ s.description = "Give people feedback about long-running tasks without overloading them with information: Use a progress bar, like Curl or Wget!"
14
15
 
15
- s.rubyforge_project = "progress_bar"
16
+ s.required_ruby_version = ">= 2.4.0"
16
17
 
17
- s.add_dependency('options', '~> 2.3.0')
18
- s.add_dependency('highline', '~> 1.6')
18
+ s.add_dependency("highline", [">= 1.6", "< 3"])
19
+ s.add_dependency("options", "~> 2.3.0")
19
20
 
20
21
  s.add_development_dependency("rake")
22
+ s.add_development_dependency("reek")
21
23
  s.add_development_dependency("rspec")
24
+ s.add_development_dependency("rubocop")
25
+ s.add_development_dependency("rubocop-rspec")
22
26
  s.add_development_dependency("timecop")
23
27
 
24
28
  s.files = `git ls-files`.split("\n")
@@ -1,40 +1,37 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'ProgressBar arguments' do
4
- before do
5
- @default_max = 100
6
- @default_meters = [:bar, :counter, :percentage, :elapsed, :eta, :rate]
7
- end
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar arguments" do
6
+ let(:default_max) { 100 }
7
+ let(:default_meters) { [:bar, :counter, :percentage, :elapsed, :eta, :rate] }
8
8
 
9
9
  it "should set appropriate defaults without any arguments" do
10
10
  bar = ProgressBar.new
11
- bar.max.should == @default_max
12
- bar.meters.should == @default_meters
11
+ expect(bar.max).to eq default_max
12
+ expect(bar.meters).to eq default_meters
13
13
  end
14
14
 
15
15
  it "should allow a single argument specifying the max" do
16
16
  bar = ProgressBar.new(123)
17
- bar.max.should == 123
18
- bar.meters.should == @default_meters
17
+ expect(bar.max).to eq 123
18
+ expect(bar.meters).to eq default_meters
19
19
  end
20
20
 
21
21
  it "should allow specifying just the meters" do
22
22
  bar = ProgressBar.new(:bar, :eta)
23
- bar.max.should == @default_max
24
- bar.meters.should == [:bar, :eta]
23
+ expect(bar.max).to eq default_max
24
+ expect(bar.meters).to eq [:bar, :eta]
25
25
  end
26
26
 
27
27
  it "should allow specyfing the max and meters" do
28
28
  bar = ProgressBar.new(123, :bar, :eta)
29
- bar.max.should == 123
30
- bar.meters.should == [:bar, :eta]
29
+ expect(bar.max).to eq 123
30
+ expect(bar.meters).to eq [:bar, :eta]
31
31
  end
32
32
 
33
33
  it "should raise an error when initial max is nonsense" do
34
- lambda {
35
- bar = ProgressBar.new(0)
36
- }.should raise_error(ProgressBar::ArgumentError)
34
+ expect { ProgressBar.new(-1) }
35
+ .to raise_error(ProgressBar::ArgumentError)
37
36
  end
38
-
39
37
  end
40
-
data/spec/bar_spec.rb CHANGED
@@ -1,37 +1,39 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'ProgressBar bar output' do
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar bar output" do
4
6
  let(:max) { 100 }
5
7
  let(:terminal_width) { 12 }
6
8
 
7
9
  let(:progress_bar) { ProgressBar.new(max, :bar) }
8
10
 
9
11
  before do
10
- progress_bar.stub(:terminal_width) { terminal_width }
12
+ allow(progress_bar).to receive(:terminal_width).and_return(terminal_width)
11
13
  progress_bar.count = count
12
14
  end
13
15
 
14
16
  subject { progress_bar.to_s }
15
17
 
16
- describe 'at count=0' do
18
+ describe "at count=0" do
17
19
  let(:count) { 0 }
18
20
 
19
21
  it { should == "[ ]" }
20
22
  end
21
23
 
22
- describe 'at count=50' do
24
+ describe "at count=50" do
23
25
  let(:count) { 50 }
24
26
 
25
27
  it { should == "[##### ]" }
26
28
  end
27
29
 
28
- describe 'at count=100' do
30
+ describe "at count=100" do
29
31
  let(:count) { 100 }
30
32
 
31
33
  it { should == "[##########]" }
32
34
  end
33
35
 
34
- describe 'at count=25 (non-integer divide, should round down)' do
36
+ describe "at count=25 (non-integer divide, should round down)" do
35
37
  let(:count) { 25 }
36
38
 
37
39
  it { should == "[## ]" }
@@ -50,6 +52,4 @@ describe 'ProgressBar bar output' do
50
52
  end
51
53
  end
52
54
  end
53
-
54
55
  end
55
-
data/spec/counter_spec.rb CHANGED
@@ -1,50 +1,45 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'ProgressBar counter output' do
4
- before do
5
- @progress_bar = ProgressBar.new(100, :counter)
6
- end
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar counter output" do
6
+ let(:progress_bar) { ProgressBar.new(100, :counter) }
7
7
 
8
- subject { @progress_bar.to_s }
8
+ subject { progress_bar.to_s }
9
9
 
10
- describe 'at count=0' do
10
+ describe "at count=0" do
11
11
  before do
12
- @progress_bar.count = 0
12
+ progress_bar.count = 0
13
13
  end
14
14
 
15
15
  it { should == "[ 0/100]" }
16
16
  end
17
17
 
18
- describe 'at count=50' do
18
+ describe "at count=50" do
19
19
  before do
20
- @progress_bar.count = 50
20
+ progress_bar.count = 50
21
21
  end
22
22
 
23
23
  it { should == "[ 50/100]" }
24
24
  end
25
25
 
26
- describe 'at count=100' do
26
+ describe "at count=100" do
27
27
  before do
28
- @progress_bar.count = 100
28
+ progress_bar.count = 100
29
29
  end
30
30
 
31
31
  it { should == "[100/100]" }
32
32
  end
33
33
 
34
- describe 'with a shorter max' do
35
- before do
36
- @progress_bar = ProgressBar.new(42, :counter)
37
- end
34
+ describe "with a shorter max" do
35
+ let(:progress_bar) { ProgressBar.new(42, :counter) }
38
36
 
39
- it { should == '[ 0/42]' }
37
+ it { should == "[ 0/42]" }
40
38
  end
41
39
 
42
- describe 'with a longer max' do
43
- before do
44
- @progress_bar = ProgressBar.new(4242, :counter)
45
- end
40
+ describe "with a longer max" do
41
+ let(:progress_bar) { ProgressBar.new(4242, :counter) }
46
42
 
47
- it { should == '[ 0/4242]' }
43
+ it { should == "[ 0/4242]" }
48
44
  end
49
-
50
45
  end
data/spec/elapsed_spec.rb CHANGED
@@ -1,48 +1,50 @@
1
+ # frozen_string_literal: true
1
2
 
2
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar elapsed output" do
6
+ let(:progress_bar) { ProgressBar.new(100, :elapsed) }
3
7
 
4
- describe 'ProgressBar elapsed output' do
5
8
  before do
6
9
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 0)
7
- @progress_bar = ProgressBar.new(100, :elapsed)
10
+ progress_bar
8
11
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 10) # 10 seconds later
9
12
  end
10
13
 
11
- subject { @progress_bar.to_s }
14
+ subject { progress_bar.to_s }
12
15
 
13
- describe 'at count=0' do
16
+ describe "at count=0" do
14
17
  before do
15
- @progress_bar.count = 0
18
+ progress_bar.count = 0
16
19
  end
17
20
 
18
21
  it { should == "[00:10]" }
19
22
  end
20
23
 
21
- describe 'at count=50' do
24
+ describe "at count=50" do
22
25
  before do
23
- @progress_bar.count = 50
26
+ progress_bar.count = 50
24
27
  end
25
28
 
26
29
  it { should == "[00:10]" }
27
30
  end
28
31
 
29
- describe 'at count=100' do
32
+ describe "at count=100" do
30
33
  before do
31
- @progress_bar.count = 100
34
+ progress_bar.count = 100
32
35
  end
33
36
 
34
37
  it { should == "[00:10]" }
35
38
  end
36
39
 
37
- describe 'with times over 1 hour' do
40
+ describe "with times over 1 hour" do
41
+ let(:progress_bar) { ProgressBar.new(42, :elapsed) }
42
+
38
43
  before do
39
44
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 0)
40
- @progress_bar = ProgressBar.new(42, :elapsed)
41
45
  Timecop.freeze Time.utc(2010, 3, 10, 2, 0, 0) # 2 hours later
42
46
  end
43
47
 
44
- it { should == '[02:00:00]' }
48
+ it { should == "[02:00:00]" }
45
49
  end
46
-
47
50
  end
48
-
data/spec/eta_spec.rb CHANGED
@@ -1,50 +1,51 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar eta output" do
6
+ let(:progress_bar) { ProgressBar.new(100, :eta) }
2
7
 
3
- describe 'ProgressBar eta output' do
4
8
  before do
5
9
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 0)
6
- @progress_bar = ProgressBar.new(100, :eta)
10
+ progress_bar
7
11
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 10) # 10 seconds later
8
12
  end
9
13
 
10
- subject { @progress_bar.to_s }
14
+ subject { progress_bar.to_s }
11
15
 
12
- describe 'at count=0' do
16
+ describe "at count=0" do
13
17
  before do
14
- @progress_bar.count = 0
18
+ progress_bar.count = 0
15
19
  end
16
20
 
17
21
  it { should == "[00:00]" }
18
22
  end
19
23
 
20
- describe 'at count=50' do
24
+ describe "at count=50" do
21
25
  before do
22
- @progress_bar.count = 50
26
+ progress_bar.count = 50
23
27
  end
24
28
 
25
29
  it { should == "[00:10]" }
26
30
  end
27
31
 
28
- describe 'at count=100' do
32
+ describe "at count=100" do
29
33
  before do
30
- @progress_bar.count = 100
34
+ progress_bar.count = 100
31
35
  end
32
36
 
33
37
  it { should == "[00:00]" }
34
38
  end
35
39
 
36
- describe 'with times over 1 hour' do
40
+ describe "with times over 1 hour" do
41
+ let(:progress_bar) { ProgressBar.new(42, :eta) }
42
+
37
43
  before do
38
44
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 0)
39
- @progress_bar = ProgressBar.new(42, :eta)
40
- @progress_bar.count = 21
45
+ progress_bar.count = 21
41
46
  Timecop.freeze Time.utc(2010, 3, 10, 2, 0, 0) # 2 hours later
42
47
  end
43
48
 
44
- it { should == '[02:00:00]' }
49
+ it { should == "[02:00:00]" }
45
50
  end
46
-
47
51
  end
48
-
49
-
50
-
@@ -1,44 +1,43 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'ProgressBar percentage output' do
4
- before do
5
- @progress_bar = ProgressBar.new(100, :percentage)
6
- end
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar percentage output" do
6
+ let(:progress_bar) { ProgressBar.new(100, :percentage) }
7
7
 
8
- subject { @progress_bar.to_s }
8
+ subject { progress_bar.to_s }
9
9
 
10
- describe 'at count=0' do
10
+ describe "at count=0" do
11
11
  before do
12
- @progress_bar.count = 0
12
+ progress_bar.count = 0
13
13
  end
14
14
 
15
15
  it { should == "[ 0%]" }
16
16
  end
17
17
 
18
- describe 'at count=50' do
18
+ describe "at count=50" do
19
19
  before do
20
- @progress_bar.count = 50
20
+ progress_bar.count = 50
21
21
  end
22
22
 
23
23
  it { should == "[ 50%]" }
24
24
  end
25
25
 
26
- describe 'at count=100' do
26
+ describe "at count=100" do
27
27
  before do
28
- @progress_bar.count = 100
28
+ progress_bar.count = 100
29
29
  end
30
30
 
31
31
  it { should == "[100%]" }
32
32
  end
33
33
 
34
- describe 'with a max that is not 100' do
34
+ describe "with a max that is not 100" do
35
+ let(:progress_bar) { ProgressBar.new(42, :percentage) }
36
+
35
37
  before do
36
- @progress_bar = ProgressBar.new(42, :percentage)
37
- @progress_bar.count = 21
38
+ progress_bar.count = 21
38
39
  end
39
40
 
40
- it { should == '[ 50.00%]' }
41
+ it { should == "[ 50.00%]" }
41
42
  end
42
-
43
43
  end
44
-
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "ProgressBar print output" do
6
+ let(:progress_bar) { ProgressBar.new(:counter) }
7
+
8
+ before do
9
+ allow(progress_bar).to receive(:terminal_width).and_return(10)
10
+ end
11
+
12
+ it "should replace the current bar with the text, and continue the bar on the next line" do
13
+ expect {
14
+ progress_bar.increment!
15
+ progress_bar.puts("Hello, world!")
16
+ }.to output("\r[ 1/100]" \
17
+ "\r#{' ' * 10}" \
18
+ "\rHello, world!\n" \
19
+ "\r[ 1/100]").to_stderr
20
+ end
21
+ end
@@ -1,47 +1,47 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
4
+
5
+ describe "ProgressBar bar output" do
6
+ let(:progress_bar) { ProgressBar.new(100) }
2
7
 
3
- describe 'ProgressBar bar output' do
4
8
  before do
5
9
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 0)
6
- @progress_bar = ProgressBar.new(100)
7
- @progress_bar.stub(:terminal_width) { 60 }
10
+ allow(progress_bar).to receive(:terminal_width).and_return(60)
8
11
  Timecop.freeze Time.utc(2010, 3, 10, 0, 0, 10) # 10 seconds later
9
12
  end
10
13
 
11
- subject { @progress_bar.to_s }
14
+ subject { progress_bar.to_s }
12
15
 
13
- describe 'at count=0' do
16
+ describe "at count=0" do
14
17
  before do
15
- @progress_bar.count = 0
18
+ progress_bar.count = 0
16
19
  end
17
20
 
18
21
  it { should == "[ ] [ 0/100] [ 0%] [00:10] [00:00] [ 0.00/s]" }
19
22
  end
20
23
 
21
- describe 'at count=50' do
24
+ describe "at count=50" do
22
25
  before do
23
- @progress_bar.count = 50
26
+ progress_bar.count = 50
24
27
  end
25
28
 
26
29
  it { should == "[####### ] [ 50/100] [ 50%] [00:10] [00:10] [ 5.00/s]" }
27
30
  end
28
31
 
29
- describe 'at count=100' do
32
+ describe "at count=100" do
30
33
  before do
31
- @progress_bar.count = 100
34
+ progress_bar.count = 100
32
35
  end
33
36
 
34
37
  it { should == "[##############] [100/100] [100%] [00:10] [00:00] [ 10.00/s]" }
35
38
  end
36
39
 
37
- describe 'at count=105' do
40
+ describe "at count=105" do
38
41
  before do
39
- @progress_bar.count = 105
42
+ progress_bar.count = 105
40
43
  end
41
44
 
42
45
  it { should == "[##############] [100/100] [100%] [00:10] [00:00] [ 10.00/s]" }
43
46
  end
44
-
45
47
  end
46
-
47
-