tty-spinner 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ec461cddc1750681eca2382e8dff48841aa7dd95
4
- data.tar.gz: 0c83312cf2d05f2c359b9b871cf5d2316078d66e
3
+ metadata.gz: 3e159c565080b22ece86e4771413feb3edcd39b3
4
+ data.tar.gz: 890c0f15b5b77de235f25295cbb861745c514b60
5
5
  SHA512:
6
- metadata.gz: e26527de9ece30e50817e6c2f96caa165e93146aaadedf3c5be9327a218ddb1c1be7f00a9f802b944448946ae48876c46f3b3de39b98d75e9d8225f5395db387
7
- data.tar.gz: 0c6530fb8490ef81e9c8ae787adbd0cc342775c4b5e1d09b2755029f21c2b884fc1c6360db3eaf44a0ec83dca7e5bc9e22865673d913729330067914f9128942
6
+ metadata.gz: 88a4bbd2545b596b43ff8ad0ffc9790a125da1a00c2bc4f436e4aa6879536767b3b32ae8de98e928adc785d9e55ff1120ef3c68270db265d691726b522a6606d
7
+ data.tar.gz: 7a138538758b9805c098e397d136dbfafb69bfcd596272078eb5294d3ad5df3a595cd547afe69fc6ba19ab3fd8fc552e9406a99cabfbab3176e098fa36559e59
data/README.md CHANGED
@@ -407,14 +407,14 @@ If options are passed, they will override any options given to the multi spinner
407
407
 
408
408
  ### 5.2 auto_spin
409
409
 
410
- The multispinner has to have been given a message on initialization.
411
- To perform automatic spinning animation use `auto_spin` method like so:
410
+ To create a top level spinner that tracks activity of all the registered spinners, the multispinner has to have been given a message on initialization:
412
411
 
413
412
  ```ruby
414
413
  multi_spinner = TTY::Spinner::Multi.new("[:spinner] Top level spinner")
415
- multi_spinner.auto_spin
416
414
  ```
417
415
 
