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.
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