Raxol.CLI.Spinner (Raxol v2.6.0)

View Source

Animated progress spinners for CLI operations.

Provides visual feedback during long-running operations like compilation, dialyzer analysis, and test runs. Based on TJ Holowaychuk's feedback about the importance of progress indicators.

Usage

# Simple spinner with message
Spinner.with_spinner("Compiling...", fn ->
  # long running operation
  Mix.Task.run("compile")
end)

# Custom spinner style
Spinner.with_spinner("Analyzing...", style: :dots, fn ->
  # operation
end)

# Manual control
{:ok, spinner} = Spinner.start("Processing...")
# do work
Spinner.succeed(spinner, "Done!")

# Or on failure
Spinner.fail(spinner, "Failed!")

Summary

Functions

Completes a progress bar with a newline.

Stops the spinner and shows a failure message.

Displays a progress bar.

Starts a spinner with the given message.

Displays a step indicator for multi-step operations.

Stops the spinner without showing any status.

Stops the spinner and shows a success message.

Updates the spinner message while it's running.

Stops the spinner and shows a warning message.

Runs a function with an animated spinner.

Writes a progress bar to the terminal, overwriting the current line.

Types

spinner_state()

@type spinner_state() :: %{pid: pid(), message: String.t(), style: spinner_style()}

spinner_style()

@type spinner_style() :: :dots | :line | :arc | :bounce | :braille

Functions

complete_progress()

@spec complete_progress() :: :ok

Completes a progress bar with a newline.

fail(spinner, message \\ "Failed")

@spec fail(spinner_state(), String.t()) :: :ok

Stops the spinner and shows a failure message.

progress_bar(current, total, opts \\ [])

@spec progress_bar(number(), number(), keyword()) :: String.t()

Displays a progress bar.

Options

  • :width - Bar width in characters (default: 30)
  • :filled - Character for filled portion (default: "=")
  • :empty - Character for empty portion (default: " ")
  • :prefix - Text before the bar (default: "")
  • :suffix - Text after the bar (default: "")

start(message, opts \\ [])

@spec start(
  String.t(),
  keyword()
) :: {:ok, spinner_state()}

Starts a spinner with the given message.

Returns {:ok, spinner_state} which can be used with succeed/2, fail/2, or stop/1.

step(current, total, message, opts \\ [])

@spec step(pos_integer(), pos_integer(), String.t(), keyword()) :: :ok

Displays a step indicator for multi-step operations.

Examples

Spinner.step(1, 5, "Compiling...")
# [1/5] Compiling...

Spinner.step(2, 5, "Running tests...", status: :in_progress)
# [2/5] Running tests...

stop(spinner)

@spec stop(spinner_state()) :: :ok

Stops the spinner without showing any status.

succeed(spinner, message \\ "Done")

@spec succeed(spinner_state(), String.t()) :: :ok

Stops the spinner and shows a success message.

update_message(spinner, new_message)

@spec update_message(spinner_state(), String.t()) :: :ok

Updates the spinner message while it's running.

warn(spinner, message \\ "Warning")

@spec warn(spinner_state(), String.t()) :: :ok

Stops the spinner and shows a warning message.

with_spinner(message, opts \\ [], fun)

@spec with_spinner(String.t(), keyword(), (-> any())) :: any()

Runs a function with an animated spinner.

Returns the result of the function.

Options

  • :style - Spinner animation style (default: :dots)
  • :success - Message to show on success (default: "Done")
  • :failure - Message to show on failure (default: "Failed")

Examples

result = Spinner.with_spinner("Compiling...", fn ->
  Mix.Task.run("compile")
end)

result = Spinner.with_spinner("Running tests...", style: :line, fn ->
  Mix.Task.run("test")
end)

write_progress(current, total, opts \\ [])

@spec write_progress(number(), number(), keyword()) :: :ok

Writes a progress bar to the terminal, overwriting the current line.