tty-progressbar 0.14.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +98 -21
  3. data/LICENSE.txt +1 -1
  4. data/README.md +511 -119
  5. data/lib/tty-progressbar.rb +2 -2
  6. data/lib/tty/progressbar.rb +216 -87
  7. data/lib/tty/progressbar/configuration.rb +124 -16
  8. data/lib/tty/progressbar/converter.rb +16 -19
  9. data/lib/tty/progressbar/formats.rb +120 -0
  10. data/lib/tty/progressbar/formatter.rb +33 -38
  11. data/lib/tty/progressbar/formatter/bar.rb +87 -29
  12. data/lib/tty/progressbar/formatter/byte_rate.rb +6 -20
  13. data/lib/tty/progressbar/formatter/current.rb +4 -19
  14. data/lib/tty/progressbar/formatter/current_byte.rb +9 -17
  15. data/lib/tty/progressbar/formatter/elapsed.rb +9 -18
  16. data/lib/tty/progressbar/formatter/estimated.rb +14 -18
  17. data/lib/tty/progressbar/formatter/estimated_time.rb +37 -0
  18. data/lib/tty/progressbar/formatter/mean_byte.rb +6 -20
  19. data/lib/tty/progressbar/formatter/mean_rate.rb +6 -20
  20. data/lib/tty/progressbar/formatter/percent.rb +10 -16
  21. data/lib/tty/progressbar/formatter/rate.rb +5 -19
  22. data/lib/tty/progressbar/formatter/total.rb +10 -16
  23. data/lib/tty/progressbar/formatter/total_byte.rb +14 -18
  24. data/lib/tty/progressbar/formatters.rb +53 -0
  25. data/lib/tty/progressbar/meter.rb +2 -2
  26. data/lib/tty/progressbar/multi.rb +69 -23
  27. data/lib/tty/progressbar/pipeline.rb +13 -6
  28. data/lib/tty/progressbar/timer.rb +89 -0
  29. data/lib/tty/progressbar/version.rb +3 -1
  30. metadata +65 -151
  31. data/.codeclimate.yml +0 -11
  32. data/.gitignore +0 -14
  33. data/.rspec +0 -3
  34. data/.travis.yml +0 -25
  35. data/CODE_OF_CONDUCT.md +0 -74
  36. data/Gemfile +0 -14
  37. data/Rakefile +0 -8
  38. data/appveyor.yml +0 -21
  39. data/examples/color.rb +0 -18
  40. data/examples/failure.rb +0 -12
  41. data/examples/iterator.rb +0 -5
  42. data/examples/lazy.rb +0 -6
  43. data/examples/multi/main_bar.rb +0 -13
  44. data/examples/multi/simple.rb +0 -13
  45. data/examples/simple.rb +0 -7
  46. data/examples/slow_process.rb +0 -29
  47. data/examples/speed.rb +0 -11
  48. data/examples/threaded.rb +0 -14
  49. data/examples/tokens.rb +0 -12
  50. data/spec/spec_helper.rb +0 -50
  51. data/spec/unit/advance_spec.rb +0 -25
  52. data/spec/unit/clear_spec.rb +0 -17
  53. data/spec/unit/complete_spec.rb +0 -16
  54. data/spec/unit/converter/to_bytes_spec.rb +0 -47
  55. data/spec/unit/converter/to_seconds_spec.rb +0 -15
  56. data/spec/unit/converter/to_time_spec.rb +0 -19
  57. data/spec/unit/custom_formatter_spec.rb +0 -26
  58. data/spec/unit/custom_token_spec.rb +0 -14
  59. data/spec/unit/events_spec.rb +0 -33
  60. data/spec/unit/finish_spec.rb +0 -15
  61. data/spec/unit/formatter/bar_spec.rb +0 -16
  62. data/spec/unit/formatter/byte_rate_spec.rb +0 -32
  63. data/spec/unit/formatter/current_byte_spec.rb +0 -16
  64. data/spec/unit/formatter/current_spec.rb +0 -14
  65. data/spec/unit/formatter/elapsed_spec.rb +0 -58
  66. data/spec/unit/formatter/estimated_spec.rb +0 -27
  67. data/spec/unit/formatter/mean_byte_spec.rb +0 -32
  68. data/spec/unit/formatter/mean_rate_spec.rb +0 -31
  69. data/spec/unit/formatter/percent_spec.rb +0 -16
  70. data/spec/unit/formatter/rate_spec.rb +0 -31
  71. data/spec/unit/formatter/total_byte_spec.rb +0 -16
  72. data/spec/unit/formatter/total_spec.rb +0 -16
  73. data/spec/unit/frequency_spec.rb +0 -27
  74. data/spec/unit/head_spec.rb +0 -32
  75. data/spec/unit/hide_cursor_spec.rb +0 -27
  76. data/spec/unit/inspect_spec.rb +0 -11
  77. data/spec/unit/iterate_spec.rb +0 -79
  78. data/spec/unit/log_spec.rb +0 -29
  79. data/spec/unit/meter_spec.rb +0 -70
  80. data/spec/unit/multi/advance_spec.rb +0 -123
  81. data/spec/unit/multi/events_spec.rb +0 -115
  82. data/spec/unit/multi/finish_spec.rb +0 -41
  83. data/spec/unit/multi/line_inset_spec.rb +0 -65
  84. data/spec/unit/multi/register_spec.rb +0 -35
  85. data/spec/unit/multi/stop_spec.rb +0 -15
  86. data/spec/unit/new_spec.rb +0 -66
  87. data/spec/unit/pipeline_spec.rb +0 -19
  88. data/spec/unit/ratio_spec.rb +0 -31
  89. data/spec/unit/reset_spec.rb +0 -31
  90. data/spec/unit/resize_spec.rb +0 -35
  91. data/spec/unit/set_current_spec.rb +0 -43
  92. data/spec/unit/start_spec.rb +0 -14
  93. data/spec/unit/stop_spec.rb +0 -19
  94. data/spec/unit/update_spec.rb +0 -22
  95. data/spec/unit/width_spec.rb +0 -21
  96. data/tasks/console.rake +0 -9
  97. data/tasks/coverage.rake +0 -9
  98. data/tasks/spec.rake +0 -27
  99. data/tty-progressbar.gemspec +0 -30
