tty-progressbar 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +492 -126
  5. data/lib/tty-progressbar.rb +2 -2
  6. data/lib/tty/progressbar.rb +168 -68
  7. data/lib/tty/progressbar/configuration.rb +121 -27
  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 +74 -27
  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 +61 -21
  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 +1 -1
  30. metadata +44 -103
  31. data/Rakefile +0 -8
  32. data/examples/color.rb +0 -18
  33. data/examples/failure.rb +0 -12
  34. data/examples/iterator.rb +0 -5
  35. data/examples/lazy.rb +0 -6
  36. data/examples/multi/main_bar.rb +0 -13
  37. data/examples/multi/simple.rb +0 -13
  38. data/examples/multi/width.rb +0 -13
  39. data/examples/simple.rb +0 -7
  40. data/examples/slow_process.rb +0 -29
  41. data/examples/speed.rb +0 -11
  42. data/examples/threaded.rb +0 -14
  43. data/examples/tokens.rb +0 -12
  44. data/examples/unicode.rb +0 -7
  45. data/spec/spec_helper.rb +0 -53
  46. data/spec/unit/advance_spec.rb +0 -25
  47. data/spec/unit/clear_spec.rb +0 -17
  48. data/spec/unit/complete_spec.rb +0 -16
  49. data/spec/unit/converter/to_bytes_spec.rb +0 -47
  50. data/spec/unit/converter/to_seconds_spec.rb +0 -15
  51. data/spec/unit/converter/to_time_spec.rb +0 -19
  52. data/spec/unit/custom_formatter_spec.rb +0 -26
  53. data/spec/unit/custom_token_spec.rb +0 -14
  54. data/spec/unit/events_spec.rb +0 -33
  55. data/spec/unit/finish_spec.rb +0 -15
  56. data/spec/unit/formatter/bar_spec.rb +0 -33
  57. data/spec/unit/formatter/byte_rate_spec.rb +0 -32
  58. data/spec/unit/formatter/current_byte_spec.rb +0 -16
  59. data/spec/unit/formatter/current_spec.rb +0 -14
  60. data/spec/unit/formatter/elapsed_spec.rb +0 -58
  61. data/spec/unit/formatter/estimated_spec.rb +0 -27
  62. data/spec/unit/formatter/mean_byte_spec.rb +0 -32
  63. data/spec/unit/formatter/mean_rate_spec.rb +0 -31
  64. data/spec/unit/formatter/percent_spec.rb +0 -16
  65. data/spec/unit/formatter/rate_spec.rb +0 -31
  66. data/spec/unit/formatter/total_byte_spec.rb +0 -16
  67. data/spec/unit/formatter/total_spec.rb +0 -16
  68. data/spec/unit/frequency_spec.rb +0 -27
  69. data/spec/unit/head_spec.rb +0 -32
  70. data/spec/unit/hide_cursor_spec.rb +0 -27
  71. data/spec/unit/inspect_spec.rb +0 -11
  72. data/spec/unit/iterate_spec.rb +0 -79
  73. data/spec/unit/log_spec.rb +0 -29
  74. data/spec/unit/meter_spec.rb +0 -70
  75. data/spec/unit/multi/advance_spec.rb +0 -123
  76. data/spec/unit/multi/events_spec.rb +0 -115
  77. data/spec/unit/multi/finish_spec.rb +0 -41
  78. data/spec/unit/multi/line_inset_spec.rb +0 -65
  79. data/spec/unit/multi/register_spec.rb +0 -35
  80. data/spec/unit/multi/reset_spec.rb +0 -28
  81. data/spec/unit/multi/stop_spec.rb +0 -15
  82. data/spec/unit/multi/width_spec.rb +0 -118
  83. data/spec/unit/new_spec.rb +0 -76
  84. data/spec/unit/pipeline_spec.rb +0 -19
  85. data/spec/unit/ratio_spec.rb +0 -31
  86. data/spec/unit/render_spec.rb +0 -25
  87. data/spec/unit/reset_spec.rb +0 -31
  88. data/spec/unit/resize_spec.rb +0 -35
  89. data/spec/unit/set_current_spec.rb +0 -43
  90. data/spec/unit/start_spec.rb +0 -14
  91. data/spec/unit/stop_spec.rb +0 -19
  92. data/spec/unit/update_spec.rb +0 -22
  93. data/spec/unit/width_spec.rb +0 -86
  94. data/tasks/console.rake +0 -9
  95. data/tasks/coverage.rake +0 -9
  96. data/tasks/spec.rake +0 -27
  97. data/tty-progressbar.gemspec +0 -32
