- Over 80 built-in spinner patterns
- Create custom spinners patterns
- Customise the spinners format
- Handy built-in completion functions (success, error, warning, info)
- Time your spinner and display its duration
- Apply colors with the use of rainbow
- Use a custom
SpinnerStream
for output
Install via the Swift Package Manger by declaring Spinner as a dependency in your projects Package.swift
:
.package(url: "https://github.com/dominicegginton/Spinner", from: "1.0.0")
import Foundation
import Spinner
let spinner = Spinner(.dots, "foo bar baz")
spinner.start()
sleep(2) // do work
spinner.stop()
Create a spinner by initializing an instance of the Spinner
class.
let spinner = Spinner(.dots, "foo bar baz")
The Spinner()
class ins accepts optional arguments that customise the spinner.
/**
Initialize spinner
- Parameter pattern: spinner pattern
- Parameter message: message to render
- Parameter color: spinner pattern color
- Parameter speed: speed of spinner animation
- Parameter format: spinner format
- Parameter stream: output steam for spinner
- Parameter signal: signal trap implementation for spinner
*/
public init(_ pattern: SpinnerPattern, _ message: String = "", color: Color = .default, speed: Double? = nil, format: String = "{S} {T}", stream: SpinnerStream? = nil, signal: SpinnerSignal? = nil)
Call the Spinner.start()
function to start the spinner animation. This will also call the SpinnerStream.hideCursor()
function to hide the cursor.
let spinner = Spinner(.dots, "foo bar baz")
spinner.start()
Call the Spinner.stop()
function to stop the spinner animation. This will also call the SpinnerStream.showCursor()
function to show the cursor.
let spinner = Spinner(.dots, "foo bar baz")
spinner.stop()
The Spinner.stop()
function accepts optional arguments that customise its behaviour.
/**
Stop the spinner
- Parameter frame: final frame to render before stopping
- Parameter message: final message to render before stopping
- Parameter color: final frame color
- Parameter terminator: the string to print after all items have been printed
*/
public func stop(frame: String? = nil, message: String? = nil, color: Color? = nil, terminator: String = "\n")
The Spinner.clear()
function is a helper function that stops and clears the spinner. Its implementation uses Spinner.stop()
under the hood.
let spinner = Spinner(.dots, "foo bar baz")
spinner.clear()
Helper functions that implement Spinner.stop()
under the hood are provided for common tasks.
/**
Stop and clear the spinner
*/
public func clear()
/**
Stop and render a green tick for the final pattern frame
- Parameter message: spinner message to render
*/
public func success(_ message: String? = nil)
/**
Stop and render a red cross for the final pattern frame
- Parameter message: spinner message to render
*/
public func error(_ message: String? = nil)
/**
Stop and render a yellow warning symbol for the final pattern frame
- Parameter message: spinner message to render
*/
public func warning(_ message: String? = nil)
/**
Stop and render a blue information sign for the final pattern frame
- Parameter message: spinner message to render
*/
public func info(_ message: String? = nil)
Functions are provided to update the spinner while animating.
/**
Update spinner pattern
- Parameter pattern: spinner pattern
*/
public func pattern(_ pattern: SpinnerPattern)
/**
Update spinner message
- Parameter message: message to render
*/
public func message(_ message: String)
/**
Update spinner animation speed
- Parameter speed: speed of spinner animation
*/
public func speed(_ speed: Double)
/**
Update spinner pattern color
- Parameter color: spinner pattern color
*/
public func color(_ color: Color)
/**
Update spinner format
- Parameter format: spinner format
*/
public func format(_ format: String)
To the spinner the Spinner.format
string is taken as a base and occurrences of keys are replaced to generate the rendered spinner.
{S}
renders the animated pattern{T}
renders the message{D}
renders the duration of since starting the spinner
let spinner = Spinner(.dots, "foo bar baz", format : "{T} - {S}") // foo bar baz - ⠧
Use a custom Spinner.format
string that includes {D}
in order to render the duration of time since starting the spinner animation
let spinner = Spinner(.dots, "foo bar baz", format: "{D} {T} - {S}") // 8s ⠧ foo bar baz
The SpinnerPattern()
enum initializer to create a spinner pattern with an array of strings.
let pattern = SpinnerPattern(frames: ["1","2","3","4","5"])
let spinner = Spinner(pattern, "foo bar baz", speed: 0.3) // 1 foo bar baz
Spinner wraps output logic in a SpinnerStream
protocol. This library provides the StdOutSpinnerStream
class that implements to writing to STDOUT.
struct SwiftCLISpinnerStream: SpinnerStream {
private let _stdout: WritableStream
init(stdout: WritableStream) {
_stdout = stdout
}
func write(string: String, terminator: String) {
_stdout.write(string, terminator: terminator)
}
func hideCursor() {
_stdout.write("\u{001B}[?25l", terminator: "")
}
func showCursor() {
_stdout.write("\u{001B}[?25h", terminator: "")
}
}
let spinner = Spinner(.dots, "foo bar baz", stream: SwiftCLISpinnerStream(stdout: stdout))
In order to handle process interrupts (for example, SIGINT through ctrl+c) a signal handler is used to show the user's cursor before exiting. This library provides a SpinnerSignal
protocol and a DefaultSpinnerSignal
structure that handles this functionality by default. If this conflicts with other signals in use, a custom implementation of SpinnerSignal
can be provided. See IBM-Swift/BlueSignals for a clean and safe way of handling signals. The appropriate signal handler for your project could look something like:
struct CustomSpinnerSignal: SpinnerSignal {
func trap() {
Signals.trap(signal: .int) { _ in
// print("\u{001B}[?25h", terminator: "")
// exit(0)
}
}
}
let spinner = Spinner(.dots, "foo bar baz", signal: CustomSpinnerSignal())