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,40 +1,58 @@
1
- class ProgressBar
2
- module Format
3
- class Molecule
4
- MOLECULES = {
5
- :t => :title,
6
- :T => :title,
7
- :c => :progress,
8
- :C => :total,
9
- :p => :percentage,
10
- :P => :percentage_with_precision,
11
- :j => :justified_percentage,
12
- :J => :justified_percentage_with_precision,
13
- :a => :elapsed_time,
14
- :e => :estimated_time_with_unknown_oob,
15
- :E => :estimated_time_with_friendly_oob,
16
- :f => :estimated_time_with_no_oob,
17
- :B => :complete_bar,
18
- :b => :bar,
19
- :w => :bar_with_percentage,
20
- :i => :incomplete_space,
21
- :r => :rate_of_change,
22
- :R => :rate_of_change_with_precision,
23
- }
24
-
25
- BAR_MOLECULES = %w{w B b i}
26
-
27
- attr_reader :key
28
- attr_reader :method_name
29
-
30
- def initialize(letter)
31
- @key = letter
32
- @method_name = MOLECULES.fetch(@key.to_sym)
33
- end
34
-
35
- def bar_molecule?
36
- BAR_MOLECULES.include? @key
37
- end
1
+ class ProgressBar
2
+ module Format
3
+ class Molecule
4
+ MOLECULES = {
5
+ :t => [:title_comp, :title],
6
+ :T => [:title_comp, :title],
7
+ :c => [:progressable, :progress],
8
+ :C => [:progressable, :total],
9
+ :p => [:percentage, :percentage],
10
+ :P => [:percentage, :percentage_with_precision],
11
+ :j => [:percentage, :justified_percentage],
12
+ :J => [:percentage, :justified_percentage_with_precision],
13
+ :a => [:time, :elapsed_with_label],
14
+ :e => [:time, :estimated_with_unknown_oob],
15
+ :E => [:time, :estimated_with_friendly_oob],
16
+ :f => [:time, :estimated_with_no_oob],
17
+ :B => [:bar, :complete_bar],
18
+ :b => [:bar, :bar],
19
+ :w => [:bar, :bar_with_percentage],
20
+ :i => [:bar, :incomplete_space],
21
+ :r => [:rate, :rate_of_change],
22
+ :R => [:rate, :rate_of_change_with_precision],
23
+ }
24
+
25
+ BAR_MOLECULES = %w{w B b i}
26
+
27
+ attr_accessor :key,
28
+ :method_name
29
+
30
+ def initialize(letter)
31
+ self.key = letter
32
+ self.method_name = MOLECULES.fetch(key.to_sym)
33
+ end
34
+
35
+ def bar_molecule?
36
+ BAR_MOLECULES.include? key
37
+ end
38
+
39
+ def non_bar_molecule?
40
+ !bar_molecule?
41
+ end
42
+
43
+ def full_key
44
+ "%#{key}"
45
+ end
46
+
47
+ def lookup_value(environment, length = 0)
48
+ component = environment.send(method_name[0])
49
+
50
+ if bar_molecule?
51
+ component.send(method_name[1], length).to_s
52
+ else
53
+ component.send(method_name[1]).to_s
38
54
  end
39
55
  end
40
56
  end
