Module: PWN::Plugins::TTYSpinner

Defined in:
lib/pwn/plugins/tty_spinner.rb

Overview

Shared TTY::Spinner lifecycle for REST / AI calls.

TTY::Spinner#stop marks @done and Thread#kills the auto_spin worker but does NOT join it. The worker is typically mid-sleep on its interval, so it stays alive long enough to write another frame (cursor col 1 + glyph) over the HTTP response that the caller is about to print. Creating the spinner with clear:false (the gem default) also reprints the last glyph + newline on stop, so the spinner appears to keep running whenever a response is provided.

#start uses clear:true + hide_cursor. #stop joins the worker (bounded) so the glyph is gone before the response is written.

Constant Summary collapse

JOIN_SECS =
0.5

Class Method Summary collapse

Class Method Details

.authorsObject

Author(s)

0day Inc. support@0dayinc.com



61
62
63
# File 'lib/pwn/plugins/tty_spinner.rb', line 61

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <support@0dayinc.com>\n"
end

.helpObject

Display usage info



67
68
69
70
71
72
# File 'lib/pwn/plugins/tty_spinner.rb', line 67

public_class_method def self.help
  puts "USAGE:
    spin = #{self}.start
    #{self}.stop(spin: spin)
  "
end

.start(opts = {}) ⇒ Object

Supported Method Parameters

spin = PWN::Plugins::TTYSpinner.start( format: 'optional - TTY::Spinner format (defaults to :dots)', output: 'optional - IO to draw on (defaults to $stderr)' )



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/pwn/plugins/tty_spinner.rb', line 29

public_class_method def self.start(opts = {})
  args = {
    format: opts[:format] || :dots,
    clear: true,
    hide_cursor: true
  }
  args[:output] = opts[:output] unless opts[:output].nil?

  spin = TTY::Spinner.new(**args)
  spin.auto_spin
  spin
end

.stop(opts = {}) ⇒ Object

Supported Method Parameters

PWN::Plugins::TTYSpinner.stop( spin: 'optional - TTY::Spinner from #start (no-op if nil)' )



47
48
49
50
51
52
53
54
55
56
57
# File 'lib/pwn/plugins/tty_spinner.rb', line 47

public_class_method def self.stop(opts = {})
  spin = opts.is_a?(Hash) ? opts[:spin] : opts
  return if spin.nil?

  thread = spin.instance_variable_get(:@thread)
  spin.stop unless spin.respond_to?(:done?) && spin.done?
  thread.join(JOIN_SECS) if thread.respond_to?(:join)
  spin
rescue StandardError
  spin
end