ruby-progressbar 1.6.1 → 1.7.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/lib/ruby-progressbar.rb +8 -3
  4. data/lib/ruby-progressbar/base.rb +121 -177
  5. data/lib/ruby-progressbar/calculators/length.rb +75 -0
  6. data/lib/ruby-progressbar/calculators/length_spec.rb +9 -0
  7. data/lib/ruby-progressbar/calculators/running_average.rb +9 -0
  8. data/lib/ruby-progressbar/components.rb +3 -5
  9. data/lib/ruby-progressbar/components/bar.rb +79 -43
  10. data/lib/ruby-progressbar/components/percentage.rb +29 -0
  11. data/lib/ruby-progressbar/components/rate.rb +34 -62
  12. data/lib/ruby-progressbar/components/time.rb +103 -0
  13. data/lib/ruby-progressbar/components/title.rb +13 -0
  14. data/lib/ruby-progressbar/format.rb +2 -1
  15. data/lib/ruby-progressbar/format/formatter.rb +27 -0
  16. data/lib/ruby-progressbar/format/molecule.rb +55 -37
  17. data/lib/ruby-progressbar/format/string.rb +36 -0
  18. data/lib/ruby-progressbar/output.rb +61 -0
  19. data/lib/ruby-progressbar/outputs/non_tty.rb +47 -0
  20. data/lib/ruby-progressbar/outputs/tty.rb +32 -0
  21. data/lib/ruby-progressbar/progress.rb +110 -0
  22. data/lib/ruby-progressbar/throttle.rb +25 -0
  23. data/lib/ruby-progressbar/time.rb +20 -17
  24. data/lib/ruby-progressbar/timer.rb +72 -0
  25. data/lib/ruby-progressbar/version.rb +2 -2
  26. data/spec/fixtures/benchmark.rb +21 -4
  27. data/spec/{lib/ruby-progressbar → ruby-progressbar}/base_spec.rb +55 -62
  28. data/spec/ruby-progressbar/calculators/running_average_spec.rb +19 -0
  29. data/spec/ruby-progressbar/components/bar_spec.rb +234 -0
  30. data/spec/ruby-progressbar/components/percentage_spec.rb +9 -0
  31. data/spec/ruby-progressbar/components/rate_spec.rb +9 -0
  32. data/spec/ruby-progressbar/components/throttle_spec.rb +157 -0
  33. data/spec/ruby-progressbar/components/time_spec.rb +308 -0
  34. data/spec/ruby-progressbar/components/title_spec.rb +12 -0
  35. data/spec/ruby-progressbar/format/formatter_spec.rb +9 -0
  36. data/spec/ruby-progressbar/format/molecule_spec.rb +30 -0
  37. data/spec/ruby-progressbar/format/string_spec.rb +9 -0
  38. data/spec/ruby-progressbar/output_spec.rb +7 -0
  39. data/spec/ruby-progressbar/outputs/non_tty_spec.rb +9 -0
  40. data/spec/ruby-progressbar/outputs/tty_spec.rb +9 -0
  41. data/spec/ruby-progressbar/progress_spec.rb +150 -0
  42. data/spec/ruby-progressbar/time_spec.rb +37 -0
  43. data/spec/ruby-progressbar/timer_spec.rb +7 -0
  44. data/spec/spec_helper.rb +2 -2
  45. data/spec/support/time.rb +3 -1
  46. metadata +55 -35
  47. data/lib/ruby-progressbar/components/elapsed_timer.rb +0 -25
  48. data/lib/ruby-progressbar/components/estimated_timer.rb +0 -90
  49. data/lib/ruby-progressbar/components/progressable.rb +0 -112
  50. data/lib/ruby-progressbar/components/throttle.rb +0 -21
  51. data/lib/ruby-progressbar/components/timer.rb +0 -69
  52. data/lib/ruby-progressbar/format/base.rb +0 -55
  53. data/lib/ruby-progressbar/formatter.rb +0 -112
  54. data/lib/ruby-progressbar/length_calculator.rb +0 -64
  55. data/lib/ruby-progressbar/running_average_calculator.rb +0 -7
  56. data/spec/lib/ruby-progressbar/components/bar_spec.rb +0 -210
  57. data/spec/lib/ruby-progressbar/components/elapsed_timer_spec.rb +0 -91
  58. data/spec/lib/ruby-progressbar/components/estimated_timer_spec.rb +0 -241
  59. data/spec/lib/ruby-progressbar/components/progressable_spec.rb +0 -47
  60. data/spec/lib/ruby-progressbar/components/throttle_spec.rb +0 -100
  61. data/spec/lib/ruby-progressbar/format/molecule_spec.rb +0 -22
  62. data/spec/lib/ruby-progressbar/running_average_calculator_spec.rb +0 -11
  63. 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