progress-monitor 1.8.9
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.
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/lib/progress-monitor.rb +227 -0
- data/samples/collect.rb +10 -0
- data/samples/file.rb +7 -0
- data/samples/hash-loop.rb +17 -0
- data/samples/skip.rb +19 -0
- data/samples/times.rb +7 -0
- data/samples/two-loops.rb +14 -0
- metadata +64 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Miguel Vazquez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= progress-monitor
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but
|
13
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
|
+
* Send me a pull request. Bonus points for topic branches.
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2009 Miguel Vazquez. See LICENSE for details.
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# Allow the possibility of monitoring the progress of some loop.
|
2
|
+
# Currently only Array.each and Hash.each are supported, but this should
|
3
|
+
# be easy to extend.
|
4
|
+
#
|
5
|
+
# Author:: Miguel Vazquez Garcia
|
6
|
+
# License:: MIT
|
7
|
+
#
|
8
|
+
|
9
|
+
# Tracks the progress of a loop. It holds information about how many
|
10
|
+
# iterations it has to go through and how many have been executed
|
11
|
+
# already. Every now and then, it prints the progress report.
|
12
|
+
class Progress
|
13
|
+
|
14
|
+
@@progress_meters = Array.new
|
15
|
+
def self.progress_meters
|
16
|
+
@@progress_meters
|
17
|
+
end
|
18
|
+
|
19
|
+
@@monitor = false
|
20
|
+
@@desc = ""
|
21
|
+
@@skip = 0
|
22
|
+
|
23
|
+
# This function will activate monitoring of the next _supported_ loop.
|
24
|
+
#
|
25
|
+
# If a description is given as a parameter it will show at the
|
26
|
+
# beginning of the progress report.
|
27
|
+
def self.monitor(desc = "", num_reports = 100, skip = 0)
|
28
|
+
@@monitor = true
|
29
|
+
@@desc = desc
|
30
|
+
@@num_reports=num_reports
|
31
|
+
@@skip = skip
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns true if next loop must be monitored.
|
35
|
+
#
|
36
|
+
def self.active?
|
37
|
+
if @@monitor
|
38
|
+
if @@skip > 0
|
39
|
+
@@skip -= 1
|
40
|
+
return false
|
41
|
+
else
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
else
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# Creates a new instance. Max is the total number of iterations of the
|
51
|
+
# loop. The depth represents how many other loops are above this one,
|
52
|
+
# this information is used to find the place to print the progress
|
53
|
+
# report.
|
54
|
+
#
|
55
|
+
def initialize(max,depth)
|
56
|
+
@max = max
|
57
|
+
@max = 1 if @max < 1
|
58
|
+
@current = 0
|
59
|
+
@time = Time.now
|
60
|
+
@last_report = 0
|
61
|
+
@num_reports = @@num_reports
|
62
|
+
@depth = depth
|
63
|
+
@desc = @@desc
|
64
|
+
@@monitor = false
|
65
|
+
report
|
66
|
+
end
|
67
|
+
|
68
|
+
# Used to register a new completed loop iteration.
|
69
|
+
#
|
70
|
+
def tick(steps = 1)
|
71
|
+
@current += steps
|
72
|
+
percent = @current.to_f/ @max.to_f
|
73
|
+
if percent - @last_report > 1.to_f/@num_reports.to_f then
|
74
|
+
report
|
75
|
+
@last_report=percent
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def set(step)
|
80
|
+
@current = step
|
81
|
+
percent = @current.to_f/ @max.to_f
|
82
|
+
if percent - @last_report > 1.to_f/@num_reports.to_f then
|
83
|
+
report
|
84
|
+
@last_report=percent
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Prints de progress report. It backs up as many lines as the meters
|
90
|
+
# depth. Prints the progress as a line of dots, a percentage, time
|
91
|
+
# spent, and time left. And then goes moves the cursor back to its
|
92
|
+
# original line. Everything is printed to stderr.
|
93
|
+
#
|
94
|
+
def report
|
95
|
+
|
96
|
+
percent = @current.to_f/ @max.to_f
|
97
|
+
percent = 0.001 if percent < 0.001
|
98
|
+
if @desc != ""
|
99
|
+
indicator = @desc + ": "
|
100
|
+
else
|
101
|
+
indicator = "Progress "
|
102
|
+
end
|
103
|
+
indicator += "["
|
104
|
+
10.times{|i|
|
105
|
+
if i < percent * 10 then
|
106
|
+
indicator += "."
|
107
|
+
else
|
108
|
+
indicator += " "
|
109
|
+
end
|
110
|
+
}
|
111
|
+
indicator += "] done #{(percent * 100).to_i}% "
|
112
|
+
|
113
|
+
eta = (Time.now - @time)/percent * (1-percent)
|
114
|
+
eta = eta.to_i
|
115
|
+
eta = [eta/3600, eta/60 % 60, eta % 60].map{|t| t.to_s.rjust(2, '0')}.join(':')
|
116
|
+
|
117
|
+
used = (Time.now - @time).to_i
|
118
|
+
used = [used/3600, used/60 % 60, used % 60].map{|t| t.to_s.rjust(2, '0')}.join(':')
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
indicator += " (Time left #{eta} seconds) (Started #{used} seconds ago)"
|
123
|
+
|
124
|
+
$stderr.print("\033[#{@depth + 1}F\033[2K" + indicator + "\033[#{@depth + 1}E" )
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
class Integer
|
132
|
+
alias :orig_times :times
|
133
|
+
|
134
|
+
def times (&block)
|
135
|
+
if Progress.active? then
|
136
|
+
progress_meters = Progress::progress_meters
|
137
|
+
progress_meters.push(Progress.new(self, progress_meters.size ))
|
138
|
+
orig_times {|w|block.call(w);progress_meters.last.tick;}
|
139
|
+
progress_meters.pop
|
140
|
+
else
|
141
|
+
orig_times &block
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
class Array
|
149
|
+
alias :orig_each :each
|
150
|
+
|
151
|
+
def each (&block)
|
152
|
+
if Progress.active? then
|
153
|
+
progress_meters = Progress::progress_meters
|
154
|
+
progress_meters.push(Progress.new(self.length, progress_meters.size ))
|
155
|
+
orig_each {|w|block.call(w);progress_meters.last.tick;}
|
156
|
+
progress_meters.pop
|
157
|
+
else
|
158
|
+
orig_each &block
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
alias :orig_collect :collect
|
163
|
+
def collect (&block)
|
164
|
+
if Progress.active? then
|
165
|
+
progress_meters = Progress::progress_meters
|
166
|
+
progress_meters.push(Progress.new(self.length, progress_meters.size ))
|
167
|
+
res = orig_collect {|w| r = block.call(w);progress_meters.last.tick; r}
|
168
|
+
progress_meters.pop
|
169
|
+
res
|
170
|
+
else
|
171
|
+
orig_collect &block
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
|
178
|
+
class Hash
|
179
|
+
alias :orig_each :each
|
180
|
+
def each (&block)
|
181
|
+
if Progress.active? then
|
182
|
+
progress_meters = Progress::progress_meters
|
183
|
+
progress_meters.push(Progress.new(self.length, progress_meters.size ))
|
184
|
+
orig_each {|k,v|block.call(k,v);progress_meters.last.tick;}
|
185
|
+
progress_meters.pop
|
186
|
+
else
|
187
|
+
orig_each &block
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
class File
|
198
|
+
alias :orig_each :each
|
199
|
+
alias :orig_collect :collect
|
200
|
+
def each (&block)
|
201
|
+
if Progress.active? then
|
202
|
+
progress_meters = Progress::progress_meters
|
203
|
+
progress_meters.push(Progress.new(self.stat.size, progress_meters.size ))
|
204
|
+
orig_each {|l| block.call(l);progress_meters.last.set(self.pos);}
|
205
|
+
progress_meters.pop
|
206
|
+
else
|
207
|
+
orig_each &block
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def collect (&block)
|
212
|
+
if Progress.active? then
|
213
|
+
progress_meters = Progress::progress_meters
|
214
|
+
progress_meters.push(Progress.new(self.stat.size, progress_meters.size ))
|
215
|
+
res = orig_collect {|l| r = block.call(l);progress_meters.last.set(self.pos); r}
|
216
|
+
progress_meters.pop
|
217
|
+
res
|
218
|
+
else
|
219
|
+
orig_collect &block
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
|
data/samples/collect.rb
ADDED
data/samples/file.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This is an example using a hash. It also shows what happens when you
|
2
|
+
# print stuff. In this case, we print new lines, and the progress meter
|
3
|
+
# is always moved to the line above the last one.
|
4
|
+
|
5
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'lib', 'progress-monitor')
|
6
|
+
|
7
|
+
h = Hash.new
|
8
|
+
|
9
|
+
('a'..'z').to_a.each{|l|
|
10
|
+
h[l] = l.upcase
|
11
|
+
}
|
12
|
+
|
13
|
+
Progress.monitor("hash",50)
|
14
|
+
h.each{|d,u|
|
15
|
+
puts "#{d} => #{u}, "
|
16
|
+
sleep(0.2)
|
17
|
+
}
|
data/samples/skip.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'lib', 'progress-monitor')
|
2
|
+
|
3
|
+
# Skip first loop
|
4
|
+
puts ""
|
5
|
+
|
6
|
+
Progress.monitor("Main Loop",100, 1)
|
7
|
+
|
8
|
+
puts "This loop must not be monitored"
|
9
|
+
puts
|
10
|
+
(1..100).to_a.each{
|
11
|
+
sleep 0.05
|
12
|
+
}
|
13
|
+
|
14
|
+
puts "This loop must be monitored"
|
15
|
+
puts
|
16
|
+
(1..100).to_a.each{
|
17
|
+
sleep 0.05
|
18
|
+
}
|
19
|
+
|
data/samples/times.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.join(File.dirname(File.dirname(__FILE__)), 'lib', 'progress-monitor')
|
2
|
+
|
3
|
+
# Each progress meter backs up one line
|
4
|
+
puts ""
|
5
|
+
puts ""
|
6
|
+
|
7
|
+
Progress.monitor("Main Loop")
|
8
|
+
(1..100).to_a.each{
|
9
|
+
Progress.monitor
|
10
|
+
(1..100).to_a.each{
|
11
|
+
sleep 0.05
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: progress-monitor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.8.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Miguel Vazquez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-27 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Patches some each and collect functions of certain classes (Array, Hash, Integer) to report progress
|
17
|
+
email: miguel.vazquez@fdi.ucm.es
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.rdoc
|
25
|
+
files:
|
26
|
+
- lib/progress-monitor.rb
|
27
|
+
- samples/collect.rb
|
28
|
+
- samples/file.rb
|
29
|
+
- samples/hash-loop.rb
|
30
|
+
- samples/skip.rb
|
31
|
+
- samples/times.rb
|
32
|
+
- samples/two-loops.rb
|
33
|
+
- LICENSE
|
34
|
+
- README.rdoc
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/mikisvaz/progress-monitor
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --charset=UTF-8
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.5
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Monitor Progress in the Command Line
|
63
|
+
test_files: []
|
64
|
+
|