progressbar 0.21.0 → 1.8.1

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. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/LICENSE.txt +19 -0
  5. data/README.md +38 -0
  6. data/Rakefile +2 -14
  7. data/lib/progressbar.rb +14 -284
  8. data/lib/ruby-progressbar/base.rb +161 -0
  9. data/lib/ruby-progressbar/calculators/length.rb +88 -0
  10. data/lib/ruby-progressbar/calculators/length_spec.rb +9 -0
  11. data/lib/ruby-progressbar/calculators/running_average.rb +9 -0
  12. data/lib/ruby-progressbar/components.rb +5 -0
  13. data/lib/ruby-progressbar/components/bar.rb +96 -0
  14. data/lib/ruby-progressbar/components/percentage.rb +29 -0
  15. data/lib/ruby-progressbar/components/rate.rb +43 -0
  16. data/lib/ruby-progressbar/components/time.rb +103 -0
  17. data/lib/ruby-progressbar/components/title.rb +13 -0
  18. data/lib/ruby-progressbar/errors/invalid_progress_error.rb +4 -0
  19. data/lib/ruby-progressbar/format.rb +3 -0
  20. data/lib/ruby-progressbar/format/formatter.rb +27 -0
  21. data/lib/ruby-progressbar/format/molecule.rb +58 -0
  22. data/lib/ruby-progressbar/format/string.rb +36 -0
  23. data/lib/ruby-progressbar/output.rb +61 -0
  24. data/lib/ruby-progressbar/outputs/non_tty.rb +47 -0
  25. data/lib/ruby-progressbar/outputs/tty.rb +32 -0
  26. data/lib/ruby-progressbar/progress.rb +114 -0
  27. data/lib/ruby-progressbar/throttle.rb +25 -0
  28. data/lib/ruby-progressbar/time.rb +30 -0
  29. data/lib/ruby-progressbar/timer.rb +72 -0
  30. data/lib/ruby-progressbar/version.rb +3 -0
  31. data/spec/fixtures/benchmark.rb +28 -0
  32. data/spec/ruby-progressbar/base_spec.rb +949 -0
  33. data/spec/ruby-progressbar/calculators/length_calculator_spec.rb +17 -0
  34. data/spec/ruby-progressbar/calculators/running_average_spec.rb +19 -0
  35. data/spec/ruby-progressbar/components/bar_spec.rb +234 -0
  36. data/spec/ruby-progressbar/components/percentage_spec.rb +9 -0
  37. data/spec/ruby-progressbar/components/rate_spec.rb +9 -0
  38. data/spec/ruby-progressbar/components/throttle_spec.rb +157 -0
  39. data/spec/ruby-progressbar/components/time_spec.rb +307 -0
  40. data/spec/ruby-progressbar/components/title_spec.rb +12 -0
  41. data/spec/ruby-progressbar/format/formatter_spec.rb +9 -0
  42. data/spec/ruby-progressbar/format/molecule_spec.rb +30 -0
  43. data/spec/ruby-progressbar/format/string_spec.rb +9 -0
  44. data/spec/ruby-progressbar/output_spec.rb +7 -0
  45. data/spec/ruby-progressbar/outputs/non_tty_spec.rb +9 -0
  46. data/spec/ruby-progressbar/outputs/tty_spec.rb +9 -0
  47. data/spec/ruby-progressbar/progress_spec.rb +156 -0
  48. data/spec/ruby-progressbar/time_spec.rb +45 -0
  49. data/spec/ruby-progressbar/timer_spec.rb +7 -0
  50. data/spec/spec_helper.rb +6 -0
  51. data/spec/support/time.rb +17 -0
  52. metadata +134 -69
  53. metadata.gz.sig +3 -0
  54. data/.gitignore +0 -23
  55. data/.ruby-version +0 -1
  56. data/.travis.yml +0 -6
  57. data/ChangeLog +0 -113
  58. data/Gemfile +0 -4
  59. data/Gemfile.lock +0 -27
  60. data/LICENSE +0 -1
  61. data/README.rdoc +0 -116
  62. data/progressbar.gemspec +0 -29
  63. data/test/test.rb +0 -125
