Class: TTY::Spinner::Multi

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Enumerable, MonitorMixin
Defined in:
lib/tty/spinner/multi.rb

Overview

Used for managing multiple terminal spinners

Constant Summary collapse

DEFAULT_INSET =
{
  top:    Gem.win_platform? ? '+ '   : "\u250c ",
  middle: Gem.win_platform? ? '|-- ' : "\u251c\u2500\u2500 ",
  bottom: Gem.win_platform? ? '|__ ' : "\u2514\u2500\u2500 "
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Multi

Initialize a multispinner

Examples:

spinner = TTY::Spinner::Multi.new

Parameters:

  • message (String)

    the optional message to print in front of the top level spinner

  • options (Hash)


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/tty/spinner/multi.rb', line 54

def initialize(*args)
  super()
  @options = args.last.is_a?(::Hash) ? args.pop : {}
  message = args.empty? ? nil : args.pop
  @inset_opts  = @options.delete(:style) { DEFAULT_INSET }
  @rows        = 0
  @spinners    = []
  @spinners_count = 0
  @top_spinner = nil
  @last_spin_at = nil
  unless message.nil?
    @top_spinner = register(message, observable: false, row: next_row)
  end

  @callbacks = {
    success: [],
    error:   [],
    done:    [],
    spin:    []
  }
end

Instance Attribute Details

#rowsObject (readonly)

The current count of all rendered rows



30
31
32
# File 'lib/tty/spinner/multi.rb', line 30

def rows
  @rows
end

Instance Method Details

#auto_spinObject

Auto spin the top level spinner & all child spinners that have scheduled jobs



143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/tty/spinner/multi.rb', line 143

def auto_spin
  raise "No top level spinner" if @top_spinner.nil?

  jobs = []
  @spinners.each do |spinner|
    if spinner.job?
      spinner.auto_spin
      jobs << Thread.new { spinner.execute_job }
    end
  end
  jobs.each(&:join)
end

#create_spinner(pattern_or_spinner, options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Create a spinner instance



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/tty/spinner/multi.rb', line 104

def create_spinner(pattern_or_spinner, options)
  case pattern_or_spinner
  when ::String
    TTY::Spinner.new(
      pattern_or_spinner,
      @options.merge(options)
    )
  when ::TTY::Spinner
    pattern_or_spinner
  else
    raise ArgumentError, "Expected a pattern or spinner, " \
      "got: #{pattern_or_spinner.class}"
  end
end

#done?Boolean

Check if all spinners are done

Returns:

  • (Boolean)


208
209
210
211
212
# File 'lib/tty/spinner/multi.rb', line 208

def done?
  synchronize do
    (@spinners - [@top_spinner]).all?(&:done?)
  end
end

#errorObject

Stop all spinners with error status



253
254
255
# File 'lib/tty/spinner/multi.rb', line 253

def error
  @spinners.dup.each(&:error)
end

#error?Boolean

Check if any spinner errored

Returns:

  • (Boolean)


230
231
232
233
234
# File 'lib/tty/spinner/multi.rb', line 230

def error?
  synchronize do
    (@spinners - [@top_spinner]).any?(&:error?)
  end
end

#line_inset(line_no) ⇒ String

Find the number of characters to move into the line before printing the spinner

Parameters:

  • line_no (Integer)

    the current spinner line number for which line inset is calculated

Returns:

  • (String)

    the inset



191
192
193
194
195
196
197
198
199
200
201
# File 'lib/tty/spinner/multi.rb', line 191

def line_inset(line_no)
  return '' if @top_spinner.nil?

  if line_no == 1
    @inset_opts[:top]
  elsif line_no == @spinners_count
    @inset_opts[:bottom]
  else
    @inset_opts[:middle]
  end
end

#next_rowObject

Increase a row count



122
123
124
125
126
# File 'lib/tty/spinner/multi.rb', line 122

def next_row
  synchronize do
    @rows += 1
  end
end

#on(key, &callback) ⇒ Object

Listen on event



260
261
262
263
264
265
266
267
# File 'lib/tty/spinner/multi.rb', line 260

def on(key, &callback)
  unless @callbacks.key?(key)
    raise ArgumentError, "The event #{key} does not exist. "\
                         ' Use :spin, :success, :error, or :done instead'
  end
  @callbacks[key] << callback
  self
end

#pauseObject

Pause all spinners



170
171
172
# File 'lib/tty/spinner/multi.rb', line 170

def pause
  @spinners.dup.each(&:pause)
end

#register(pattern_or_spinner, **options, &job) ⇒ Object

Register a new spinner

Parameters:

  • pattern_or_spinner (String, TTY::Spinner)

    the pattern used for creating spinner, or a spinner instance



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/tty/spinner/multi.rb', line 82

def register(pattern_or_spinner, **options, &job)
  observable = options.delete(:observable) { true }
  spinner = nil

  synchronize do
    spinner = create_spinner(pattern_or_spinner, options)
    spinner.attach_to(self)
    spinner.job(&job) if block_given?
    observe(spinner) if observable
    @spinners << spinner
    @spinners_count += 1
    if @top_spinner
      @spinners.each { |sp| sp.redraw_indent if sp.spinning? || sp.done? }
    end
  end

  spinner
end

#resumeObject

Resume all spinners



177
178
179
# File 'lib/tty/spinner/multi.rb', line 177

def resume
  @spinners.dup.each(&:resume)
end

#spinObject

Perform a single spin animation



159
160
161
162
163
164
165
# File 'lib/tty/spinner/multi.rb', line 159

def spin
  raise "No top level spinner" if @top_spinner.nil?

  synchronize do
    throttle { @top_spinner.spin }
  end
end

#stopObject

Stop all spinners



239
240
241
# File 'lib/tty/spinner/multi.rb', line 239

def stop
  @spinners.dup.each(&:stop)
end

#successObject

Stop all spinners with success status



246
247
248
# File 'lib/tty/spinner/multi.rb', line 246

def success
  @spinners.dup.each(&:success)
end

#success?Boolean

Check if all spinners succeeded

Returns:

  • (Boolean)


219
220
221
222
223
# File 'lib/tty/spinner/multi.rb', line 219

def success?
  synchronize do
    (@spinners - [@top_spinner]).all?(&:success?)
  end
end

#top_spinnerTTY::Spinner

Get the top level spinner if it exists

Returns:



133
134
135
136
137
# File 'lib/tty/spinner/multi.rb', line 133

def top_spinner
  raise "No top level spinner" if @top_spinner.nil?

  @top_spinner
end