Class: Kotoshu::Cli::ProgressReporter

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/cli/progress_reporter.rb

Overview

Renders download progress to an output IO.

Two rendering strategies, picked at construction time:

- TTY: a single-line bar that rewrites itself ('[====>     ] 45% 51MB/114MB')
- Non-TTY: a periodic line every REPORT_INTERVAL_BYTES ('downloaded 51 MB of 114 MB')

Both share #update and #finish so callers don’t care which mode they’re in. Pass a NullReporter (or anything quack-like) to silence.

The reporter knows nothing about HTTP, files, or chunks — callers feed it cumulative byte counts. This keeps it pure and testable.

Defined Under Namespace

Classes: Null

Constant Summary collapse

REPORT_INTERVAL_BYTES =

10 MB between non-TTY line prints

10 * 1024 * 1024

Instance Method Summary collapse

Constructor Details

#initialize(output:, label: "download", tty: nil) ⇒ ProgressReporter

Returns a new instance of ProgressReporter.

Parameters:

  • output (IO)

    Where to render. Usually $stderr.

  • label (String) (defaults to: "download")

    Short prefix shown in TTY mode (e.g. “en model”).

  • tty (Boolean) (defaults to: nil)

    Override the auto-detected TTY check.



22
23
24
25
26
27
28
29
# File 'lib/kotoshu/cli/progress_reporter.rb', line 22

def initialize(output:, label: "download", tty: nil)
  @output = output
  @label = label
  @tty = tty.nil? ? output.tty? : tty
  @total = nil
  @received = 0
  @last_reported_at = 0
end

Instance Method Details

#finishObject



60
61
62
63
64
65
66
# File 'lib/kotoshu/cli/progress_reporter.rb', line 60

def finish
  return unless @tty

  # Clear the bar line and print final newline.
  @output.print "\r#{' ' * 80}\r"
  @output.puts "#{@label}: done (#{format_bytes(@received)})"
end

#maybe_report_periodicObject

Print a line in non-TTY mode if enough bytes have flowed since the last print. Called by update() in non-TTY mode.



51
52
53
54
55
56
57
58
# File 'lib/kotoshu/cli/progress_reporter.rb', line 51

def maybe_report_periodic
  return if @tty
  return if @total.nil?
  return unless @received >= @last_reported_at + REPORT_INTERVAL_BYTES

  @output.puts "  downloaded #{format_bytes(@received)} of #{format_bytes(@total)}"
  @last_reported_at = @received
end

#start(total_bytes) ⇒ Object

Parameters:

  • total_bytes (Integer, nil)

    Total size from Content-Length, or nil if unknown.



32
33
34
35
36
37
38
39
# File 'lib/kotoshu/cli/progress_reporter.rb', line 32

def start(total_bytes)
  @total = total_bytes
  @received = 0
  @last_reported_at = 0
  return unless @tty

  @output.puts "#{@label}: " + indeterminate_bar(0)
end

#update(received_bytes) ⇒ Object

Parameters:

  • received_bytes (Integer)

    Cumulative bytes received so far.



42
43
44
45
46
47
# File 'lib/kotoshu/cli/progress_reporter.rb', line 42

def update(received_bytes)
  @received = received_bytes
  return unless @tty

  render_tty
end