progress 0.4.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 1.0.0
data/lib/progress.rb CHANGED
@@ -12,17 +12,22 @@ class Progress
12
12
  elsif total.nil?
13
13
  total = 1
14
14
  end
15
- total = Float(total)
16
- @title, @current, @total = title, 0.0, total == 0.0 ? 1.0 : total
15
+ @title = title
16
+ @current = 0.0
17
+ @total = total == 0.0 ? 1.0 : Float(total)
17
18
  end
18
19
 
19
20
  def step_if_blank
20
- self.current = 1.0 if current == 0.0 && total == 1.0
21
+ if current == 0.0 && total == 1.0
22
+ self.current = 1.0
23
+ end
21
24
  end
22
25
 
23
26
  def to_f(inner)
24
27
  inner = [inner, 1.0].min
25
- inner *= current_step if current_step
28
+ if current_step
29
+ inner *= current_step
30
+ end
26
31
  (current + inner) / total
27
32
  end
28
33
 
@@ -65,6 +70,10 @@ class Progress
65
70
  # ==== To force highlight
66
71
  # Progress.highlight = true
67
72
  def start(title = nil, total = nil)
73
+ if levels.empty?
74
+ @started_at = Time.now
75
+ @eta = nil
76
+ end
68
77
  levels << new(title, total)
69
78
  print_message(true)
70
79
  if block_given?
@@ -76,32 +85,37 @@ class Progress
76
85
  end
77
86
  end
78
87
 
79
- def step(steps = 1)
88
+ def step(steps = 1, &block)
80
89
  if levels.last
81
- if block_given?
82
- levels.last.step(steps) do
83
- yield
84
- end
85
- end
86
- levels.last.current += Float(steps)
87
- print_message
88
- elsif block_given?
89
- yield
90
+ set(levels.last.current + Float(steps), &block)
91
+ elsif block
92
+ block.call
90
93
  end
91
94
  end
92
95
 
93
- def set(value)
96
+ def set(value, &block)
94
97
  if levels.last
98
+ ret = if block
99
+ levels.last.step(value - levels.last.current, &block)
100
+ end
95
101
  levels.last.current = Float(value)
96
102
  print_message
103
+ ret
104
+ elsif block
105
+ block.call
97
106
  end
98
107
  end
99
108
 
100
109
  def stop
101
110
  if levels.last
102
- print_message(true) if levels.last.step_if_blank || levels.length == 1
111
+ if levels.last.step_if_blank || levels.length == 1
112
+ print_message(true)
113
+ set_title(nil)
114
+ end
103
115
  levels.pop
104
- io.puts if levels.empty?
116
+ if levels.empty?
117
+ io.puts
118
+ end
105
119
  end
106
120
  end
107
121
 
@@ -134,43 +148,72 @@ class Progress
134
148
  end
135
149
 
136
150
  def time_to_print?
137
- if @previous
138
- if @previous < Time.now - 0.3
139
- @previous = Time.now
140
- true
141
- else
142
- false
143
- end
144
- else
151
+ if !@previous || @previous < Time.now - 0.3
145
152
  @previous = Time.now
146
153
  true
147
154
  end
148
155
  end
149
156
 
157
+ def eta(completed)
158
+ now = Time.now
159
+ if now > @started_at && completed > 0
160
+ current_eta = @started_at + (now - @started_at) / completed
161
+ @eta = @eta ? @eta + (current_eta - @eta) * (1 + completed) * 0.5 : current_eta
162
+ seconds = @eta - now
163
+ if seconds > 0
164
+ left = case seconds
165
+ when 0...60
166
+ '%.0fs' % seconds
167
+ when 60...3600
168
+ '%.1fm' % (seconds / 60)
169
+ when 3600...86400
170
+ '%.1fh' % (seconds / 3600)
171
+ else
172
+ '%.1fd' % (seconds / 86400)
173
+ end
174
+ eta_string = " (ETA: #{left})"
175
+ end
176
+ end
177
+ end
178
+
179
+ def set_title(title)
180
+ if io_tty?
181
+ io.print("\e]0;#{title}\a")
182
+ end
183
+ end
184
+
150
185
  def print_message(force = false)
151
186
  if force || time_to_print?
152
- messages = []
153
187
  inner = 0
188
+ parts = []
189
+ parts_cl = []
154
190
  levels.reverse.each do |l|
155
191
  current = l.to_f(inner)
