Class: Audition::Progress

Inherits:
Object
  • Object
show all
Defined in:
lib/audition/progress.rb

Overview

Narrates a scan phase by phase on stderr. This class tracks only where the scan has got to; what the narration looks like—a line rewritten in place, a line per phase, or nothing at all—belongs to the renderer.

Defined Under Namespace

Classes: Line, Log, Renderer

Constant Summary collapse

AUTO_THRESHOLD =

Below this many files a scan ends before a reader could read the first redraw.

200
SILENT =

Handed to analysis entry points as their default, so none of them has to ask whether narration is wanted. Shareable, so a worker can hold it, and the guards below keep it that way.

Ractor.make_shareable(new(renderer: nil))

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(renderer:) ⇒ Progress



314
315
316
317
318
319
# File 'lib/audition/progress.rb', line 314

def initialize(renderer:)
  @renderer = renderer
  @count = 0
  @started = self.class.now
  @phase_started = @started
end

Instance Attribute Details

#count ⇒ Object (readonly)

Returns the value of attribute count.



304
305
306
# File 'lib/audition/progress.rb', line 304

def count
  @count
end

#label ⇒ Object (readonly)

Returns the value of attribute label.



304
305
306
# File 'lib/audition/progress.rb', line 304

def label
  @label
end

#phase_total ⇒ Object (readonly)

What the phase as a whole covers; its stages divide that up.



307
308
309
# File 'lib/audition/progress.rb', line 307

def phase_total
  @phase_total
end

#ractors ⇒ Object

How many Ractors the phase is running on, nil while it is serial.



311
312
313
# File 'lib/audition/progress.rb', line 311

def ractors
  @ractors
end

#renderer ⇒ Object (readonly)

Returns the value of attribute renderer.



304
305
306
# File 'lib/audition/progress.rb', line 304

def renderer
  @renderer
end

#stage_label ⇒ Object (readonly)

Returns the value of attribute stage_label.



304
305
306
# File 'lib/audition/progress.rb', line 304

def stage_label
  @stage_label
end

#total ⇒ Object (readonly)

Returns the value of attribute total.



304
305
306
# File 'lib/audition/progress.rb', line 304

def total
  @total
end

#unit ⇒ Object (readonly)

What the phase as a whole covers; its stages divide that up.



307
308
309
# File 'lib/audition/progress.rb', line 307

def unit
  @unit
end

Class Method Details

.for(units: nil, wanted: nil, format: :text, io: $stderr, style: nil) ⇒ Progress



283
284
285
286
287
# File 'lib/audition/progress.rb', line 283

def for(units: nil, wanted: nil, format: :text, io: $stderr,
  style: nil)
  renderer = renderer_for(units, wanted, format, io, style)
  renderer ? new(renderer: renderer) : SILENT
end

.now ⇒ Object

The one clock in play: the renderers throttle and animate against the scan's own elapsed time rather than keeping time of their own.



269
270
271
# File 'lib/audition/progress.rb', line 269

def now
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

Instance Method Details

#countable? ⇒ Boolean



405
406
407
# File 'lib/audition/progress.rb', line 405

def countable?
  !@total.nil? || @count.positive?
end

#elapsed ⇒ Object

Seconds since the scan began.



389
390
391
# File 'lib/audition/progress.rb', line 389

def elapsed
  self.class.now - @started
end

#enabled? ⇒ Boolean



326
327
328
# File 'lib/audition/progress.rb', line 326

def enabled?
  !@renderer.nil?
end

#finish ⇒ Object

Clears whatever the narration left behind.



384
385
386
# File 'lib/audition/progress.rb', line 384

def finish
  @renderer&.clear
end

#item(label) ⇒ Object

Counts one unit and names it, for phases whose units are few enough to name. The name takes the stage slot, so nothing in the renderers has to make room for it.



375
376
377
378
379
380
381
# File 'lib/audition/progress.rb', line 375

def item(label)
  return unless @renderer

  @stage_label = label
  @count += 1
  @renderer.item(self)
end

#percent ⇒ Integer?



399
400
401
402
403
# File 'lib/audition/progress.rb', line 399

def percent
  return nil unless @total&.positive?

  (100 * @count / @total).clamp(0, 100)
end

#phase(label, total: nil, unit: "files") ⇒ Object

Narrates one named phase for the duration of the block.



335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/audition/progress.rb', line 335

def phase(label, total: nil, unit: "files")
  return yield self unless @renderer

  @label = label
  @phase_total = total
  @unit = unit
  @phase_started = self.class.now
  @ractors = nil
  restart(nil, total)
  yield self
ensure
  @renderer&.phase_done(self)
end

#phase_elapsed ⇒ Object

Seconds since the current phase began.



394
395
396
# File 'lib/audition/progress.rb', line 394

def phase_elapsed
  self.class.now - @phase_started
end

#stage(label, total: nil) ⇒ Object

Renames the work within the current phase and restarts its count. A nil total marks a step whose length is not known until it ends, which the renderer is then free to animate.



361
362
363
# File 'lib/audition/progress.rb', line 361

def stage(label, total: nil)
  restart(label, total) if @renderer
end

#tick(count = 1) ⇒ Object



365
366
367
368
369
370
# File 'lib/audition/progress.rb', line 365

def tick(count = 1)
  return unless @renderer

  @count += count
  @renderer.update(self)
end