416
+ The top level multi spinner will perform spinning animation automatically when at least one of the registered spinners starts spinning.
417
+
418
418
  If you register spinners without any tasks then you will have to manually control when the `multi_spinner` finishes by calling `stop`, `success` or `error` (see [manual](#521-manual-async)).
419
419
 
420
420
  Alternatively, you can register spinners with tasks that will automatically animate and finish spinners when respective tasks are done (see [async tasks](#522-auto-async-tasks)).
@@ -441,17 +441,23 @@ spinner_2 = spinners.register "[:spinner] two"
441
441
  Once registered, you can set spinners running in separate threads:
442
442
 
443
443
  ```ruby
444
- multi_spinner.auto_spin
445
444
  spinner_1.auto_spin
446
445
  spinner_2.auto_spin
447
446
  ```
448
447
 
449
- Finnally, you need to stop each spinner manually, in our case we mark the multi spinner as failure as one of its children has been marked as failure:
448
+ Finnally, you need to stop each spinner manually, in our case we mark the second spinner as failure which in turn will stop the top level multi spinner automatically and mark it as failure:
450
449
 
451
450
  ```ruby
452
451
  spinner_1.success
453
452
  spinner_2.error
454
- multi_spinner.error
453
+ ```
454
+
455
+ The result may look like this:
456
+
457
+ ```ruby
458
+ ┌ [✖] top
459
+ ├── [✔] one
460
+ └── [✖] two
455
461
  ```
456
462
 
457
463
  #### 5.2.2 auto async tasks
data/lib/tty/spinner.rb CHANGED
@@ -61,6 +61,8 @@ module TTY
61
61
  # @api public
62
62
  attr_reader :tokens
63
63
 
64
+ attr_reader :interval
65
+
64
66
  # Initialize a spinner
65
67
  #
66
68
  # @example
@@ -100,6 +102,7 @@ module TTY
100
102
  @interval = options.fetch(:interval) do
101
103
  fetch_format(@format.to_sym, :interval)
102
104
  end
105
+ @row = options[:row]
103
106
 
104
107
  @callbacks = Hash.new { |h, k| h[k] = [] }
105
108
  @length = @frames.length
@@ -109,7 +112,6 @@ module TTY
109
112
  @thread = nil
110
113
  @job = nil
111
114
  @multispinner= nil
112
- @row = nil
113
115
  @succeeded = false
114
116
  @first_run = true
115
117
  end
@@ -119,7 +121,7 @@ module TTY
119
121
  # @param [TTY::Spinner::Multi] the multispinner that it is running under
120
122
  #
121
123
  # @api private
122
- def add_multispinner(multispinner)
124
+ def attach_to(multispinner)
123
125
  @multispinner = multispinner
124
126
  end
125
127
 
@@ -332,6 +334,7 @@ module TTY
332
334
  def spin
333
335
  synchronize do
334
336
  return if @done
337
+ emit(:spin)
335
338
 
336
339
  if @hide_cursor && !spinning?
337
340
  write(TTY::Cursor.hide)
@@ -470,7 +473,7 @@ module TTY
470
473
  if @multispinner
471
474
  CURSOR_LOCK.synchronize do
472
475
  if @first_run
473
- @row = @multispinner.next_row
476
+ @row ||= @multispinner.next_row
474
477
  yield if block_given?
475
478
  output.print "\n"
476
479
  @first_run = false
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'monitor'
4
5
  require 'forwardable'
5
6
 
6
7
  require_relative '../spinner'
@@ -12,6 +13,7 @@ module TTY
12
13
  # @api public
13
14
  class Multi
14
15
  include Enumerable
16
+ include MonitorMixin
15
17
 
16
18
  extend Forwardable
17
19
 
@@ -51,20 +53,24 @@ module TTY
51
53
  #
52
54
  # @api public
53
55
  def initialize(*args)
56
+ super()
54
57
  @options = args.last.is_a?(::Hash) ? args.pop : {}
55
58
  message = args.empty? ? nil : args.pop
56
- @inset_opts = @options.delete(:style) { DEFAULT_INSET }
57
- @create_spinner_lock = Mutex.new
59
+ @inset_opts = @options.delete(:style) { DEFAULT_INSET }
60
+ @rows = 0
58
61
  @spinners = []
59
62
  @top_spinner = nil
60
- @top_spinner = register(message) unless message.nil?
63
+ @last_spin_at = nil
64
+ unless message.nil?
65
+ @top_spinner = register(message, observable: false, row: next_row)
66
+ end
61
67
 
62
68
  @callbacks = {
63
69
  success: [],
64
70
  error: [],
65
- done: []
71
+ done: [],
72
+ spin: []
66
73
  }
67
- @rows = 0
68
74
  end
69
75
 
70
76
  # Register a new spinner
@@ -74,12 +80,13 @@ module TTY
74
80
  #
75
81
  # @api public
76
82
  def register(pattern, options = {}, &job)
83
+ observable = options.delete(:observable) { true }
77
84
  spinner = TTY::Spinner.new(pattern, @options.merge(options))
78
85
 
79
- @create_spinner_lock.synchronize do
80
- spinner.add_multispinner(self)
86
+ synchronize do
87
+ spinner.attach_to(self)
81
88
  spinner.job(&job) if block_given?
82
- observe(spinner)
89
+ observe(spinner) if observable
83
90
  @spinners << spinner
84
91
  if @top_spinner
85
92
  @spinners.each { |sp| sp.redraw_indent if sp.spinning? || sp.done? }
@@ -93,7 +100,7 @@ module TTY
93
100
  #
94
101
  # @api public
95
102
  def next_row
96
- @create_spinner_lock.synchronize do
103
+ synchronize do
97
104
  @rows += 1
98
105
  end
99
106
  end
@@ -116,7 +123,6 @@ module TTY
116
123
  def auto_spin
117
124
  raise "No top level spinner" if @top_spinner.nil?
118
125
 
119
- @top_spinner.auto_spin
120
126
  jobs = []
121
127
  @spinners.each do |spinner|
122
128
  if spinner.job?
@@ -133,7 +139,9 @@ module TTY
133
139
  def spin
134
140
  raise "No top level spinner" if @top_spinner.nil?
135
141
 
136
- @top_spinner.spin
142
+ synchronize do
143
+ throttle { @top_spinner.spin }
144
+ end
137
145
  end
138
146
 
139
147
  # Pause all spinners
@@ -179,7 +187,9 @@ module TTY
179
187
  #
180
188
  # @api public
181
189
  def done?
182
- (@spinners - [@top_spinner]).all?(&:done?)
190
+ synchronize do
191
+ (@spinners - [@top_spinner]).all?(&:done?)
192
+ end
183
193
  end
184
194
 
185
195
  # Check if all spinners succeeded
@@ -188,7 +198,9 @@ module TTY
188
198
  #
189
199
  # @api public
190
200
  def success?
191
- (@spinners - [@top_spinner]).all?(&:success?)
201
+ synchronize do
202
+ (@spinners - [@top_spinner]).all?(&:success?)
203
+ end
192
204
  end
193
205
 
194
206
  # Check if any spinner errored
@@ -197,14 +209,15 @@ module TTY
197
209
  #
198
210
  # @api public
199
211
  def error?
200
- (@spinners - [@top_spinner]).any?(&:error?)
212
+ synchronize do
213
+ (@spinners - [@top_spinner]).any?(&:error?)
214
+ end
201
215
  end
202
216
 
203
217
  # Stop all spinners
204
218
  #
205
219
  # @api public
206
220
  def stop
207
- @top_spinner.stop if @top_spinner
208
221
  @spinners.dup.each(&:stop)
209
222
  end
210
223
 
@@ -212,7 +225,6 @@ module TTY
212
225
  #
213
226
  # @api public
214
227
  def success
215
- @top_spinner.success if @top_spinner
216
228
  @spinners.dup.each(&:success)
217
229
  end
218
230
 
@@ -220,7 +232,6 @@ module TTY
220
232
  #
221
233
  # @api public
222
234
  def error
223
- @top_spinner.error if @top_spinner
224
235
  @spinners.dup.each(&:error)
225
236
  end
226
237
 
@@ -230,7 +241,7 @@ module TTY
230
241
  def on(key, &callback)
231
242
  unless @callbacks.key?(key)
232
243
  raise ArgumentError, "The event #{key} does not exist. "\
233
- " Use :success, :error, or :done instead"
244
+ ' Use :spin, :success, :error, or :done instead'
234
245
  end
235
246
  @callbacks[key] << callback
236
247
  self
@@ -238,6 +249,22 @@ module TTY
238
249
 
239
250
  private
240
251
 
252
+ # Check if this spinner should revolve to keep constant speed
253
+ # matching top spinner interval
254
+ #
255
+ # @api private
256
+ def throttle
257
+ sleep_time = 1.0 / @top_spinner.interval
258
+ if @last_spin_at && Time.now - @last_spin_at < sleep_time
259
+ return
260
+ end
261
+ yield if block_given?
262
+ @last_spin_at = Time.now
263
+ end
264
+
265
+ # Fire an event
266
+ #
267
+ # @api private
241
268
  def emit(key, *args)
242
269
  @callbacks[key].each do |block|
243
270
  block.call(*args)
@@ -251,11 +278,22 @@ module TTY
251
278
  #
252
279
  # @api private
253
280
  def observe(spinner)
254
- spinner.on(:success, &success_handler)
281
+ spinner.on(:spin, &spin_handler)
282
+ .on(:success, &success_handler)
255
283
  .on(:error, &error_handler)
256
284
  .on(:done, &done_handler)
257
285
  end
258
286
 
287
+ # Handle spin event
288
+ #
289
+ # @api private
290
+ def spin_handler
291
+ proc do
292
+ spin if @top_spinner
293
+ emit(:spin)
294
+ end
295
+ end
296
+
259
297
  # Handle the success state
260
298
  #
261
299
  # @api private
@@ -286,7 +324,7 @@ module TTY
286
324
  def done_handler
287
325
  proc do
288
326
  if done?
289
- @top_spinner.done if @top_spinner && !error? && !success?
327
+ @top_spinner.stop if @top_spinner && !error? && !success?
290
328
  emit(:done)
291
329
  end
292
330
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module TTY
4
4
  class Spinner
5
- VERSION = "0.6.0"
5
+ VERSION = "0.7.0"
6
6
  end # Spinner
7
7
  end # TTY
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tty-spinner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-07 00:00:00.000000000 Z
11
+ date: 2017-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tty-cursor