@@ -1,27 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../formatter"
4
+
3
5
  module TTY
4
6
  class ProgressBar
5
7
  # Used by {Pipeline} to format bar
6
8
  #
7
9
  # @api private
8
10
  class BarFormatter
9
- MATCHER = /:bar/.freeze
10
-
11
- def initialize(progress)
12
- @progress = progress
13
- end
14
-
15
- # Determines whether this formatter is applied or not.
16
- #
17
- # @param [Object] value
18
- #
19
- # @return [Boolean]
20
- #
21
- # @api private
22
- def matches?(value)
23
- !!(value.to_s =~ MATCHER)
24
- end
11
+ include TTY::ProgressBar::Formatter[/:bar/i.freeze]
25
12
 
26
13
  # Format :bar token
27
14
  #
@@ -29,19 +16,90 @@ module TTY
29
16
  # the value being formatted
30
17
  #
31
18
  # @api public
32
- def format(value)
33
- available_space = [0, @progress.max_columns - value.gsub(/:bar/, '').length].max
34
- width = [@progress.width, available_space].min
35
- complete_length = (width * @progress.ratio).round
36
- complete = Array.new(complete_length, @progress.complete)
37
- incomplete = Array.new(width - complete_length, @progress.incomplete)
38
- complete[-1] = @progress.head if complete_length > 0
39
-
40
- bar = ''
41
- bar += complete.join
42
- bar += incomplete.join
43
-
44
- value.gsub(MATCHER, bar)
19
+ def call(value)
20
+ without_bar = value.gsub(/:bar/, "")
21
+ available_space = [0, ProgressBar.max_columns -
22
+ ProgressBar.display_columns(without_bar) -
23
+ @progress.inset].max
24
+ width = [@progress.width.to_i, available_space].min
25
+
26
+ # When we don't know the total progress, use either user
27
+ # defined width or rely on terminal width detection
28
+ if @progress.indeterminate?
29
+ width = available_space if width.zero?
30
+
31
+ format_indeterminate(value, width)
32
+ else
33
+ format_determinate(value, width)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ # @api private
40
+ def format_indeterminate(value, width)
41
+ buffer = []
42
+ possible_width = width
43
+ unknown_char_length = ProgressBar.display_columns(@progress.unknown)
44
+ complete_char_length = ProgressBar.display_columns(@progress.complete)
45
+ incomplete_char_length = ProgressBar.display_columns(@progress.incomplete)
46
+ head_char_length = ProgressBar.display_columns(@progress.head)
47
+
48
+ possible_width -= unknown_char_length
49
+ max_char_length = [complete_char_length, incomplete_char_length,
50
+ head_char_length].max
51
+ # figure out how many unicode chars would fit normally
52
+ # when the bar has total to prevent resizing
53
+ possible_width = (possible_width / max_char_length) * max_char_length
54
+ complete = (possible_width * @progress.ratio).round
55
+ incomplete = possible_width - complete
56
+
57
+ buffer << " " * complete
58
+ buffer << @progress.unknown
59
+ buffer << " " * incomplete
60
+
61
+ value.gsub(matcher, buffer.join)
62
+ end
63
+
64
+ # @api private
65
+ def format_determinate(value, width)
66
+ complete_bar_length = (width * @progress.ratio).round
67
+ complete_char_length = ProgressBar.display_columns(@progress.complete)
68
+ incomplete_char_length = ProgressBar.display_columns(@progress.incomplete)
69
+ head_char_length = ProgressBar.display_columns(@progress.head)
70
+
71
+ # division by char length only when unicode chars are used
72
+ # otherwise it has no effect on regular ascii chars
73
+ complete_items = [
74
+ complete_bar_length / complete_char_length,
75
+ # or see how many incomplete (unicode) items fit
76
+ (complete_bar_length / incomplete_char_length) * incomplete_char_length
77
+ ].min
78
+
79
+ complete_width = complete_items * complete_char_length
80
+ incomplete_width = width - complete_width
81
+ incomplete_items = [
82
+ incomplete_width / incomplete_char_length,
83
+ # or see how many complete (unicode) items fit
84
+ (incomplete_width / complete_char_length) * complete_char_length
85
+ ].min
86
+
87
+ complete = Array.new(complete_items, @progress.complete)
88
+ incomplete = Array.new(incomplete_items, @progress.incomplete)
89
+
90
+ if complete_items > 0 && head_char_length > 0 &&
91
+ (incomplete_items > 0 || incomplete_items.zero? && !@progress.clear_head)
92
+ # see how many head chars per complete char
93
+ times = (head_char_length / complete_char_length.to_f).round
94
+ if complete_items < times # not enough complete chars to fit
95
+ incomplete.pop(times - complete_items)
96
+ end
97
+ complete.pop(times)
98
+ extra_space = " " * (times * complete_char_length - head_char_length)
99
+ complete << "#{@progress.head}#{extra_space}"
100
+ end
101
+
102
+ value.gsub(matcher, "#{complete.join}#{incomplete.join}")
45
103
  end
