ruby-progressbar 1.6.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/ruby-progressbar.rb +8 -3
- data/lib/ruby-progressbar/base.rb +121 -177
- data/lib/ruby-progressbar/calculators/length.rb +75 -0
- data/lib/ruby-progressbar/calculators/length_spec.rb +9 -0
- data/lib/ruby-progressbar/calculators/running_average.rb +9 -0
- data/lib/ruby-progressbar/components.rb +3 -5
- data/lib/ruby-progressbar/components/bar.rb +79 -43
- data/lib/ruby-progressbar/components/percentage.rb +29 -0
- data/lib/ruby-progressbar/components/rate.rb +34 -62
- data/lib/ruby-progressbar/components/time.rb +103 -0
- data/lib/ruby-progressbar/components/title.rb +13 -0
- data/lib/ruby-progressbar/format.rb +2 -1
- data/lib/ruby-progressbar/format/formatter.rb +27 -0
- data/lib/ruby-progressbar/format/molecule.rb +55 -37
- data/lib/ruby-progressbar/format/string.rb +36 -0
- data/lib/ruby-progressbar/output.rb +61 -0
- data/lib/ruby-progressbar/outputs/non_tty.rb +47 -0
- data/lib/ruby-progressbar/outputs/tty.rb +32 -0
- data/lib/ruby-progressbar/progress.rb +110 -0
- data/lib/ruby-progressbar/throttle.rb +25 -0
- data/lib/ruby-progressbar/time.rb +20 -17
- data/lib/ruby-progressbar/timer.rb +72 -0
- data/lib/ruby-progressbar/version.rb +2 -2
- data/spec/fixtures/benchmark.rb +21 -4
- data/spec/{lib/ruby-progressbar → ruby-progressbar}/base_spec.rb +55 -62
- data/spec/ruby-progressbar/calculators/running_average_spec.rb +19 -0
- data/spec/ruby-progressbar/components/bar_spec.rb +234 -0
- data/spec/ruby-progressbar/components/percentage_spec.rb +9 -0
- data/spec/ruby-progressbar/components/rate_spec.rb +9 -0
- data/spec/ruby-progressbar/components/throttle_spec.rb +157 -0
- data/spec/ruby-progressbar/components/time_spec.rb +308 -0
- data/spec/ruby-progressbar/components/title_spec.rb +12 -0
- data/spec/ruby-progressbar/format/formatter_spec.rb +9 -0
- data/spec/ruby-progressbar/format/molecule_spec.rb +30 -0
- data/spec/ruby-progressbar/format/string_spec.rb +9 -0
- data/spec/ruby-progressbar/output_spec.rb +7 -0
- data/spec/ruby-progressbar/outputs/non_tty_spec.rb +9 -0
- data/spec/ruby-progressbar/outputs/tty_spec.rb +9 -0
- data/spec/ruby-progressbar/progress_spec.rb +150 -0
- data/spec/ruby-progressbar/time_spec.rb +37 -0
- data/spec/ruby-progressbar/timer_spec.rb +7 -0
- data/spec/spec_helper.rb +2 -2
- data/spec/support/time.rb +3 -1
- metadata +55 -35
- data/lib/ruby-progressbar/components/elapsed_timer.rb +0 -25
- data/lib/ruby-progressbar/components/estimated_timer.rb +0 -90
- data/lib/ruby-progressbar/components/progressable.rb +0 -112
- data/lib/ruby-progressbar/components/throttle.rb +0 -21
- data/lib/ruby-progressbar/components/timer.rb +0 -69
- data/lib/ruby-progressbar/format/base.rb +0 -55
- data/lib/ruby-progressbar/formatter.rb +0 -112
- data/lib/ruby-progressbar/length_calculator.rb +0 -64
- data/lib/ruby-progressbar/running_average_calculator.rb +0 -7
- data/spec/lib/ruby-progressbar/components/bar_spec.rb +0 -210
- data/spec/lib/ruby-progressbar/components/elapsed_timer_spec.rb +0 -91
- data/spec/lib/ruby-progressbar/components/estimated_timer_spec.rb +0 -241
- data/spec/lib/ruby-progressbar/components/progressable_spec.rb +0 -47
- data/spec/lib/ruby-progressbar/components/throttle_spec.rb +0 -100
- data/spec/lib/ruby-progressbar/format/molecule_spec.rb +0 -22
- data/spec/lib/ruby-progressbar/running_average_calculator_spec.rb +0 -11
- data/spec/lib/ruby-progressbar/time_spec.rb +0 -49
@@ -1,25 +0,0 @@
|
|
1
|
-
class ProgressBar
|
2
|
-
module Components
|
3
|
-
class ElapsedTimer
|
4
|
-
include Timer
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
@started_at = nil
|
8
|
-
@stopped_at = nil
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_s
|
12
|
-
"Time: #{elapsed_time}"
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
def elapsed_time
|
17
|
-
return '--:--:--' unless started?
|
18
|
-
|
19
|
-
hours, minutes, seconds = divide_seconds(elapsed_whole_seconds)
|
20
|
-
|
21
|
-
sprintf TIME_FORMAT, hours, minutes, seconds
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,90 +0,0 @@
|
|
1
|
-
class ProgressBar
|
2
|
-
module Components
|
3
|
-
class EstimatedTimer
|
4
|
-
include Timer
|
5
|
-
include Progressable
|
6
|
-
|
7
|
-
VALID_OOB_TIME_FORMATS = [:unknown, :friendly, nil]
|
8
|
-
|
9
|
-
def initialize(options = {})
|
10
|
-
@out_of_bounds_time_format = nil
|
11
|
-
@starting_at = nil
|
12
|
-
@stopped_at = nil
|
13
|
-
|
14
|
-
super
|
15
|
-
end
|
16
|
-
|
17
|
-
def start(options = {})
|
18
|
-
as(Timer).start
|
19
|
-
as(Progressable).start(options)
|
20
|
-
end
|
21
|
-
|
22
|
-
def reset
|
23
|
-
as(Timer).reset
|
24
|
-
as(Progressable).reset
|
25
|
-
end
|
26
|
-
|
27
|
-
def out_of_bounds_time_format=(format)
|
28
|
-
raise "Invalid Out Of Bounds time format. Valid formats are #{VALID_OOB_TIME_FORMATS.inspect}" unless VALID_OOB_TIME_FORMATS.include? format
|
29
|
-
|
30
|
-
@out_of_bounds_time_format = format
|
31
|
-
end
|
32
|
-
|
33
|
-
def to_s
|
34
|
-
" ETA: #{estimated_time}"
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
def estimated_time
|
39
|
-
return '??:??:??' if running_average.zero? || total.nil?
|
40
|
-
|
41
|
-
hours, minutes, seconds = *divide_seconds(estimated_seconds_remaining)
|
42
|
-
|
43
|
-
if hours > 99 && @out_of_bounds_time_format
|
44
|
-
out_of_bounds_time
|
45
|
-
else
|
46
|
-
sprintf TIME_FORMAT, hours, minutes, seconds
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def estimated_seconds_remaining
|
51
|
-
(elapsed_seconds * (self.total / self.running_average - 1)).round
|
52
|
-
end
|
53
|
-
|
54
|
-
def out_of_bounds_time
|
55
|
-
case @out_of_bounds_time_format
|
56
|
-
when :unknown
|
57
|
-
'??:??:??'
|
58
|
-
when :friendly
|
59
|
-
'> 4 Days'
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def as(ancestor, &blk)
|
64
|
-
@__as ||= {}
|
65
|
-
unless r = @__as[ancestor]
|
66
|
-
r = (@__as[ancestor] = As.new(self, ancestor))
|
67
|
-
end
|
68
|
-
r.instance_eval(&blk) if block_given?
|
69
|
-
r
|
70
|
-
end
|
71
|
-
|
72
|
-
class As
|
73
|
-
private(*instance_methods.select { |m| m !~ /(^__|^\W|^binding$)/ })
|
74
|
-
|
75
|
-
def initialize(subject, ancestor)
|
76
|
-
@subject = subject
|
77
|
-
@ancestor = ancestor
|
78
|
-
end
|
79
|
-
|
80
|
-
def start(*args, &blk)
|
81
|
-
@ancestor.instance_method(:start).bind(@subject).call(*args,&blk)
|
82
|
-
end
|
83
|
-
|
84
|
-
def method_missing(sym, *args, &blk)
|
85
|
-
@ancestor.instance_method(sym).bind(@subject).call(*args,&blk)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
require 'ruby-progressbar/errors/invalid_progress_error'
|
2
|
-
|
3
|
-
class ProgressBar
|
4
|
-
module Components
|
5
|
-
module Progressable
|
6
|
-
DEFAULT_TOTAL = 100
|
7
|
-
DEFAULT_BEGINNING_POSITION = 0
|
8
|
-
DEFAULT_SMOOTHING = 0.1
|
9
|
-
|
10
|
-
attr_reader :total
|
11
|
-
attr_reader :progress
|
12
|
-
attr_accessor :starting_position
|
13
|
-
attr_accessor :running_average
|
14
|
-
attr_accessor :smoothing
|
15
|
-
attr_accessor :autofinish
|
16
|
-
attr_accessor :finished
|
17
|
-
|
18
|
-
def initialize(options = {})
|
19
|
-
self.total = options.fetch(:total, DEFAULT_TOTAL)
|
20
|
-
self.smoothing = options[:smoothing] || DEFAULT_SMOOTHING
|
21
|
-
self.autofinish = options.fetch(:autofinish, true)
|
22
|
-
|
23
|
-
start :at => DEFAULT_BEGINNING_POSITION
|
24
|
-
end
|
25
|
-
|
26
|
-
def start(options = {})
|
27
|
-
self.finished = false
|
28
|
-
self.running_average = 0
|
29
|
-
self.progress = \
|
30
|
-
self.starting_position = options[:at] || self.progress
|
31
|
-
end
|
32
|
-
|
33
|
-
def started?
|
34
|
-
!!self.starting_position
|
35
|
-
end
|
36
|
-
|
37
|
-
def finished?
|
38
|
-
finished || (autofinish && progress == total)
|
39
|
-
end
|
40
|
-
|
41
|
-
def increment
|
42
|
-
warn "WARNING: Your progress bar is currently at #{progress} out of #{total} and cannot be incremented. In v2.0.0 this will become a ProgressBar::InvalidProgressError." if progress == total
|
43
|
-
|
44
|
-
self.progress += 1 unless progress == total
|
45
|
-
end
|
46
|
-
|
47
|
-
def decrement
|
48
|
-
warn "WARNING: Your progress bar is currently at #{progress} out of #{total} and cannot be decremented. In v2.0.0 this will become a ProgressBar::InvalidProgressError." if progress == 0
|
49
|
-
|
50
|
-
self.progress -= 1 unless progress == 0
|
51
|
-
end
|
52
|
-
|
53
|
-
def reset
|
54
|
-
start :at => self.starting_position
|
55
|
-
end
|
56
|
-
|
57
|
-
def progress=(new_progress)
|
58
|
-
validate_progress(new_progress)
|
59
|
-
|
60
|
-
@progress = new_progress
|
61
|
-
|
62
|
-
update_running_average
|
63
|
-
end
|
64
|
-
|
65
|
-
def total=(new_total)
|
66
|
-
validate_total(new_total)
|
67
|
-
@total = new_total
|
68
|
-
end
|
69
|
-
|
70
|
-
def finish
|
71
|
-
self.finished = true
|
72
|
-
self.progress = total
|
73
|
-
end
|
74
|
-
|
75
|
-
def percentage_completed
|
76
|
-
return 100 if total == 0
|
77
|
-
return 0 if total.nil?
|
78
|
-
|
79
|
-
# progress / total * 100
|
80
|
-
#
|
81
|
-
# Doing this way so we can avoid converting each
|
82
|
-
# number to a float and then back to an integer.
|
83
|
-
#
|
84
|
-
(self.progress * 100 / total).to_i
|
85
|
-
end
|
86
|
-
|
87
|
-
def percentage_completed_with_precision
|
88
|
-
return 100.0 if total == 0
|
89
|
-
return 0.0 if total.nil?
|
90
|
-
|
91
|
-
format('%5.2f', (progress.to_f * 100.0 / total * 100.0).floor / 100.0)
|
92
|
-
end
|
93
|
-
|
94
|
-
def progress_made
|
95
|
-
started? ? self.progress - self.starting_position : 0
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
def validate_total(new_total)
|
100
|
-
(progress.nil? || new_total.nil? || new_total >= progress) || raise(ProgressBar::InvalidProgressError, "You can't set the item's total value to be less than the current progress.")
|
101
|
-
end
|
102
|
-
|
103
|
-
def validate_progress(new_progress)
|
104
|
-
(total.nil? || new_progress <= total) || raise(ProgressBar::InvalidProgressError, "You can't set the item's current value to be greater than the total.")
|
105
|
-
end
|
106
|
-
|
107
|
-
def update_running_average
|
108
|
-
self.running_average = RunningAverageCalculator.calculate(self.running_average, self.progress_made, self.smoothing)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
class ProgressBar
|
2
|
-
module Components
|
3
|
-
class Throttle
|
4
|
-
include Timer
|
5
|
-
|
6
|
-
def initialize(options = {})
|
7
|
-
@period = options.delete(:throttle_rate) { 0.01 } || 0.01
|
8
|
-
@started_at = nil
|
9
|
-
@stopped_at = nil
|
10
|
-
end
|
11
|
-
|
12
|
-
def choke(force = false, &block)
|
13
|
-
if !started? || @period.nil? || force || elapsed_seconds >= @period
|
14
|
-
yield
|
15
|
-
|
16
|
-
start
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'ruby-progressbar/time'
|
2
|
-
|
3
|
-
class ProgressBar
|
4
|
-
module Components
|
5
|
-
module Timer
|
6
|
-
TIME_FORMAT = '%02d:%02d:%02d'
|
7
|
-
|
8
|
-
def start
|
9
|
-
@started_at = stopped? ? now - (@stopped_at - @started_at) : now
|
10
|
-
@stopped_at = nil
|
11
|
-
end
|
12
|
-
|
13
|
-
def stop
|
14
|
-
return unless started?
|
15
|
-
|
16
|
-
@stopped_at = now
|
17
|
-
end
|
18
|
-
|
19
|
-
def pause
|
20
|
-
stop
|
21
|
-
end
|
22
|
-
|
23
|
-
def resume
|
24
|
-
start
|
25
|
-
end
|
26
|
-
|
27
|
-
def started?
|
28
|
-
!!@started_at
|
29
|
-
end
|
30
|
-
|
31
|
-
def stopped?
|
32
|
-
!!@stopped_at
|
33
|
-
end
|
34
|
-
|
35
|
-
def reset
|
36
|
-
@started_at = nil
|
37
|
-
@stopped_at = nil
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
def now
|
42
|
-
ProgressBar::Time.now
|
43
|
-
end
|
44
|
-
|
45
|
-
def elapsed_seconds
|
46
|
-
((@stopped_at || now) - @started_at)
|
47
|
-
end
|
48
|
-
|
49
|
-
def elapsed_whole_seconds
|
50
|
-
elapsed_seconds.floor
|
51
|
-
end
|
52
|
-
|
53
|
-
def elapsed_time
|
54
|
-
return '--:--:--' unless started?
|
55
|
-
|
56
|
-
hours, minutes, seconds = *divide_seconds(elapsed_whole_seconds)
|
57
|
-
|
58
|
-
sprintf TIME_FORMAT, hours, minutes, seconds
|
59
|
-
end
|
60
|
-
|
61
|
-
def divide_seconds(seconds)
|
62
|
-
hours, seconds = seconds.divmod(3600)
|
63
|
-
minutes, seconds = seconds.divmod(60)
|
64
|
-
|
65
|
-
[hours, minutes, seconds]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
class ProgressBar
|
2
|
-
module Format
|
3
|
-
class Base
|
4
|
-
attr_reader :molecules
|
5
|
-
|
6
|
-
def initialize(format_string)
|
7
|
-
@format_string = format_string
|
8
|
-
@molecules = parse(format_string)
|
9
|
-
end
|
10
|
-
|
11
|
-
def process(environment)
|
12
|
-
processed_string = @format_string.dup
|
13
|
-
ansi_sgr_codes = %r{\e\[[\d;]+m}
|
14
|
-
|
15
|
-
non_bar_molecules.each do |molecule|
|
16
|
-
processed_string.gsub!("%#{molecule.key}", environment.send(molecule.method_name).to_s)
|
17
|
-
end
|
18
|
-
|
19
|
-
remaining_molecules = bar_molecules.size
|
20
|
-
placeholder_length = remaining_molecules * 2
|
21
|
-
|
22
|
-
processed_string.gsub! '%%', '%'
|
23
|
-
|
24
|
-
processed_string_length = processed_string.gsub(ansi_sgr_codes, '').length
|
25
|
-
leftover_bar_length = environment.send(:length) - processed_string_length + placeholder_length
|
26
|
-
leftover_bar_length = leftover_bar_length < 0 ? 0 : leftover_bar_length
|
27
|
-
|
28
|
-
bar_molecules.each do |molecule|
|
29
|
-
processed_string.gsub!("%#{molecule.key}", environment.send(molecule.method_name, leftover_bar_length).to_s)
|
30
|
-
end
|
31
|
-
|
32
|
-
processed_string
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
def non_bar_molecules
|
37
|
-
@non_bar_molecules ||= molecules.select { |molecule| !molecule.bar_molecule? }
|
38
|
-
end
|
39
|
-
|
40
|
-
def bar_molecules
|
41
|
-
@bar_molecules ||= molecules.select { |molecule| molecule.bar_molecule? }
|
42
|
-
end
|
43
|
-
|
44
|
-
def parse(format_string)
|
45
|
-
molecules = []
|
46
|
-
|
47
|
-
format_string.scan(/%[a-zA-Z]/) do |match|
|
48
|
-
molecules << Molecule.new(match[1,1])
|
49
|
-
end
|
50
|
-
|
51
|
-
molecules
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
class ProgressBar
|
2
|
-
module Formatter
|
3
|
-
DEFAULT_FORMAT_STRING = '%t: |%B|'
|
4
|
-
DEFAULT_NON_TTY_FORMAT_STRING = '%t: |%b|'
|
5
|
-
DEFAULT_TITLE = 'Progress'
|
6
|
-
|
7
|
-
def initialize(options)
|
8
|
-
@format_string = nil
|
9
|
-
self.format_string = options[:format] || DEFAULT_FORMAT_STRING
|
10
|
-
@title = options[:title] || DEFAULT_TITLE
|
11
|
-
|
12
|
-
super(options)
|
13
|
-
end
|
14
|
-
|
15
|
-
def format(new_format_string = DEFAULT_FORMAT_STRING)
|
16
|
-
self.format_string = new_format_string
|
17
|
-
@format.process(self)
|
18
|
-
end
|
19
|
-
|
20
|
-
def title=(title)
|
21
|
-
@title = title
|
22
|
-
end
|
23
|
-
|
24
|
-
def progress
|
25
|
-
@bar.progress
|
26
|
-
end
|
27
|
-
|
28
|
-
def total
|
29
|
-
@bar.total
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
def format_string=(format_string)
|
34
|
-
if @format_string != format_string
|
35
|
-
@format_string = format_string
|
36
|
-
@format = ProgressBar::Format::Base.new(format_string)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# Format Methods
|
41
|
-
def title
|
42
|
-
@title
|
43
|
-
end
|
44
|
-
|
45
|
-
def percentage
|
46
|
-
@bar.percentage_completed
|
47
|
-
end
|
48
|
-
|
49
|
-
def justified_percentage
|
50
|
-
@bar.percentage_completed.to_s.rjust(3)
|
51
|
-
end
|
52
|
-
|
53
|
-
def percentage_with_precision
|
54
|
-
@bar.percentage_completed_with_precision
|
55
|
-
end
|
56
|
-
|
57
|
-
def justified_percentage_with_precision
|
58
|
-
@bar.percentage_completed_with_precision.to_s.rjust(6)
|
59
|
-
end
|
60
|
-
|
61
|
-
def elapsed_time
|
62
|
-
@elapsed_time
|
63
|
-
end
|
64
|
-
|
65
|
-
def estimated_time_with_no_oob
|
66
|
-
@estimated_time.out_of_bounds_time_format = nil
|
67
|
-
estimated_time
|
68
|
-
end
|
69
|
-
|
70
|
-
def estimated_time_with_unknown_oob
|
71
|
-
@estimated_time.out_of_bounds_time_format = :unknown
|
72
|
-
estimated_time
|
73
|
-
end
|
74
|
-
|
75
|
-
def estimated_time_with_friendly_oob
|
76
|
-
@estimated_time.out_of_bounds_time_format = :friendly
|
77
|
-
estimated_time
|
78
|
-
end
|
79
|
-
|
80
|
-
def bar(length)
|
81
|
-
@bar.length = length
|
82
|
-
@bar.standard_complete_string
|
83
|
-
end
|
84
|
-
|
85
|
-
def complete_bar(length)
|
86
|
-
@bar.length = length
|
87
|
-
@bar.to_s
|
88
|
-
end
|
89
|
-
|
90
|
-
def incomplete_space(length)
|
91
|
-
@bar.length = length
|
92
|
-
@bar.empty_string
|
93
|
-
end
|
94
|
-
|
95
|
-
def bar_with_percentage(length)
|
96
|
-
@bar.length = length
|
97
|
-
@bar.integrated_percentage_complete_string
|
98
|
-
end
|
99
|
-
|
100
|
-
def estimated_time
|
101
|
-
finished? ? @elapsed_time : @estimated_time
|
102
|
-
end
|
103
|
-
|
104
|
-
def rate_of_change
|
105
|
-
@rate.to_s
|
106
|
-
end
|
107
|
-
|
108
|
-
def rate_of_change_with_precision
|
109
|
-
@rate.to_s("%.2f")
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|