@@ -1,62 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "formats"
4
+
1
5
  module TTY
2
6
  class ProgressBar
3
7
  class Configuration
8
+ include TTY::ProgressBar::Formats
4
9
 
10
+ # The total number of steps to completion
11
+ # @api public
5
12
  attr_reader :total
6
13
 
14
+ # The maximum width for the progress bar except all formatting tokens
15
+ # @api public
7
16
  attr_accessor :width
8
- #attr_reader :width
9
-
10
- attr_accessor :no_width
11
17
 
12
- attr_accessor :incomplete
18
+ # The complete character in progress animation
19
+ # @api public
20
+ attr_reader :complete
13
21
 
14
- attr_accessor :complete
22
+ # The incomplete character in progress animation
23
+ # @api public
24
+ attr_reader :incomplete
15
25
 
26
+ # The head character, defaults to complete
27
+ # @api public
16
28
  attr_accessor :head
17
29
 
18
- attr_accessor :hide_cursor
30
+ # The unknown character for indeterminate progress animation
31
+ # @api public
32
+ attr_reader :unknown
19
33
 
20
- attr_accessor :clear
34
+ # The amount of indentation before a progress animation
35
+ # @api private
36
+ attr_accessor :inset
21
37
 
38
+ # The preconfigured bar format name, defaults to :classic
39
+ # @api public
40
+ attr_accessor :bar_format
41
+
42
+ # The object that responds to print call, defaults to stderr
43
+ # @api public
22
44
  attr_accessor :output
23
45
 
46
+ # The frequency with which to display a progress bar per second
47
+ # @api public
24
48
  attr_accessor :frequency
25
49
 
50
+ # The time interval for sampling of speed measurement, defaults to 1 second
51
+ # @api public
26
52
  attr_accessor :interval
27
53
 
28
- attr_accessor :inset
54
+ # Whether or not to hide the cursor, defaults to false
55
+ # @api public
56
+ attr_accessor :hide_cursor
57
+
58
+ # Whether or not to clear the progress line, defaults to false
59
+ # @api public
60
+ attr_accessor :clear
61
+
62
+ # Whether or not to replace head character with complete, defaults to false
63
+ # @api public
64
+ attr_accessor :clear_head
29
65
 
30
66
  def initialize(options)
31
67
  self.total = options[:total] if options[:total]
32
- @width = options.fetch(:width) { total }
33
- @no_width = options.fetch(:no_width) { false }
34
- @incomplete = options.fetch(:incomplete) { ' ' }
35
- @complete = options.fetch(:complete) { '=' }
36
- @head = options.fetch(:head) { @complete || '=' }
37
- @hide_cursor = options.fetch(:hide_cursor) { false }
38
- @clear = options.fetch(:clear) { false }
68
+ @width = options.fetch(:width) { total }
69
+ @bar_format = options.fetch(:bar_format, :classic)
70
+ self.incomplete = options.fetch(:incomplete) { fetch_char(@bar_format, :incomplete) }
71
+ self.complete = options.fetch(:complete) { fetch_char(@bar_format, :complete) }
72
+ self.unknown = options.fetch(:unknown) { fetch_char(@bar_format, :unknown) }
73
+ @head = options.fetch(:head) { @complete || "=" }
74
+ @clear_head = options.fetch(:clear_head, false)
75
+ @hide_cursor = options.fetch(:hide_cursor, false)
76
+ @clear = options.fetch(:clear, false)
39
77
  @output = options.fetch(:output) { $stderr }
40
- @frequency = options.fetch(:frequency) { 0 } # 0Hz
41
- @interval = options.fetch(:interval) { 1 } # 1 sec
42
- @inset = options.fetch(:inset) { 0 }
78
+ @frequency = options.fetch(:frequency, 0) # 0Hz
79
+ @interval = options.fetch(:interval, 1) # 1 sec
80
+ @inset = options.fetch(:inset, 0)
43
81
  end
44
82
 
45
- # def width=(value)
46
- # return if value.nil?
83
+ # Set complete character(s)
84
+ #
85
+ # @param [String] value
86
+ #
87
+ # @api public
88
+ def complete=(value)
89
+ raise_if_empty(:complete, value)
47
90
 