46
104
  end # BarFormatter
47
105
  end # ProgressBar
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../converter'
3
+ require_relative "../converter"
4
+ require_relative "../formatter"
4
5
 
5
6
  module TTY
6
7
  class ProgressBar
@@ -8,32 +9,17 @@ module TTY
8
9
  #
9
10
  # @api private
10
11
  class ByteRateFormatter
11
- MATCHER = /:byte_rate/i
12
-
13
- def initialize(progress)
14
- @progress = progress
15
- end
16
-
17
- # Determines whether this formatter is applied or not.
18
- #
19
- # @param [Object] value
20
- #
21
- # @return [Boolean]
22
- #
23
- # @api private
24
- def matches?(value)
25
- !!(value.to_s =~ MATCHER)
26
- end
12
+ include TTY::ProgressBar::Formatter[/:byte_rate/i.freeze]
27
13
 
28
14
  # Format :byte_rate token
29
15
  #
30
16
  # @param [String] value
31
- # the value being formatted
17
+ # the value to format
32
18
  #
33
19
  # @api public
34
- def format(value)
20
+ def call(value)
35
21
  formatted = Converter.to_bytes(@progress.rate)
36
- value.gsub(MATCHER, formatted)
22
+ value.gsub(matcher, formatted)
37
23
  end
38
24
  end # ByteRateFormatter
39
25
  end # ProgressBar
@@ -6,31 +6,16 @@ module TTY
6
6
  #
7
7
  # @api private
8
8
  class CurrentFormatter
9
- MATCHER = /:current\b/i.freeze
10
-
11
- def initialize(progress)
12
- @progress = progress
13
- end
14
-
15
- # Determines whether this formatter is applied or not.
16
- #
17
- # @param [Object] value
18
- #
19
- # @return [Boolean]
20
- #
21
- # @api private
22
- def matches?(value)
23
- !!(value.to_s =~ MATCHER)
24
- end
9
+ include TTY::ProgressBar::Formatter[/:current\b/i.freeze]
25
10
 
