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
@@ -0,0 +1,9 @@
1
+ class ProgressBar
2
+ module Calculators
3
+ class RunningAverage
4
+ def self.calculate(current_average, new_value_to_average, smoothing_factor)
5
+ new_value_to_average * (1.0 - smoothing_factor) + current_average * smoothing_factor
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,5 @@
1
- require 'ruby-progressbar/components/timer'
2
- require 'ruby-progressbar/components/progressable'
3
1
  require 'ruby-progressbar/components/bar'
4
- require 'ruby-progressbar/components/estimated_timer'
5
- require 'ruby-progressbar/components/elapsed_timer'
6
- require 'ruby-progressbar/components/throttle'
2
+ require 'ruby-progressbar/components/percentage'
7
3
  require 'ruby-progressbar/components/rate'
4
+ require 'ruby-progressbar/components/time'
5
+ require 'ruby-progressbar/components/title'
@@ -1,60 +1,96 @@
1
- class ProgressBar
2
- module Components
3
- class Bar
4
- include Progressable
1
+ ###
2
+ # UPA = Unknown Progress Animation
3
+ #
4
+ class ProgressBar
5
+ module Components
6
+ class Bar
7
+ DEFAULT_PROGRESS_MARK = '='
8
+ DEFAULT_REMAINDER_MARK = ' '
9
+ DEFAULT_UPA_STEPS = ['=---', '-=--', '--=-', '---=']
5
10
 
6
- DEFAULT_PROGRESS_MARK = '='
7
- DEFAULT_REMAINDER_MARK = ' '
8
- DEFAULT_UNKNOWN_PROGRESS_ANIMATION_STEPS = ['=---', '-=--', '--=-', '---=']
11
+ attr_accessor :progress_mark,
12
+ :remainder_mark,
13
+ :length,
14
+ :progress,
15
+ :upa_steps
9
16
 
10
- attr_accessor :progress_mark
11
- attr_accessor :remainder_mark
12
- attr_accessor :length
13
- attr_accessor :unknown_progress_animation_steps
17
+ def initialize(options = {})
18
+ self.upa_steps = options[:unknown_progress_animation_steps] || DEFAULT_UPA_STEPS
19
+ self.progress_mark = options[:progress_mark] || DEFAULT_PROGRESS_MARK
20
+ self.remainder_mark = options[:remainder_mark] || DEFAULT_REMAINDER_MARK
21
+ self.progress = options[:progress]
22
+ self.length = options[:length]
23
+ end
14
24
 
15
- def initialize(options = {})
16
- super
25
+ def to_s(options = { :format => :standard })
26
+ if progress.unknown?
27
+ unknown_string
28
+ elsif options[:format] == :standard
29
+ "#{standard_complete_string}#{incomplete_string}"
30
+ elsif options[:format] == :integrated_percentage
31
+ "#{integrated_percentage_complete_string}#{incomplete_string}"
32
+ end
33
+ end
17
34
 
18
- self.unknown_progress_animation_steps = options[:unknown_progress_animation_steps] || DEFAULT_UNKNOWN_PROGRESS_ANIMATION_STEPS
19
- self.progress_mark = options[:progress_mark] || DEFAULT_PROGRESS_MARK
20
- self.remainder_mark = options[:remainder_mark] || DEFAULT_REMAINDER_MARK
21
- end
35
+ private
22
36
 
23
- def to_s(options = {:format => :standard})
24
- completed_string = send(:"#{options[:format]}_complete_string")
37
+ def integrated_percentage_complete_string
38
+ return standard_complete_string if completed_length < 5
25
39
 
26
- "#{completed_string}#{empty_string}"
27
- end
40
+ " #{progress.percentage_completed} ".to_s.center(completed_length, progress_mark)
41
+ end
28
42
 
29
- def integrated_percentage_complete_string
30
- return standard_complete_string if completed_length < 5
43
+ def standard_complete_string
44
+ progress_mark * completed_length
45
+ end
31
46
 
32
- " #{percentage_completed} ".to_s.center(completed_length, progress_mark)
33
- end
47
+ def incomplete_string
48
+ remainder_mark * (length - completed_length)
49
+ end
34
50
 
35
- def standard_complete_string
36
- progress_mark * completed_length
37
- end
51
+ def bar(length)
52
+ self.length = length
38
53
 
39
- def empty_string
40
- incomplete_length = (length - completed_length)
54
+ standard_complete_string
55
+ end
56
+
57
+ def complete_bar(length)
58
+ self.length = length
41
59
 
42
- if total.nil?
43
- current_animation_step = progress % unknown_progress_animation_steps.size
44
- animation_graphic = unknown_progress_animation_steps[current_animation_step]
60
+ to_s
61
+ end
45
62
 
46
- unknown_incomplete_string = animation_graphic * ((incomplete_length / unknown_progress_animation_steps.size) + 2)
63
+ def unknown_string
64
+ unknown_frame_string = unknown_progress_frame * ((length / upa_steps.size) + 2)
65
+
66
+ unknown_frame_string[0, length]
67
+ end
47
68
 