48
- # if value < ProgressBar.max_columns
49
- # @width = value
50
- # else
51
- # @width = ProgressBar.max_columns
52
- # end
53
- # end
91
+ @complete = value
92
+ end
93
+
94
+ # Set incomplete character(s)
95
+ #
96
+ # @param [String] value
97
+ #
98
+ # @api public
99
+ def incomplete=(value)
100
+ raise_if_empty(:incomplete, value)
101
+
102
+ @incomplete = value
103
+ end
104
+
105
+ # Set unknown character(s)
106
+ #
107
+ # @param [String] value
108
+ #
109
+ # @api public
110
+ def unknown=(value)
111
+ raise_if_empty(:unknown, value)
112
+
113
+ @unknown = value
114
+ end
54
115
 
116
+ # Set total and adjust width if unset
117
+ #
118
+ # @param [Integer,nil] value
119
+ #
120
+ # @api public
55
121
  def total=(value)
56
- fail ArgumentError unless value
57
122
  @total = value
58
123
  self.width = value if width.nil?
59
124
  end
125
+
126
+ private
127
+
128
+ # Find bar char by type name and property
129
+ #
130
+ # @param [Symbol] name
131
+ # @param [Symbol] property
132
+ #
133
+ # @api private
134
+ def fetch_char(name, property)
135
+ if FORMATS.key?(name)
136
+ FORMATS[name][property]
137
+ else
138
+ raise ArgumentError, "unsupported bar format: #{name.inspect}. " \
139
+ "Available formats are: " \
140
+ "#{FORMATS.keys.sort.map(&:inspect).join(', ')}"
141
+ end
142
+ end
143
+
144
+ # Check whether a parameter's value is empty or not
145
+ #
146
+ # @raise [ArgumentError]
147
+ #
148
+ # @api private
149
+ def raise_if_empty(name, value)
150
+ return value unless value.to_s.empty?
151
+
152
+ raise ArgumentError, "cannot provide an empty string for #{name.inspect}"
153
+ end
60
154
  end # Configuration
61
155
  end # ProgressBar
62
156
  end # TTY
@@ -15,19 +15,21 @@ module TTY
15
15
  #
16
16
  # @api public
17
17
  def to_time(seconds)
18
+ days = (seconds / (24 * HOURSECONDS).to_f).floor
19
+ seconds -= days * 24 * HOURSECONDS
18
20
  hours = (seconds / HOURSECONDS.to_f).floor
19
21
  seconds -= hours * HOURSECONDS
20
22
  minutes = (seconds / 60).floor
21
23
  seconds -= minutes * 60
22
24
 
23
- if hours > 99
24
- sprintf('%dh', hours)
25
+ if days > 0 # over 24 hours switch to days
26
+ format("%dd%2dh%2dm", days, hours, minutes)
25
27
  elsif hours > 0
26
- sprintf('%2dh%2dm', hours, minutes)
28
+ format("%2dh%2dm", hours, minutes)
27
29
  elsif minutes > 0
28
- sprintf('%2dm%2ds', minutes, seconds)
30
+ format("%2dm%2ds", minutes, seconds)
29
31
  else
30
- sprintf('%2ds', seconds)
32
+ format("%2ds", seconds)
31
33
  end
32
34
  end
33
35
  module_function :to_time
@@ -41,43 +43,38 @@ module TTY
41
43
  # the formatted result
42
44
  #
43
45
  # @api public
44
- def to_seconds(seconds, precision = nil)
46
+ def to_seconds(seconds, precision: nil)
45
47
  precision ||= (seconds < 1 && !seconds.zero?) ? 5 : 2
46
- sprintf "%5.#{precision}f", seconds
48
+ format "%5.#{precision}f", seconds
47
49
  end
48
50
  module_function :to_seconds
49
51
 
50
- BYTE_UNITS = %w(b kb mb gb tb pb eb).freeze
52
+ BYTE_UNITS = %w[b kb mb gb tb pb eb].freeze
51
53
 
52
54
  # Convert value to bytes
53
55
  #
54
56
  # @param [Numeric] value
55
57
  # the value to convert to bytes
56
- # @param [Hash[Symbol]] options
57
- # @option [Integer] :decimals
58
+ # @param [Integer] decimals
58
59
  # the number of decimals parts