156
192
  value = current == 0 ? '......' : "#{'%5.1f' % (current * 100.0)}%"
157
- messages << "#{"#{l.title}: " if l.title}#{!highlight? || value == '100.0%' ? value : "\e[1m#{value}\e[0m"}"
158
193
  inner = current
194
+
195
+ title = l.title ? "#{l.title}: " : ''
196
+ highlighted = "\e[1m#{value}\e[0m"
197
+ if !highlight? || value == '100.0%'
198
+ parts << "#{title}#{value}"
199
+ else
200
+ parts << "#{title}#{highlighted}"
201
+ end
202
+ parts_cl << "#{title}#{value}"
159
203
  end
160
- message = messages.reverse * ' > '
204
+
205
+ eta_string = eta(inner)
206
+ message = "#{parts.reverse * ' > '}#{eta_string}"
207
+ message_cl = "#{parts_cl.reverse * ' > '}#{eta_string}"
161
208
 
162
209
  unless lines?
163
210
  previous_length = @previous_length || 0
164
- message_cl = if highlight?
165
- message.gsub(/\033\[(0|1)m/, '')
166
- else
167
- message
168
- end
169
211
  @previous_length = message_cl.length
170
212
  message = "#{message}#{' ' * [previous_length - message_cl.length, 0].max}\r"
171
213
  end
172
214
 
173
215
  lines? ? io.puts(message) : io.print(message)
216
+ set_title(message_cl)
174
217
  end
175
218
  end
176
219
  end
data/progress.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{progress}
8
- s.version = "0.4.1"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Boba Fat"]
12
- s.date = %q{2010-11-13}
12
+ s.date = %q{2010-11-14}
13
13
  s.extra_rdoc_files = [
14
14
  "README.rdoc"
15
15
  ]
@@ -15,6 +15,10 @@ describe Progress do
15
15
  s
16
16
  end
17
17
 
18
+ def io_pop_no_eta
19
+ io_pop.sub(/ \(ETA: \d+.\)$/, '')
20
+ end
21
+
18
22
  def verify_output_before_step(i)
19
23
  io_pop.should =~ /#{Regexp.quote(i == 0 ? '......' : (i / 10.0).to_s)}/
20
24
  end
@@ -109,6 +113,18 @@ describe Progress do
109
113
  end.should == 'qwerty'
110
114
  end
111
115
 
116
+ it "should return result from step" do
117
+ Progress.start do
118
+ Progress.step{ 'qwerty' }.should == 'qwerty'
119
+ end
120
+ end
121
+
122
+ it "should return result from set" do
123
+ Progress.start do
124
+ Progress.set(1){ 'qwerty' }.should == 'qwerty'
125
+ end
126
+ end
127
+
112
128
  it "should return result from nested block" do
113
129
  [1, 2, 3].with_progress('a').map do |a|
114
130
  [1, 2, 3].with_progress('b').map do |b|
@@ -132,28 +148,28 @@ describe Progress do
132
148
  end
133
149
  end
134
150
 
135
- [[2, 2000], [20, 200], [200, 20], [2000, 2]].each do |_a, _b|
151
+ [[2, 200], [20, 20], [200, 2]].each do |_a, _b|
136
152
  it "should allow enclosed progress [#{_a}, #{_b}]" do
137
153
  _a.times_with_progress('A') do |a|
138
- io_pop.should == "A: #{a == 0 ? '......' : '%5.1f%%'}\n" % [a / _a.to_f * 100.0]
154
+ io_pop_no_eta.should == "A: #{a == 0 ? '......' : '%5.1f%%'}\n" % [a / _a.to_f * 100.0]
139
155
  _b.times_with_progress('B') do |b|
140
- io_pop.should == "A: #{a == 0 && b == 0 ? '......' : '%5.1f%%'} > B: #{b == 0 ? '......' : '%5.1f%%'}\n" % [(a + b / _b.to_f) / _a.to_f * 100.0, b / _b.to_f * 100.0]
156
+ io_pop_no_eta.should == "A: #{a == 0 && b == 0 ? '......' : '%5.1f%%'} > B: #{b == 0 ? '......' : '%5.1f%%'}\n" % [(a + b / _b.to_f) / _a.to_f * 100.0, b / _b.to_f * 100.0]
141
157
  end
142
- io_pop.should == "A: %5.1f%% > B: 100.0%%\n" % [(a + 1) / _a.to_f * 100.0]
158
+ io_pop_no_eta.should == "A: %5.1f%% > B: 100.0%%\n" % [(a + 1) / _a.to_f * 100.0]
143
159
  end
144
160
  io_pop.should == "A: 100.0%\nA: 100.0%\n\n"
145
161
  end
146
162
 
147
163
  it "should not overlap outer progress if inner exceeds [#{_a}, #{_b}]" do
148
164
  _a.times_with_progress('A') do |a|
149
- io_pop.should == "A: #{a == 0 ? '......' : '%5.1f%%'}\n" % [a / _a.to_f * 100.0]
165
+ io_pop_no_eta.should == "A: #{a == 0 ? '......' : '%5.1f%%'}\n" % [a / _a.to_f * 100.0]
150
166
  Progress.start('B', _b) do
151
167
  (_b * 2).times do |b|
152
- io_pop.should == "A: #{a == 0 && b == 0 ? '......' : '%5.1f%%'} > B: #{b == 0 ? '......' : '%5.1f%%'}\n" % [(a + [b / _b.to_f, 1].min) / _a.to_f * 100.0, b / _b.to_f * 100.0]
168
+ io_pop_no_eta.should == "A: #{a == 0 && b == 0 ? '......' : '%5.1f%%'} > B: #{b == 0 ? '......' : '%5.1f%%'}\n" % [(a + [b / _b.to_f, 1].min) / _a.to_f * 100.0, b / _b.to_f * 100.0]
153
169
  Progress.step
154
170
  end
155
171
  end
156
- io_pop.should == "A: %5.1f%% > B: 200.0%%\n" % [(a + 1) / _a.to_f * 100.0]
172
+ io_pop_no_eta.should == "A: %5.1f%% > B: 200.0%%\n" % [(a + 1) / _a.to_f * 100.0]
157
173
  end
158
174
  io_pop.should == "A: 100.0%\nA: 100.0%\n\n"
159
175
  end
@@ -161,15 +177,15 @@ describe Progress do
161
177
  it "should allow step with block to validly count custom progresses [#{_a}, #{_b}]" do
162
178
  a_step = 99
163
179
  Progress.start('A', _a * 100) do
164
- io_pop.should == "A: ......\n"
180
+ io_pop_no_eta.should == "A: ......\n"
165
181
  _a.times do |a|
166
182
  Progress.step(a_step) do
167
183
  _b.times_with_progress('B') do |b|
168
- io_pop.should == "A: #{a == 0 && b == 0 ? '......' : '%5.1f%%'} > B: #{b == 0 ? '......' : '%5.1f%%'}\n" % [(a * a_step + b / _b.to_f * a_step) / (_a * 100).to_f * 100.0, b / _b.to_f * 100.0]
184
+ io_pop_no_eta.should == "A: #{a == 0 && b == 0 ? '......' : '%5.1f%%'} > B: #{b == 0 ? '......' : '%5.1f%%'}\n" % [(a * a_step + b / _b.to_f * a_step) / (_a * 100).to_f * 100.0, b / _b.to_f * 100.0]
169
185
  end
170
- io_pop.should == "A: %5.1f%% > B: 100.0%\n" % [(a + 1) * a_step.to_f / (100.0 * _a.to_f) * 100.0]
186
+ io_pop_no_eta.should == "A: %5.1f%% > B: 100.0%\n" % [(a + 1) * a_step.to_f / (100.0 * _a.to_f) * 100.0]
171
187
  end
172
- io_pop.should == "A: %5.1f%%\n" % [(a + 1) * a_step.to_f / (100.0 * _a.to_f) * 100.0]
188
+ io_pop_no_eta.should == "A: %5.1f%%\n" % [(a + 1) * a_step.to_f / (100.0 * _a.to_f) * 100.0]
173
189
  end
174
190
  Progress.step _a
175
191
  end
@@ -178,12 +194,6 @@ describe Progress do
178
194
  end
179
195
  end
180
196
 
181
-
182
-
183
-
184
-
185
-
186
-
187
197
  describe Enumerable do
188
198
  before :each do
189
199
  @a = (0...1000).to_a
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: progress
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
- - 0
8
- - 4
9
7
  - 1
10
- version: 0.4.1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Boba Fat
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-13 00:00:00 +03:00
18
+ date: 2010-11-14 00:00:00 +03:00
19
19
  default_executable:
20
20
  dependencies: []
21
21