26
11
  # Format :current token
27
12
  #
28
13
  # @param [String] value
29
- # the value being formatted
14
+ # the value to format
30
15
  #
31
16
  # @api public
32
- def format(value)
33
- value.gsub(MATCHER, @progress.current.to_s)
17
+ def call(value)
18
+ value.gsub(matcher, @progress.current.to_s)
34
19
  end
35
20
  end # CurrentFormatter
36
21
  end # ProgressBar
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../converter'
3
+ require_relative "../converter"
4
+ require_relative "../formatter"
4
5
 
5
6
  module TTY
6
7
  class ProgressBar
@@ -8,26 +9,17 @@ module TTY
8
9
  #
9
10
  # @api private
10
11
  class ByteFormatter
11
- MATCHER = /(:current_byte|:byte)\b/i.freeze
12
+ include TTY::ProgressBar::Formatter[/(:current_byte|:byte)\b/i.freeze]
12
13
 
13
- def initialize(progress)
14
- @progress = progress
15
- end
16
-
17
- # Determines whether this formatter is applied or not.
18
- #
19
- # @param [Object] value
14
+ # Format :current_byte token
20
15
  #
21
- # @return [Boolean]
16
+ # @param [String] value
17
+ # the value to format
22
18
  #
23
- # @api private
24
- def matches?(value)
25
- !!(value.to_s =~ MATCHER)
26
- end
27
-
28
- def format(value)
19
+ # @api public
20
+ def call(value)
29
21
  bytes = Converter.to_bytes(@progress.current)
30
- value.gsub(MATCHER, bytes)
22
+ value.gsub(matcher, bytes)
31
23
  end
32
24
  end # ByteFormatter
33
25
  end # ProgressBar
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../converter'
3
+ require_relative "../converter"
4
+ require_relative "../formatter"
4
5
 
5
6
  module TTY
6
7
  class ProgressBar
@@ -8,26 +9,16 @@ module TTY
8
9
  #
9
10
  # @api private
10
11
  class ElapsedFormatter
11
- MATCHER = /:elapsed/.freeze
12
+ include TTY::ProgressBar::Formatter[/:elapsed/.freeze]
12
13
 
13
- def initialize(progress)
14
- @progress = progress
15
- end
16
-
17
- # Determines whether this formatter is applied or not.
18
- #
19
- # @param [Object] value
14
+ # Format :elapsed token
20
15
  #
21
- # @return [Boolean]
16
+ # @param [String] value
17
+ # the value to format
22
18
  #
23
- # @api private
24
- def matches?(value)
25
- !!(value.to_s =~ MATCHER)
26
- end
27
-
28
- def format(value)
29
- elapsed = (Time.now - @progress.start_at)
30
- value.gsub(MATCHER, Converter.to_time(elapsed))
19
+ # @api public
20
+ def call(value)
21
+ value.gsub(matcher, Converter.to_time(@progress.elapsed_time))
31
22
  end
32
23
  end # ElapsedFormatter
33
24
  end # ProgressBar
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../converter'
3
+ require_relative "../converter"
4
+ require_relative "../formatter"
4
5
 
5
6
  module TTY
6
7
  class ProgressBar
@@ -8,29 +9,24 @@ module TTY
8
9
  #
9
10
  # @api private
10
11
  class EstimatedFormatter
11
- MATCHER = /:eta/.freeze
12
+ include TTY::ProgressBar::Formatter[/:eta/.freeze]
12
13
 
13
- def initialize(progress)
14
- @progress = progress
15
- end
16
-
17
- # Determines whether this formatter is applied or not.
14
+ # Format :eta token
18
15
  #
19
- # @param [Object] value
16
+ # @param [String] value
17
+ # the value to format
20
18
  #
21
- # @return [Boolean]
22
- #
23
- # @api private
24
- def matches?(value)
25
- !!(value.to_s =~ MATCHER)
26
- end
19
+ # @api public
20
+ def call(value)
21
+ if @progress.indeterminate?
22
+ return value.gsub(matcher, "--s")
23
+ end
27
24
 