59
- # @option [String] :separator
60
+ # @param [String] separator
60
61
  # the separator to use for thousands in a number
61
- # @option [String] :unit_separator
62
+ # @param [String] unit_separator
62
63
  # the separtor to use between number and unit
63
64
  #
64
65
  # @return [String]
65
66
  #
66
67
  # @api public
67
- def to_bytes(value, options = {})
68
- decimals = options.fetch(:decimals) { 2 }
69
- separator = options.fetch(:separator) { '.' }
70
- unit_separator = options.fetch(:unit_separator) { '' }
71
-
68
+ def to_bytes(value, decimals: 2, separator: ".", unit_separator: "")
72
69
  base = 1024
73
70
  pattern = "%.#{decimals}f"
74
71
 
75
- unit = BYTE_UNITS.find.with_index { |_, i| value < base ** (i + 1) }
72
+ unit = BYTE_UNITS.find.with_index { |_, i| value < base**(i + 1) }
76
73
 
77
74
  if value < base
78
75
  formatted_value = value.to_i.to_s
79
76
  else
80
- value_to_size = value / (base ** BYTE_UNITS.index(unit)).to_f
77
+ value_to_size = value / (base**BYTE_UNITS.index(unit)).to_f
81
78
  formatted_value = format(pattern, value_to_size)
82
79
  end
83
80
 
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TTY
4
+ class ProgressBar
5
+ module Formats
6
+ FORMATS = {
7
+ arrow: { # ▸▸▸▸▸▹▹▹▹▹
8
+ complete: "▸",
9
+ incomplete: "▹",
10
+ unknown: "◂▸"
11
+ },
12
+ asterisk: { # ✱✱✱✱✱✳✳✳✳✳
13
+ complete: "✱",
14
+ incomplete: "✳",
15
+ unknown: "✳✱✳"
16
+ },
17
+ blade: { # ▰▰▰▰▰▱▱▱▱▱
18
+ complete: "▰",
19
+ incomplete: "▱",
20
+ unknown: "▱▰▱"
21
+ },
22
+ block: { # █████░░░░░
23
+ complete: "█",
24
+ incomplete: "░",
25
+ unknown: "█"
26
+ },
27
+ box: { # ■■■■■□□□□□
28
+ complete: "■",
29
+ incomplete: "□",
30
+ unknown: "□■□"
31
+ },
32
+ bracket: { # ❭❭❭❭❭❭❭❭❭❭
33
+ complete: "❭",
34
+ incomplete: " ",
35
+ unknown: "❬=❭"
36
+ },
37
+ burger: { # ≡≡≡≡≡≡≡≡≡≡
38
+ complete: "≡",
39
+ incomplete: " ",
40
+ unknown: "<≡>"
41
+ },
42
+ button: { # ⦿⦿⦿⦿⦿⦾⦾⦾⦾⦾
43
+ complete: "⦿",
44
+ incomplete: "⦾",
45
+ unknown: "⦾⦿⦾"
46
+ },
47
+ chevron: { # ››››››››››
48
+ complete: "›",
49
+ incomplete: " ",
50
+ unknown: "‹=›"
51
+ },
52
+ circle: { # ●●●●●○○○○○
53
+ complete: "●",
54
+ incomplete: "○",
55
+ unknown: "○●○"
56
+ },
57
+ classic: { # ==========
58
+ complete: "=",
59
+ incomplete: " ",
60
+ unknown: "<=>"
61
+ },
62
+ crate: { # ▣▣▣▣▣⬚⬚⬚⬚⬚
63
+ complete: "▣",
64
+ incomplete: "⬚",
65
+ unknown: "⬚▣⬚"
66
+ },
67
+ diamond: { # ♦♦♦♦♦♢♢♢♢♢
68
+ complete: "♦",
69
+ incomplete: "♢",
70
+ unknown: "♢♦♢"
71
+ },
72
+ dot: { # ・・・・・・・・・・
73
+ complete: "・",
74
+ incomplete: " ",
75
+ unknown: "・・・"
76
+ },
77
+ heart: { # ♥♥♥♥♥♡♡♡♡♡
78
+ complete: "♥",
79
+ incomplete: "♡",
80
+ unknown: "♡♥♡"
81
+ },
82
+ rectangle: { # ▮▮▮▮▮▯▯▯▯▯
83
+ complete: "▮",
84
+ incomplete: "▯",
85
+ unknown: "▯▮▯"
86
+ },
87
+ square: { # ▪▪▪▪▪▫▫▫▫▫
88
+ complete: "▪",
89
+ incomplete: "▫",
90
+ unknown: "▫▪▫"
91
+ },
92
+ star: { # ★★★★★☆☆☆☆☆
93
+ complete: "★",
94
+ incomplete: "☆",
95
+ unknown: "☆★☆"
96
+ },
97
+ track: { # ▬▬▬▬▬═════
98
+ complete: "▬",
99
+ incomplete: "═",
100
+ unknown: "═▬═"
101
+ },
102
+ tread: { # ❱❱❱❱❱❱❱❱❱❱
103
+ complete: "❱",
104
+ incomplete: " ",
105
+ unknown: "❰=❱"
106
+ },
107
+ triangle: { # ▶▶▶▶▶▷▷▷▷▷
108
+ complete: "▶",
109
+ incomplete: "▷",
110
+ unknown: "◀▶"
111
+ },
112
+ wave: { # ~~~~~_____
113
+ complete: "~",
114
+ incomplete: "_",
115
+ unknown: "<~>"
116
+ }
117
+ }.freeze
118
+ end # Formats
119
+ end # ProgressBar
120
+ end # TTY
@@ -1,48 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'pipeline'
4
-
5
- require_relative 'formatter/bar'
6
- require_relative 'formatter/current'
7
- require_relative 'formatter/current_byte'
8
- require_relative 'formatter/elapsed'
9
- require_relative 'formatter/estimated'
10
- require_relative 'formatter/percent'
11
- require_relative 'formatter/rate'
12
- require_relative 'formatter/byte_rate'
13
- require_relative 'formatter/mean_rate'
14
- require_relative 'formatter/mean_byte'
15
- require_relative 'formatter/total'
16
- require_relative 'formatter/total_byte'
17
-
18
3
  module TTY
