tty-progressbar 0.15.1 → 0.18.2

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +495 -125
  5. data/lib/tty-progressbar.rb +2 -2
  6. data/lib/tty/progressbar.rb +169 -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 +18 -20
  17. data/lib/tty/progressbar/formatter/estimated_time.rb +39 -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 +3 -1
  30. metadata +56 -164
  31. data/.codeclimate.yml +0 -11
  32. data/.gitignore +0 -14
  33. data/.rspec +0 -3
  34. data/.travis.yml +0 -26
  35. data/CODE_OF_CONDUCT.md +0 -74
  36. data/Gemfile +0 -14
  37. data/Rakefile +0 -8
  38. data/appveyor.yml +0 -23
  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/multi/width.rb +0 -13
  46. data/examples/simple.rb +0 -7
  47. data/examples/slow_process.rb +0 -29
  48. data/examples/speed.rb +0 -11
  49. data/examples/threaded.rb +0 -14
  50. data/examples/tokens.rb +0 -12
  51. data/examples/unicode.rb +0 -7
  52. data/spec/spec_helper.rb +0 -51
  53. data/spec/unit/advance_spec.rb +0 -25
  54. data/spec/unit/clear_spec.rb +0 -17
  55. data/spec/unit/complete_spec.rb +0 -16
  56. data/spec/unit/converter/to_bytes_spec.rb +0 -47
  57. data/spec/unit/converter/to_seconds_spec.rb +0 -15
  58. data/spec/unit/converter/to_time_spec.rb +0 -19
  59. data/spec/unit/custom_formatter_spec.rb +0 -26
  60. data/spec/unit/custom_token_spec.rb +0 -14
  61. data/spec/unit/events_spec.rb +0 -33
  62. data/spec/unit/finish_spec.rb +0 -15
  63. data/spec/unit/formatter/bar_spec.rb +0 -16
  64. data/spec/unit/formatter/byte_rate_spec.rb +0 -32
  65. data/spec/unit/formatter/current_byte_spec.rb +0 -16
  66. data/spec/unit/formatter/current_spec.rb +0 -14
  67. data/spec/unit/formatter/elapsed_spec.rb +0 -58
  68. data/spec/unit/formatter/estimated_spec.rb +0 -27
  69. data/spec/unit/formatter/mean_byte_spec.rb +0 -32
  70. data/spec/unit/formatter/mean_rate_spec.rb +0 -31
  71. data/spec/unit/formatter/percent_spec.rb +0 -16
  72. data/spec/unit/formatter/rate_spec.rb +0 -31
  73. data/spec/unit/formatter/total_byte_spec.rb +0 -16
  74. data/spec/unit/formatter/total_spec.rb +0 -16
  75. data/spec/unit/frequency_spec.rb +0 -27
  76. data/spec/unit/head_spec.rb +0 -32
  77. data/spec/unit/hide_cursor_spec.rb +0 -27
  78. data/spec/unit/inspect_spec.rb +0 -11
  79. data/spec/unit/iterate_spec.rb +0 -79
  80. data/spec/unit/log_spec.rb +0 -29
  81. data/spec/unit/meter_spec.rb +0 -70
  82. data/spec/unit/multi/advance_spec.rb +0 -123
  83. data/spec/unit/multi/events_spec.rb +0 -115
  84. data/spec/unit/multi/finish_spec.rb +0 -41
  85. data/spec/unit/multi/line_inset_spec.rb +0 -65
  86. data/spec/unit/multi/register_spec.rb +0 -35
  87. data/spec/unit/multi/reset_spec.rb +0 -28
  88. data/spec/unit/multi/stop_spec.rb +0 -15
  89. data/spec/unit/multi/width_spec.rb +0 -118
  90. data/spec/unit/new_spec.rb +0 -76
  91. data/spec/unit/pipeline_spec.rb +0 -19
  92. data/spec/unit/ratio_spec.rb +0 -31
  93. data/spec/unit/render_spec.rb +0 -25
  94. data/spec/unit/reset_spec.rb +0 -31
  95. data/spec/unit/resize_spec.rb +0 -35
  96. data/spec/unit/set_current_spec.rb +0 -43
  97. data/spec/unit/start_spec.rb +0 -14
  98. data/spec/unit/stop_spec.rb +0 -19
  99. data/spec/unit/update_spec.rb +0 -22
  100. data/spec/unit/width_spec.rb +0 -86
  101. data/tasks/console.rake +0 -9
  102. data/tasks/coverage.rake +0 -9
  103. data/tasks/spec.rake +0 -27
  104. data/tty-progressbar.gemspec +0 -30
@@ -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