28
- def format(value)
29
- elapsed = Time.now - @progress.start_at
25
+ elapsed = @progress.elapsed_time
30
26
  estimated = (elapsed / @progress.ratio).to_f - elapsed
31
27
  estimated = (estimated.infinite? || estimated < 0) ? 0.0 : estimated
32
- value.gsub(MATCHER, Converter.to_time(estimated))
28
+ value.gsub(matcher, Converter.to_time(estimated))
33
29
  end
34
- end # ElapsedFormatter
30
+ end # EstimatedFormatter
35
31
  end # ProgressBar
36
32
  end # TTY
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ # Used by {Pipeline} to format :eta_time token
6
+ #
7
+ # @api private
8
+ class EstimatedTimeFormatter
9
+ include TTY::ProgressBar::Formatter[/:eta_time/.freeze]
10
+
11
+ # Format :eta_time token
12
+ #
13
+ # @param [String] value
14
+ # the value to format
15
+ #
16
+ # @api public
17
+ def call(value)
18
+ if @progress.indeterminate?
19
+ return value.gsub(matcher, "--:--:--")
20
+ end
21
+
22
+ elapsed = @progress.elapsed_time
23
+ estimated = (elapsed / @progress.ratio).to_f - elapsed
24
+ estimated = (estimated.infinite? || estimated < 0) ? 0.0 : estimated
25
+
26
+ time_format = if estimated >= 86_400 # longer than a day
27
+ "%Y-%m-%d %H:%M:%S"
28
+ else
29
+ "%H:%M:%S"
30
+ end
31
+ completion_time = Time.now + estimated
32
+ eta_time = completion_time.strftime(time_format)
33
+ value.gsub(matcher, eta_time)
34
+ end
35
+ end # EstimatedTimeFormatter
36
+ end # ProgressBar
37
+ end # TTY
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../converter'
3
+ require_relative "../converter"
4
+ require_relative "../formatter"
4
5
 
5
6
  module TTY
6
7
  class ProgressBar
@@ -8,32 +9,17 @@ module TTY
8
9
  #
9
10
  # @api private
10
11
  class MeanByteFormatter
11
- MATCHER = /:mean_byte/i.freeze
12
+ include TTY::ProgressBar::Formatter[/:mean_byte/i.freeze]
12
13
 
13
- def initialize(progress)
14
- @progress = progress
15
- end
16
-
17
- # Determines whether this formatter is applied or not.
18
- #
19
- # @param [Object] value
20
- #
21
- # @return [Boolean]
22
- #
23
- # @api private
24
- def matches?(value)
25
- !!(value.to_s =~ MATCHER)
26
- end
27
-
28
- # Format :rate token
14
+ # Format :mean_byte token
29
15
  #
30
16
  # @param [String] value
31
17
  # the value being formatted
32
18
  #
33
19
  # @api public
34
- def format(value)
20
+ def call(value)
35
21
  formatted = Converter.to_bytes(@progress.mean_rate)
36
- value.gsub(MATCHER, formatted)
22
+ value.gsub(matcher, formatted)
37
23
  end
38
24
  end # MeanByteFormatter
39
25
  end # ProgressBar
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../converter'
3
+ require_relative "../converter"
4
+ require_relative "../formatter"
4
5
 
5
6
  module TTY
6
7
  class ProgressBar
@@ -8,32 +9,17 @@ module TTY
8
9
  #
9
10
  # @api private
10
11
  class MeanRateFormatter
11
- MATCHER = /:mean_rate/i.freeze
12
+ include TTY::ProgressBar::Formatter[/:mean_rate/i.freeze]
12
13
 
13
- def initialize(progress)
14
- @progress = progress
15
- end
16
-
17
- # Determines whether this formatter is applied or not.
18
- #
19
- # @param [Object] value
20
- #
21
- # @return [Boolean]
22
- #
23
- # @api private
24
- def matches?(value)
25
- !!(value.to_s =~ MATCHER)
26
- end
27
-
28
- # Format :rate token
14
+ # Format :mean_rate token
29
15
  #
30
16
  # @param [String] value
31
17
  # the value being formatted
32
18
  #
33
19
  # @api public
34
- def format(value)
20
+ def call(value)
35
21
  formatted = Converter.to_seconds(@progress.mean_rate)
36
- value.gsub(MATCHER, formatted)
22
+ value.gsub(matcher, formatted)
37
23
  end
38
24
  end # MeanRateFormatter
39
25
  end # ProgressBar