48
- unknown_incomplete_string[0, incomplete_length]
49
- else
50
- remainder_mark * incomplete_length
51
- end
52
- end
69
+ def incomplete_space(length)
70
+ self.length = length
53
71
 
54
- private
55
- def completed_length
56
- (length * percentage_completed / 100).floor
57
- end
72
+ if progress.unknown?
73
+ unknown_string
74
+ else
75
+ incomplete_string
58
76
  end
59
77
  end
78
+
79
+ def bar_with_percentage(length)
80
+ self.length = length
81
+
82
+ integrated_percentage_complete_string
83
+ end
84
+
85
+ def completed_length
86
+ (length * progress.percentage_completed / 100).floor
87
+ end
88
+
89
+ def unknown_progress_frame
90
+ current_animation_step = progress.progress % upa_steps.size
91
+
92
+ upa_steps[current_animation_step]
93
+ end
94
+ end
95
+ end
60
96
  end
@@ -0,0 +1,29 @@
1
+ class ProgressBar
2
+ module Components
3
+ class Percentage
4
+ attr_accessor :progress
5
+
6
+ def initialize(options = {})
7
+ self.progress = options[:progress]
8
+ end
9
+
10
+ private
11
+
12
+ def percentage
13
+ progress.percentage_completed
14
+ end
15
+
16
+ def justified_percentage
17
+ progress.percentage_completed.to_s.rjust(3)
18
+ end
19
+
20
+ def percentage_with_precision
21
+ progress.percentage_completed_with_precision
22
+ end
23
+
24
+ def justified_percentage_with_precision
25
+ progress.percentage_completed_with_precision.to_s.rjust(6)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,71 +1,43 @@
1
- class ProgressBar
2
- module Components
3
- class Rate
4
- include Timer
5
- include Progressable
6
-
7
- attr_accessor :rate_scale
8
-
9
- def initialize(options = {})
10
- self.rate_scale = options[:rate_scale]
11
- @started_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 to_s(format_string = "%i")
28
- elapsed = elapsed_whole_seconds.to_f
29
- return 0 unless elapsed > 0
30
-
31
- base_rate = (progress_made / elapsed)
32
-
33
- if rate_scale
34
- scaled_rate = rate_scale.call(base_rate)
35
- else
36
- scaled_rate = base_rate
37
- end
1
+ class ProgressBar
2
+ module Components
3
+ class Rate
4
+ attr_accessor :rate_scale,
5
+ :started_at,
6
+ :stopped_at,
7
+ :timer,
8
+ :progress
9
+
10
+ def initialize(options = {})
11
+ self.rate_scale = options[:rate_scale] || lambda { |x| x }
12
+ self.started_at = nil
13
+ self.stopped_at = nil
14
+ self.timer = options[:timer]
15
+ self.progress = options[:progress]
16
+ end
38
17
 
39
- format_string % scaled_rate
40
- end
18
+ private
41
19
 
42
- private
20
+ def rate_of_change(format_string = '%i')
21
+ return 0 unless elapsed_seconds > 0
43
22
 
44
- def as(ancestor, &blk)
45
- @__as ||= {}
46
- unless r = @__as[ancestor]
47
- r = (@__as[ancestor] = As.new(self, ancestor))
48
- end
49
- r.instance_eval(&blk) if block_given?
50
- r
51
- end
23
+ format_string % scaled_rate
24
+ end
52
25
 
53
- class As
54
- private(*instance_methods.select { |m| m !~ /(^__|^\W|^binding$)/ })
26
+ def rate_of_change_with_precision
27
+ rate_of_change('%.2f')
28
+ end
55
29
 
56
- def initialize(subject, ancestor)
57
- @subject = subject
58
- @ancestor = ancestor
59
- end
30
+ def scaled_rate
31
+ rate_scale.call(base_rate)
32
+ end
60
33
 
61
- def start(*args, &blk)
62
- @ancestor.instance_method(:start).bind(@subject).call(*args,&blk)
63
- end
34
+ def base_rate
35
+ progress.absolute / elapsed_seconds
36
+ end
64
37
 
65
- def method_missing(sym, *args, &blk)
66
- @ancestor.instance_method(sym).bind(@subject).call(*args,&blk)
67
- end
68
- end
69
- end
38
+ def elapsed_seconds
39
+ timer.elapsed_whole_seconds.to_f
70
40
  end
71
41
  end