19
4
  class ProgressBar
20
- class Formatter
21
- extend Forwardable
22
-
23
- def_delegators :@pipeline, :decorate, :use
24
-
25
- # @api private
26
- def initialize(pipeline = nil)
27
- @pipeline = pipeline || TTY::ProgressBar::Pipeline.new
5
+ class Formatter < ::Module
6
+ # A helper for declaring a matching token pattern
7
+ #
8
+ # @api public
9
+ def self.[](token_match)
10
+ new(token_match)
28
11
  end
29
12
 
30
- # Prepare default pipeline formatters
13
+ # Initialize this module with token matching pattern
31
14
  #
32
- # @api private
33
- def load
34
- @pipeline.use TTY::ProgressBar::CurrentFormatter
35
- @pipeline.use TTY::ProgressBar::TotalFormatter
36
- @pipeline.use TTY::ProgressBar::TotalByteFormatter
37
- @pipeline.use TTY::ProgressBar::ElapsedFormatter
38
- @pipeline.use TTY::ProgressBar::EstimatedFormatter
39
- @pipeline.use TTY::ProgressBar::PercentFormatter
40
- @pipeline.use TTY::ProgressBar::ByteFormatter
41
- @pipeline.use TTY::ProgressBar::ByteRateFormatter
42
- @pipeline.use TTY::ProgressBar::RateFormatter
43
- @pipeline.use TTY::ProgressBar::MeanRateFormatter
44
- @pipeline.use TTY::ProgressBar::MeanByteFormatter
45
- @pipeline.use TTY::ProgressBar::BarFormatter
15
+ # @param [Regexp] token_match
16
+ # the token matching pattern
17
+ #
18
+ # @api public
19
+ def initialize(token_match)
20
+ pattern = token_match
21
+
22
+ module_eval do
23
+ define_method(:initialize) do |progress|
24
+ @progress = progress
25
+ end
26
+
27
+ define_method(:matcher) { pattern }
28
+ define_method(:progress) { @progress }
29
+
30
+ # Determines whether this formatter is applied or not.
31
+ #
32
+ # @param [Object] value
33
+ #
34
+ # @return [Boolean]
35
+ #
36
+ # @api private
37
+ define_method(:matches?) do |value|
38
+ !!(value.to_s =~ pattern)
39
+ end
40
+ end
46
41
  end
47
42
  end # Formatter
48
43
  end # ProgressBar