57
+ end
58
+ end
@@ -0,0 +1,36 @@
1
+ class ProgressBar
2
+ module Format
3
+ class String < ::String
4
+ MOLECULE_PATTERN = /%[a-zA-Z]/
5
+ ANSI_SGR_PATTERN = /\e\[[\d;]+m/
6
+
7
+ def displayable_length
8
+ gsub(ANSI_SGR_PATTERN, '').length
9
+ end
10
+
11
+ def bar_molecule_placeholder_length
12
+ @bar_molecule_placeholder_length ||= bar_molecules.size * 2
13
+ end
14
+
15
+ def non_bar_molecules
16
+ @non_bar_molecules ||= molecules.select(&:non_bar_molecule?)
17
+ end
18
+
19
+ def bar_molecules
20
+ @bar_molecules ||= molecules.select(&:bar_molecule?)
21
+ end
22
+
23
+ def molecules
24
+ @molecules ||= begin
25
+ molecules = []
26
+
27
+ scan(MOLECULE_PATTERN) do |match|
28
+ molecules << Molecule.new(match[1, 1])
29
+ end
30
+
31
+ molecules
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,61 @@
1
+ class ProgressBar
2
+ class Output
3
+ DEFAULT_OUTPUT_STREAM = $stdout
4
+
5
+ attr_accessor :stream
6
+
7
+ def initialize(options = {})
8
+ self.bar = options[:bar]
9
+ self.stream = options[:output] || DEFAULT_OUTPUT_STREAM
10
+ self.length_calculator = Calculators::Length.new(options)
11
+ self.throttle = Throttle.new(options)
12
+ end
13
+
14
+ def self.detect(options = {})
15
+ if (options[:output] || DEFAULT_OUTPUT_STREAM).tty?
16
+ Outputs::Tty.new(options)
17
+ else
18
+ Outputs::NonTty.new(options)
19
+ end
20
+ end
21
+
22
+ def log(string)
23
+ clear
24
+ stream.puts string
25
+
26
+ refresh(:force => true) unless bar.stopped?
27
+ end
28
+
29
+ def clear_string
30
+ ' ' * length_calculator.length
31
+ end
32
+
33
+ def length
34
+ length_calculator.length
35
+ end
36
+
37
+ def with_refresh
38
+ yield
39
+ refresh
40
+ end
41
+
42
+ def refresh(options = {})
43
+ throttle.choke(:force_update_if => (bar.stopped? || options[:force])) do
44
+ clear if length_calculator.length_changed?
45
+
46
+ print_and_flush
47
+ end
48
+ end
49
+
50
+ def print_and_flush
51
+ stream.print bar_update_string + eol
52
+ stream.flush
53
+ end
54
+
55
+ protected
56
+
57
+ attr_accessor :length_calculator,
58
+ :throttle,
59
+ :bar
60
+ end
61
+ end
@@ -0,0 +1,47 @@
1
+ require 'ruby-progressbar/output'
2
+
3
+ class ProgressBar
4
+ module Outputs
5
+ class NonTty < Output
6
+ DEFAULT_FORMAT_STRING = '%t: |%b|'
7
+
8
+ def clear
9
+ self.last_update_length = 0
10
+
11
+ stream.print "\n"
12
+ end
13
+
14
+ def last_update_length
15
+ @last_update_length ||= 0
16
+ end
17
+
18
+ def bar_update_string
19
+ formatted_string = bar.to_s
20
+ formatted_string = formatted_string[0...-1] unless bar.finished?
21
+
22
+ output_string = formatted_string[last_update_length..-1]
23
+ self.last_update_length = formatted_string.length
24
+
25
+ output_string
26
+ end
27
+
28
+ def default_format
29
+ DEFAULT_FORMAT_STRING
30
+ end
31
+
32
+ def resolve_format(*)
33
+ default_format
34
+ end
35
+
36
+ def refresh_with_format_change(*); end
37
+
38
+ def eol
39
+ bar.stopped? ? "\n" : ''
40
+ end
41
+
42
+ protected
43
+
44
+ attr_accessor :last_update_length
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ require 'ruby-progressbar/output'
2
+
3
+ class ProgressBar
4
+ module Outputs
5
+ class Tty < Output
6
+ DEFAULT_FORMAT_STRING = '%t: |%B|'
7
+
8
+ alias_method :refresh_with_format_change, :with_refresh
9
+
10
+ def clear
11
+ stream.print clear_string
12
+ stream.print "\r"
13
+ end
14
+
15
+ def bar_update_string
16
+ bar.to_s
17
+ end
18
+
19
+ def default_format
20
+ DEFAULT_FORMAT_STRING
21
+ end
22
+
23
+ def resolve_format(other_format)
24
+ other_format || default_format
25
+ end
26
+
27
+ def eol
28
+ bar.stopped? ? "\n" : "\r"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,110 @@
1
+ require 'ruby-progressbar/errors/invalid_progress_error'
2
+
3
+ class ProgressBar
4
+ class Progress
5
+ DEFAULT_TOTAL = 100
6
+ DEFAULT_BEGINNING_POSITION = 0
7
+ DEFAULT_SMOOTHING = 0.1
8
+
9
+ attr_accessor :total,
10
+ :progress,
11
+ :starting_position,
12
+ :running_average,
13
+ :smoothing
14
+
15
+ def initialize(options = {})
16
+ self.total = options.fetch(:total, DEFAULT_TOTAL)
17
+ self.smoothing = options[:smoothing] || DEFAULT_SMOOTHING
18
+
19
+ start :at => DEFAULT_BEGINNING_POSITION
20
+ end
21
+
22
+ def start(options = {})
23
+ self.running_average = 0
24
+ self.progress = \
25
+ self.starting_position = options[:at] || progress
26
+ end
27
+
28
+ def finish
29
+ self.progress = total
30
+ end
31
+
32
+ def finished?
33
+ @progress == @total
34
+ end
35
+
36
+ def increment
37
+ warn "WARNING: Your progress bar is currently at #{progress} out of #{total} " \
38
+ 'and cannot be incremented. In v2.0.0 this will become a ' \
39
+ 'ProgressBar::InvalidProgressError.' if progress == total
40
+
41
+ self.progress += 1 unless progress == total
42
+ end
43
+
44
+ def decrement
45
+ warn "WARNING: Your progress bar is currently at #{progress} out of #{total} " \
46
+ 'and cannot be decremented. In v2.0.0 this will become a ' \
47
+ 'ProgressBar::InvalidProgressError.' if progress == 0
48
+
49
+ self.progress -= 1 unless progress == 0
50
+ end
51
+
52
+ def reset
53
+ start :at => starting_position
54
+ end
55
+
56
+ def progress=(new_progress)
57
+ fail ProgressBar::InvalidProgressError,
58
+ "You can't set the item's current value to be greater than the total." \
59
+ if total &&
60
+ new_progress > total
61
+
62
+ @progress = new_progress
63
+
64
+ self.running_average = Calculators::RunningAverage.calculate(running_average,
65
+ absolute,
66
+ smoothing)
67
+ end
68
+
69
+ def total=(new_total)
70
+ fail ProgressBar::InvalidProgressError,
71
+ "You can't set the item's total value to less than the current progress." \
72
+ unless progress.nil? ||
73
+ new_total.nil? ||
74
+ new_total >= progress
75
+
76
+ @total = new_total
77
+ end
78
+
79
+ def percentage_completed
80
+ return 0 if total.nil?
81
+ return 100 if total.zero?
82
+
83
+ # progress / total * 100
84
+ #
85
+ # Doing this way so we can avoid converting each
86
+ # number to a float and then back to an integer.
87
+ #
88
+ (progress * 100 / total).to_i
89
+ end
90
+
91
+ def none?
92
+ progress.zero?
93
+ end
94
+
95
+ def unknown?
96
+ progress.nil? || total.nil?
97
+ end
98
+
99
+ def percentage_completed_with_precision
100
+ return 100.0 if total == 0
101
+ return 0.0 if total.nil?
102
+
103
+ format('%5.2f', (progress.to_f * 100.0 / total * 100.0).floor / 100.0)
104
+ end
105
+
106
+ def absolute
107
+ progress - starting_position
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,25 @@
1
+ class ProgressBar
2
+ class Throttle
3
+ attr_accessor :rate,
4
+ :started_at,
5
+ :stopped_at,
6
+ :timer
7
+
8
+ def initialize(options = {})
9
+ self.rate = options[:throttle_rate] || 0.01
10
+ self.started_at = nil
11
+ self.stopped_at = nil
12
+ self.timer = options.fetch(:throttle_timer, Timer.new)
13
+ end
14
+
15
+ def choke(options = {})
16
+ return unless !timer.started? ||
17
+ options.fetch(:force_update_if, false) ||
18
+ timer.elapsed_seconds >= rate
19
+
20
+ timer.restart
21
+
22
+ yield
23
+ end
24
+ end
25
+ end
@@ -1,22 +1,25 @@
1
- class ProgressBar
2
- class Time
3
- def self.now(time = ::Time)
4
- @@time = time
1
+ class ProgressBar
2
+ class Time
3
+ def self.now(time = ::Time)
4
+ @time = time
5
5
 
6
- @@time.send unmocked_time_method
7
- end
6
+ @time.send unmocked_time_method
7
+ end
8
8
 
9
- private
10
- def self.unmocked_time_method
11
- time_mocking_library_methods.find { |method| @@time.respond_to? method }
12
- end
9
+ def self.unmocked_time_method
10
+ @unmocked_time_method ||= begin
11
+ time_mocking_library_methods.find do |method|
12
+ @time.respond_to? method
13
+ end
14
+ end
15
+ end
13
16
 
14
- def self.time_mocking_library_methods
15
- [
16
- :now_without_mock_time, # Timecop
17
- :now_without_delorean, # Delorean
18
- :now # Actual
19
- ]
20
- end
17
+ def self.time_mocking_library_methods
18
+ [
19
+ :now_without_mock_time, # Timecop
20
+ :now_without_delorean, # Delorean
21
+ :now # Actual
22
+ ]
21
23
  end
22
24
  end
25
+ end