42
+ end
43
+ end
@@ -0,0 +1,103 @@
1
+ ###
2
+ # OOB = 'Out of Bounds'
3
+ #
4
+ class ProgressBar
5
+ module Components
6
+ class Time
7
+ TIME_FORMAT = '%02d:%02d:%02d'
8
+ OOB_TIME_FORMATS = [:unknown, :friendly, nil]
9
+ OOB_LIMIT_IN_HOURS = 99
10
+ OOB_UNKNOWN_TIME_TEXT = '??:??:??'
11
+ OOB_FRIENDLY_TIME_TEXT = '> 4 Days'
12
+ NO_TIME_ELAPSED_TEXT = '--:--:--'
13
+ ESTIMATED_LABEL = ' ETA'
14
+ ELAPSED_LABEL = 'Time'
15
+
16
+ def initialize(options = {})
17
+ self.out_of_bounds_time_format = options[:out_of_bounds_time_format]
18
+ self.timer = options[:timer]
19
+ self.progress = options[:progress]
20
+ end
21
+
22
+ def estimated_with_label
23
+ "#{ESTIMATED_LABEL}: #{estimated}"
24
+ end
25
+
26
+ def elapsed_with_label
27
+ "#{ELAPSED_LABEL}: #{elapsed}"
28
+ end
29
+
30
+ protected
31
+
32
+ def estimated_with_no_oob
33
+ self.out_of_bounds_time_format = nil
34
+
35
+ estimated_with_elapsed_fallback
36
+ end
37
+
38
+ def estimated_with_unknown_oob
39
+ self.out_of_bounds_time_format = :unknown
40
+
41
+ estimated_with_elapsed_fallback
42
+ end
43
+
44
+ def estimated_with_friendly_oob
45
+ self.out_of_bounds_time_format = :friendly
46
+
47
+ estimated_with_elapsed_fallback
48
+ end
49
+
50
+ attr_accessor :out_of_bounds_time_format,
51
+ :timer,
52
+ :progress
53
+
54
+ def out_of_bounds_time_format=(format)
55
+ unless OOB_TIME_FORMATS.include? format
56
+ fail 'Invalid Out Of Bounds time format. Valid formats are ' +
57
+ OOB_TIME_FORMATS.inspect
58
+ end
59
+
60
+ @out_of_bounds_time_format = format
61
+ end
62
+
63
+ private
64
+
65
+ def estimated
66
+ return OOB_UNKNOWN_TIME_TEXT if progress.unknown? || progress.none? || timer.stopped?
67
+
68
+ hours, minutes, seconds = timer.divide_seconds(estimated_seconds_remaining)
69
+
70
+ if hours > OOB_LIMIT_IN_HOURS && out_of_bounds_time_format
71
+ out_of_bounds_time
72
+ else
73
+ TIME_FORMAT % [hours, minutes, seconds]
74
+ end
75
+ end
76
+
77
+ def elapsed
78
+ return NO_TIME_ELAPSED_TEXT unless timer.started?
79
+
80
+ hours, minutes, seconds = timer.divide_seconds(timer.elapsed_whole_seconds)
81
+
82
+ TIME_FORMAT % [hours, minutes, seconds]
83
+ end
84
+
85
+ def estimated_with_elapsed_fallback
86
+ progress.finished? ? elapsed_with_label : estimated_with_label
87
+ end
88
+
89
+ def estimated_seconds_remaining
90
+ (timer.elapsed_seconds * (progress.total / progress.running_average - 1)).round
91
+ end
92
+
93
+ def out_of_bounds_time
94
+ case out_of_bounds_time_format
95
+ when :unknown
96
+ OOB_UNKNOWN_TIME_TEXT
97
+ when :friendly
98
+ OOB_FRIENDLY_TIME_TEXT
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,13 @@
1
+ class ProgressBar
2
+ module Components
3
+ class Title
4
+ DEFAULT_TITLE = 'Progress'
5
+
6
+ attr_accessor :title
7
+
8
+ def initialize(options = {})
9
+ self.title = options[:title] || DEFAULT_TITLE
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,2 +1,3 @@
1
1
  require 'ruby-progressbar/format/molecule'
2
- require 'ruby-progressbar/format/base'
2
+ require 'ruby-progressbar/format/formatter'
3
+ require 'ruby-progressbar/format/string'
@@ -0,0 +1,27 @@
1
+ class ProgressBar
2
+ module Format
3
+ class Formatter
4
+ def self.process(format_string, max_length, bar)
5
+ processed_string = format_string.dup
6
+
7
+ format_string.non_bar_molecules.each do |molecule|
8
+ processed_string.gsub!(molecule.full_key, molecule.lookup_value(bar, nil))
9
+ end
10
+
11
+ processed_string.gsub!(/%%/, '%')
12
+
13
+ bar_length = max_length -
14
+ processed_string.displayable_length +
15
+ format_string.bar_molecule_placeholder_length
16
+ bar_length = bar_length < 0 ? 0 : bar_length
17
+
18
+ format_string.bar_molecules.each do |molecule|
19
+ processed_string.gsub!(molecule.full_key,
20
+ molecule.lookup_value(bar, bar_length))
21
+ end
22
+
23
+ processed_string
24
+ end
25
+ end
26
+ end
27
+ end