Class: TTY::Spinner
- Inherits:
-
Object
- Object
- TTY::Spinner
- Includes:
- MonitorMixin, Formats
- Defined in:
- lib/tty/spinner.rb,
lib/tty/spinner/multi.rb,
lib/tty/spinner/version.rb
Overview
Used for creating terminal spinner
Defined Under Namespace
Classes: Multi
Constant Summary collapse
- NotSpinningError =
Class.new(StandardError)
- ECMA_CSI =
"\x1b["
- MATCHER =
/:spinner/
- TICK =
'✔'
- CROSS =
'✖'
- CURSOR_LOCK =
Monitor.new
- VERSION =
"0.9.3"
Constants included from Formats
Instance Attribute Summary collapse
-
#format ⇒ String
readonly
The current format type.
-
#hide_cursor ⇒ Boolean
readonly
Whether to show or hide cursor.
-
#interval ⇒ Object
readonly
The amount of time between frames in auto spinning.
-
#message ⇒ String
readonly
The message to print before the spinner.
-
#output ⇒ Object
readonly
The object that responds to print call defaulting to stderr.
-
#row ⇒ Object
readonly
The current row inside the multi spinner.
-
#tokens ⇒ Hash[Symbol, Object]
readonly
Tokens for the message.
Instance Method Summary collapse
-
#attach_to(multispinner) ⇒ Object
private
Notifies the TTY::Spinner that it is running under a multispinner.
-
#auto_spin ⇒ Object
Start automatic spinning animation.
-
#clear_line ⇒ Object
Clear current line.
-
#done? ⇒ Boolean
Whether the spinner has completed spinning.
-
#duration ⇒ Numeric
Duration of the spinning animation.
-
#error(stop_message = '') ⇒ Object
Finish spinning and set state to :error.
-
#error? ⇒ Boolean
Whether the spinner is in the error state.
-
#execute_job {|TTY::Spinner| ... } ⇒ Object
Execute this spinner job.
-
#initialize(*args) ⇒ Spinner
constructor
Initialize a spinner.
-
#job(&work) ⇒ Object
Add job to this spinner.
-
#job? ⇒ Boolean
Check if this spinner has a scheduled job.
-
#join(timeout = nil) ⇒ Object
Join running spinner.
-
#kill ⇒ Object
Kill running spinner.
-
#next_char ⇒ String
private
Retrieve next character.
-
#on(name, &block) ⇒ self
Register callback.
-
#pause ⇒ Object
Pause spinner automatic animation.
-
#paused? ⇒ Boolean
Checked if current spinner is paused.
-
#redraw_indent ⇒ Object
private
Redraw the indent for this spinner, if it exists.
-
#reset ⇒ Object
Reset the spinner to initial frame.
-
#resume ⇒ Object
Resume spinner automatic animation.
-
#run(stop_message = '') { ... } ⇒ Object
Run spinner while executing job.
-
#spin ⇒ String
Perform a spin.
-
#spinning? ⇒ Boolean
Whether the spinner is spinning.
-
#start ⇒ Object
Start timer and unlock spinner.
-
#stop(stop_message = '') ⇒ Object
Finish spining.
-
#success(stop_message = '') ⇒ Object
Finish spinning and set state to :success.
-
#success? ⇒ Boolean
Whether the spinner is in the success state.
-
#update(tokens) ⇒ Object
Update string formatting tokens.
Constructor Details
#initialize(*args) ⇒ Spinner
Initialize a spinner
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/tty/spinner.rb', line 94 def initialize(*args) super() = args.last.is_a?(::Hash) ? args.pop : {} @message = args.empty? ? ':spinner' : args.pop @tokens = {} @format = .fetch(:format) { :classic } @output = .fetch(:output) { $stderr } @hide_cursor = .fetch(:hide_cursor) { false } @frames = .fetch(:frames) do fetch_format(@format.to_sym, :frames) end @clear = .fetch(:clear) { false } @success_mark= .fetch(:success_mark) { TICK } @error_mark = .fetch(:error_mark) { CROSS } @interval = .fetch(:interval) do fetch_format(@format.to_sym, :interval) end @row = [:row] @callbacks = Hash.new { |h, k| h[k] = [] } @length = @frames.length @thread = nil @job = nil @multispinner= nil reset end |
Instance Attribute Details
#format ⇒ String (readonly)
The current format type
38 39 40 |
# File 'lib/tty/spinner.rb', line 38 def format @format end |
#hide_cursor ⇒ Boolean (readonly)
Whether to show or hide cursor
45 46 47 |
# File 'lib/tty/spinner.rb', line 45 def hide_cursor @hide_cursor end |
#interval ⇒ Object (readonly)
The amount of time between frames in auto spinning
66 67 68 |
# File 'lib/tty/spinner.rb', line 66 def interval @interval end |
#message ⇒ String (readonly)
The message to print before the spinner
53 54 55 |
# File 'lib/tty/spinner.rb', line 53 def @message end |
#output ⇒ Object (readonly)
The object that responds to print call defaulting to stderr
31 32 33 |
# File 'lib/tty/spinner.rb', line 31 def output @output end |
#row ⇒ Object (readonly)
The current row inside the multi spinner
71 72 73 |
# File 'lib/tty/spinner.rb', line 71 def row @row end |
#tokens ⇒ Hash[Symbol, Object] (readonly)
Tokens for the message
61 62 63 |
# File 'lib/tty/spinner.rb', line 61 def tokens @tokens end |
Instance Method Details
#attach_to(multispinner) ⇒ 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.
Notifies the TTY::Spinner that it is running under a multispinner
140 141 142 |
# File 'lib/tty/spinner.rb', line 140 def attach_to(multispinner) @multispinner = multispinner end |
#auto_spin ⇒ Object
Start automatic spinning animation
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/tty/spinner.rb', line 240 def auto_spin CURSOR_LOCK.synchronize do start sleep_time = 1.0 / @interval spin @thread = Thread.new do sleep(sleep_time) while @started_at if Thread.current['pause'] Thread.stop Thread.current['pause'] = false end spin sleep(sleep_time) end end end ensure if @hide_cursor write(TTY::Cursor.show, false) end end |
#clear_line ⇒ Object
Clear current line
460 461 462 |
# File 'lib/tty/spinner.rb', line 460 def clear_line write(ECMA_CSI + '0m' + TTY::Cursor.clear_line) end |
#done? ⇒ Boolean
Whether the spinner has completed spinning
149 150 151 |
# File 'lib/tty/spinner.rb', line 149 def done? @done end |
#duration ⇒ Numeric
Duration of the spinning animation
319 320 321 |
# File 'lib/tty/spinner.rb', line 319 def duration @started_at ? Time.now - @started_at : nil end |
#error(stop_message = '') ⇒ Object
Finish spinning and set state to :error
447 448 449 450 451 452 453 454 455 |
# File 'lib/tty/spinner.rb', line 447 def error( = '') return if done? synchronize do @succeeded = :error stop() emit(:error) end end |
#error? ⇒ Boolean
Whether the spinner is in the error state. This is only true temporarily while it is being marked with a failure mark.
178 179 180 |
# File 'lib/tty/spinner.rb', line 178 def error? @succeeded == :error end |
#execute_job {|TTY::Spinner| ... } ⇒ Object
Execute this spinner job
224 225 226 |
# File 'lib/tty/spinner.rb', line 224 def execute_job job.(self) if job? end |
#job(&work) ⇒ Object
Add job to this spinner
209 210 211 212 213 214 215 216 217 |
# File 'lib/tty/spinner.rb', line 209 def job(&work) synchronize do if block_given? @job = work else @job end end end |
#job? ⇒ Boolean
Check if this spinner has a scheduled job
233 234 235 |
# File 'lib/tty/spinner.rb', line 233 def job? !@job.nil? end |
#join(timeout = nil) ⇒ Object
Join running spinner
329 330 331 332 333 334 335 |
# File 'lib/tty/spinner.rb', line 329 def join(timeout = nil) unless @thread raise(NotSpinningError, 'Cannot join spinner that is not running') end timeout ? @thread.join(timeout) : @thread.join end |
#kill ⇒ Object
Kill running spinner
340 341 342 343 344 |
# File 'lib/tty/spinner.rb', line 340 def kill synchronize do @thread.kill if @thread end end |
#next_char ⇒ String
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.
Retrieve next character
421 422 423 424 425 426 427 428 429 |
# File 'lib/tty/spinner.rb', line 421 def next_char if success? @success_mark elsif error? @error_mark else @frames[@current - 1] end end |
#on(name, &block) ⇒ self
Register callback
190 191 192 193 194 195 |
# File 'lib/tty/spinner.rb', line 190 def on(name, &block) synchronize do @callbacks[name] << block end self end |
#pause ⇒ Object
Pause spinner automatic animation
276 277 278 279 280 281 282 |
# File 'lib/tty/spinner.rb', line 276 def pause return if paused? synchronize do @thread['pause'] = true if @thread end end |
#paused? ⇒ Boolean
Checked if current spinner is paused
269 270 271 |
# File 'lib/tty/spinner.rb', line 269 def paused? !!(@thread && @thread['pause']) end |
#redraw_indent ⇒ 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.
Redraw the indent for this spinner, if it exists
373 374 375 376 377 378 379 |
# File 'lib/tty/spinner.rb', line 373 def redraw_indent if @hide_cursor && !spinning? write(TTY::Cursor.hide) end write("", false) end |
#reset ⇒ Object
Reset the spinner to initial frame
125 126 127 128 129 130 131 132 133 |
# File 'lib/tty/spinner.rb', line 125 def reset synchronize do @current = 0 @done = false @state = :stopped @succeeded = false @first_run = true end end |
#resume ⇒ Object
Resume spinner automatic animation
287 288 289 290 291 |
# File 'lib/tty/spinner.rb', line 287 def resume return unless paused? @thread.wakeup if @thread end |
#run(stop_message = '') { ... } ⇒ Object
Run spinner while executing job
304 305 306 307 308 309 310 311 312 |
# File 'lib/tty/spinner.rb', line 304 def run( = '', &block) job(&block) auto_spin @work = Thread.new { execute_job } @work.join ensure stop() end |
#spin ⇒ String
Perform a spin
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/tty/spinner.rb', line 352 def spin synchronize do return if @done emit(:spin) if @hide_cursor && !spinning? write(TTY::Cursor.hide) end data = .gsub(MATCHER, @frames[@current]) data = replace_tokens(data) write(data, true) @current = (@current + 1) % @length @state = :spinning data end end |
#spinning? ⇒ Boolean
Whether the spinner is spinning
158 159 160 |
# File 'lib/tty/spinner.rb', line 158 def spinning? @state == :spinning end |
#start ⇒ Object
Start timer and unlock spinner
200 201 202 203 204 |
# File 'lib/tty/spinner.rb', line 200 def start @started_at = Time.now @done = false reset end |
#stop(stop_message = '') ⇒ Object
Finish spining
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/tty/spinner.rb', line 387 def stop( = '') mon_enter return if done? clear_line return if @clear data = .gsub(MATCHER, next_char) data = replace_tokens(data) if !.empty? data << ' ' + end write(data, false) write("\n", false) unless @clear || @multispinner ensure @state = :stopped @done = true @started_at = nil if @hide_cursor write(TTY::Cursor.show, false) end emit(:done) kill mon_exit end |
#success(stop_message = '') ⇒ Object
Finish spinning and set state to :success
434 435 436 437 438 439 440 441 442 |
# File 'lib/tty/spinner.rb', line 434 def success( = '') return if done? synchronize do @succeeded = :success stop() emit(:success) end end |
#success? ⇒ Boolean
Whether the spinner is in the success state. When true the spinner is marked with a success mark.
168 169 170 |
# File 'lib/tty/spinner.rb', line 168 def success? @succeeded == :success end |
#update(tokens) ⇒ Object
Update string formatting tokens
470 471 472 473 474 475 |
# File 'lib/tty/spinner.rb', line 470 def update(tokens) synchronize do clear_line if spinning? @tokens.merge!(tokens) end end |