@@ -0,0 +1,58 @@
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
+ }.freeze
24
+
25
+ BAR_MOLECULES = %w{w B b i}.freeze
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
54
+ end
55
+ end
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|'.freeze
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_writer :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|'.freeze
7
+
8
+ alias 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,114 @@
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_reader :total,
10
+ :progress
11
+
12
+ attr_accessor :starting_position,
13
+ :running_average,
14
+ :smoothing
15
+
16
+ def initialize(options = {})
17
+ self.total = options.fetch(:total, DEFAULT_TOTAL)
18
+ self.smoothing = options[:smoothing] || DEFAULT_SMOOTHING
19
+
20
+ start :at => DEFAULT_BEGINNING_POSITION
21
+ end
22
+
23
+ def start(options = {})
24
+ self.running_average = 0
25
+ self.progress = \
26
+ self.starting_position = options[:at] || progress
27
+ end
28
+
29
+ def finish
30
+ self.progress = total unless unknown?
31
+ end
32
+
33
+ def finished?
34
+ @progress == @total
35
+ end
36
+
37
+ def increment
38
+ if progress == total
39
+ warn "WARNING: Your progress bar is currently at #{progress} out of #{total} " \
40
+ "and cannot be incremented. In v2.0.0 this will become a " \
41
+ "ProgressBar::InvalidProgressError."
42
+ end
43
+
44
+ self.progress += 1 unless progress == total
45
+ end
46
+
47
+ def decrement
48
+ if progress == 0
49
+ warn "WARNING: Your progress bar is currently at #{progress} out of #{total} " \
50
+ "and cannot be decremented. In v2.0.0 this will become a " \
51
+ "ProgressBar::InvalidProgressError."
52
+ end
53
+
54
+ self.progress -= 1 unless progress == 0
55
+ end
56
+
57
+ def reset
58
+ start :at => starting_position
59
+ end
60
+
61
+ def progress=(new_progress)
62
+ if total && new_progress > total
63
+ fail ProgressBar::InvalidProgressError,
64
+ "You can't set the item's current value to be greater than the total."
65
+ end
66
+
67
+ @progress = new_progress
68
+
69
+ self.running_average = Calculators::RunningAverage.calculate(running_average,
70
+ absolute,
71
+ smoothing)
72
+ end
73
+
74
+ def total=(new_total)
75
+ unless progress.nil? || new_total.nil? || new_total >= progress
76
+ fail ProgressBar::InvalidProgressError,
77
+ "You can't set the item's total value to less than the current progress."
78
+ end
79
+
80
+ @total = new_total
81
+ end
82
+
83
+ def percentage_completed
84
+ return 0 if total.nil?
85
+ return 100 if total == 0
86
+
87
+ # progress / total * 100
88
+ #
89
+ # Doing this way so we can avoid converting each
90
+ # number to a float and then back to an integer.
91
+ #
92
+ (progress * 100 / total).to_i
93
+ end
94
+
95
+ def none?
96
+ running_average.zero? || progress.zero?
97
+ end
98
+
99
+ def unknown?
100
+ progress.nil? || total.nil?
101
+ end
102
+
103
+ def percentage_completed_with_precision
104
+ return 100.0 if total == 0
105
+ return 0.0 if total.nil?
106
+
107
+ '%5.2f' % [(progress * 100 / total.to_f * 100).floor / 100.0]
108
+ end
109
+
110
+ def absolute
111
+ progress - starting_position
112
+ end
113
+ end
114
+ 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
@@ -0,0 +1,30 @@
1
+ class ProgressBar
2
+ class Time
3
+ TIME_MOCKING_LIBRARY_METHODS = [
4
+ :__simple_stub__now, # ActiveSupport
5
+ :now_without_mock_time, # Timecop
6
+ :now_without_delorean, # Delorean
7
+ :now # Actual
8
+ ].freeze
9
+
10
+ def initialize(time = ::Time)
11
+ self.time = time
12
+ end
13
+
14
+ def now
15
+ time.__send__ unmocked_time_method
16
+ end
17
+
18
+ def unmocked_time_method
19
+ @unmocked_time_method ||= begin
20
+ TIME_MOCKING_LIBRARY_METHODS.find do |method|
21
+ time.respond_to? method
22
+ end
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ attr_accessor :time
29
+ end
30
+ end
@@ -0,0 +1,72 @@
1
+ require 'ruby-progressbar/time'
2
+
3
+ class ProgressBar
4
+ class Timer
5
+ attr_accessor :started_at,
6
+ :stopped_at
7
+
8
+ def initialize(options = {})
9
+ self.time = options[:time] || Time.new
10
+ end
11
+
12
+ def start
13
+ self.started_at = stopped? ? time.now - (stopped_at - started_at) : time.now
14
+ self.stopped_at = nil
15
+ end
16
+
17
+ def stop
18
+ return unless started?
19
+
20
+ self.stopped_at = time.now
21
+ end
22
+
23
+ def pause
24
+ stop
25
+ end
26
+
27
+ def resume
28
+ start
29
+ end
30
+
31
+ def started?
32
+ started_at
33
+ end
34
+
35
+ def stopped?
36
+ stopped_at
37
+ end
38
+
39
+ def reset
40
+ self.started_at = nil
41
+ self.stopped_at = nil
42
+ end
43
+
44
+ def reset?
45
+ !started_at
46
+ end
47
+
48
+ def restart
49
+ reset
50
+ start
51
+ end
52
+
53
+ def elapsed_seconds
54
+ ((stopped_at || time.now) - started_at)
55
+ end
56
+
57
+ def elapsed_whole_seconds
58
+ elapsed_seconds.floor
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
+
68
+ protected
69
+
70
+ attr_accessor :time
71
+ end
72
+ end