progressbar 0.21.0 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/LICENSE.txt +19 -0
- data/README.md +38 -0
- data/Rakefile +2 -14
- data/lib/progressbar.rb +14 -284
- data/lib/ruby-progressbar/base.rb +161 -0
- data/lib/ruby-progressbar/calculators/length.rb +88 -0
- data/lib/ruby-progressbar/calculators/length_spec.rb +9 -0
- data/lib/ruby-progressbar/calculators/running_average.rb +9 -0
- data/lib/ruby-progressbar/components.rb +5 -0
- data/lib/ruby-progressbar/components/bar.rb +96 -0
- data/lib/ruby-progressbar/components/percentage.rb +29 -0
- data/lib/ruby-progressbar/components/rate.rb +43 -0
- data/lib/ruby-progressbar/components/time.rb +103 -0
- data/lib/ruby-progressbar/components/title.rb +13 -0
- data/lib/ruby-progressbar/errors/invalid_progress_error.rb +4 -0
- data/lib/ruby-progressbar/format.rb +3 -0
- data/lib/ruby-progressbar/format/formatter.rb +27 -0
- data/lib/ruby-progressbar/format/molecule.rb +58 -0
- data/lib/ruby-progressbar/format/string.rb +36 -0
- data/lib/ruby-progressbar/output.rb +61 -0
- data/lib/ruby-progressbar/outputs/non_tty.rb +47 -0
- data/lib/ruby-progressbar/outputs/tty.rb +32 -0
- data/lib/ruby-progressbar/progress.rb +114 -0
- data/lib/ruby-progressbar/throttle.rb +25 -0
- data/lib/ruby-progressbar/time.rb +30 -0
- data/lib/ruby-progressbar/timer.rb +72 -0
- data/lib/ruby-progressbar/version.rb +3 -0
- data/spec/fixtures/benchmark.rb +28 -0
- data/spec/ruby-progressbar/base_spec.rb +949 -0
- data/spec/ruby-progressbar/calculators/length_calculator_spec.rb +17 -0
- data/spec/ruby-progressbar/calculators/running_average_spec.rb +19 -0
- data/spec/ruby-progressbar/components/bar_spec.rb +234 -0
- data/spec/ruby-progressbar/components/percentage_spec.rb +9 -0
- data/spec/ruby-progressbar/components/rate_spec.rb +9 -0
- data/spec/ruby-progressbar/components/throttle_spec.rb +157 -0
- data/spec/ruby-progressbar/components/time_spec.rb +307 -0
- data/spec/ruby-progressbar/components/title_spec.rb +12 -0
- data/spec/ruby-progressbar/format/formatter_spec.rb +9 -0
- data/spec/ruby-progressbar/format/molecule_spec.rb +30 -0
- data/spec/ruby-progressbar/format/string_spec.rb +9 -0
- data/spec/ruby-progressbar/output_spec.rb +7 -0
- data/spec/ruby-progressbar/outputs/non_tty_spec.rb +9 -0
- data/spec/ruby-progressbar/outputs/tty_spec.rb +9 -0
- data/spec/ruby-progressbar/progress_spec.rb +156 -0
- data/spec/ruby-progressbar/time_spec.rb +45 -0
- data/spec/ruby-progressbar/timer_spec.rb +7 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/time.rb +17 -0
- metadata +134 -69
- metadata.gz.sig +3 -0
- data/.gitignore +0 -23
- data/.ruby-version +0 -1
- data/.travis.yml +0 -6
- data/ChangeLog +0 -113
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -27
- data/LICENSE +0 -1
- data/README.rdoc +0 -116
- data/progressbar.gemspec +0 -29
- data/test/test.rb +0 -125
@@ -0,0 +1,88 @@
|
|
1
|
+
class ProgressBar
|
2
|
+
module Calculators
|
3
|
+
class Length
|
4
|
+
attr_reader :length_override
|
5
|
+
attr_accessor :current_length
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
self.length_override = options[:length]
|
9
|
+
self.current_length = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def length
|
13
|
+
current_length || reset_length
|
14
|
+
end
|
15
|
+
|
16
|
+
def length_changed?
|
17
|
+
previous_length = current_length
|
18
|
+
self.current_length = calculate_length
|
19
|
+
|
20
|
+
previous_length != current_length
|
21
|
+
end
|
22
|
+
|
23
|
+
def calculate_length
|
24
|
+
length_override || terminal_width || 80
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset_length
|
28
|
+
self.current_length = calculate_length
|
29
|
+
end
|
30
|
+
|
31
|
+
def length_override=(other)
|
32
|
+
@length_override ||= ENV['RUBY_PROGRESS_BAR_LENGTH'] || other
|
33
|
+
@length_override = @length_override.to_i if @length_override
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# This code was copied and modified from Rake, available under MIT-LICENSE
|
39
|
+
# Copyright (c) 2003, 2004 Jim Weirich
|
40
|
+
def terminal_width
|
41
|
+
return 80 unless unix?
|
42
|
+
|
43
|
+
result = dynamic_width
|
44
|
+
result < 20 ? 80 : result
|
45
|
+
rescue
|
46
|
+
80
|
47
|
+
end
|
48
|
+
|
49
|
+
# rubocop:disable Lint/DuplicateMethods
|
50
|
+
begin
|
51
|
+
require 'io/console'
|
52
|
+
|
53
|
+
def dynamic_width
|
54
|
+
if IO.console
|
55
|
+
dynamic_width_via_io_object
|
56
|
+
else
|
57
|
+
dynamic_width_via_system_calls
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue LoadError
|
61
|
+
def dynamic_width
|
62
|
+
dynamic_width_via_system_calls
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def dynamic_width_via_io_object
|
67
|
+
_rows, columns = IO.console.winsize
|
68
|
+
columns
|
69
|
+
end
|
70
|
+
|
71
|
+
def dynamic_width_via_system_calls
|
72
|
+
dynamic_width_stty.nonzero? || dynamic_width_tput
|
73
|
+
end
|
74
|
+
|
75
|
+
def dynamic_width_stty
|
76
|
+
`stty size 2>/dev/null`.split[1].to_i
|
77
|
+
end
|
78
|
+
|
79
|
+
def dynamic_width_tput
|
80
|
+
`tput cols 2>/dev/null`.to_i
|
81
|
+
end
|
82
|
+
|
83
|
+
def unix?
|
84
|
+
RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
###
|
2
|
+
# UPA = Unknown Progress Animation
|
3
|
+
#
|
4
|
+
class ProgressBar
|
5
|
+
module Components
|
6
|
+
class Bar
|
7
|
+
DEFAULT_PROGRESS_MARK = '='.freeze
|
8
|
+
DEFAULT_REMAINDER_MARK = ' '.freeze
|
9
|
+
DEFAULT_UPA_STEPS = ['=---', '-=--', '--=-', '---='].freeze
|
10
|
+
|
11
|
+
attr_accessor :progress_mark,
|
12
|
+
:remainder_mark,
|
13
|
+
:length,
|
14
|
+
:progress,
|
15
|
+
:upa_steps
|
16
|
+
|
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
|
24
|
+
|
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
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def integrated_percentage_complete_string
|
38
|
+
return standard_complete_string if completed_length < 5
|
39
|
+
|
40
|
+
" #{progress.percentage_completed} ".to_s.center(completed_length, progress_mark)
|
41
|
+
end
|
42
|
+
|
43
|
+
def standard_complete_string
|
44
|
+
progress_mark * completed_length
|
45
|
+
end
|
46
|
+
|
47
|
+
def incomplete_string
|
48
|
+
remainder_mark * (length - completed_length)
|
49
|
+
end
|
50
|
+
|
51
|
+
def bar(length)
|
52
|
+
self.length = length
|
53
|
+
|
54
|
+
standard_complete_string
|
55
|
+
end
|
56
|
+
|
57
|
+
def complete_bar(length)
|
58
|
+
self.length = length
|
59
|
+
|
60
|
+
to_s
|
61
|
+
end
|
62
|
+
|
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
|
68
|
+
|
69
|
+
def incomplete_space(length)
|
70
|
+
self.length = length
|
71
|
+
|
72
|
+
if progress.unknown?
|
73
|
+
unknown_string
|
74
|
+
else
|
75
|
+
incomplete_string
|
76
|
+
end
|
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
|
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
|
@@ -0,0 +1,43 @@
|
|
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
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def rate_of_change(format_string = '%i')
|
21
|
+
return 0 unless elapsed_seconds.positive?
|
22
|
+
|
23
|
+
format_string % scaled_rate
|
24
|
+
end
|
25
|
+
|
26
|
+
def rate_of_change_with_precision
|
27
|
+
rate_of_change('%.2f')
|
28
|
+
end
|
29
|
+
|
30
|
+
def scaled_rate
|
31
|
+
rate_scale.call(base_rate)
|
32
|
+
end
|
33
|
+
|
34
|
+
def base_rate
|
35
|
+
progress.absolute / elapsed_seconds
|
36
|
+
end
|
37
|
+
|
38
|
+
def elapsed_seconds
|
39
|
+
timer.elapsed_whole_seconds.to_f
|
40
|
+
end
|
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'.freeze
|
8
|
+
OOB_TIME_FORMATS = [:unknown, :friendly, nil].freeze
|
9
|
+
OOB_LIMIT_IN_HOURS = 99
|
10
|
+
OOB_UNKNOWN_TIME_TEXT = '??:??:??'.freeze
|
11
|
+
OOB_FRIENDLY_TIME_TEXT = '> 4 Days'.freeze
|
12
|
+
NO_TIME_ELAPSED_TEXT = '--:--:--'.freeze
|
13
|
+
ESTIMATED_LABEL = ' ETA'.freeze
|
14
|
+
ELAPSED_LABEL = 'Time'.freeze
|
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_reader :out_of_bounds_time_format
|
51
|
+
attr_accessor :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,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.negative? ? 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
|