# `Owl.ProgressBar`
[🔗](https://github.com/fuelen/owl/blob/v0.13.1/lib/owl/progress_bar.ex#L1)

A live progress bar widget.

## Single bar

    Owl.ProgressBar.start(id: :users, label: "Creating users", total: 1000)

    Enum.each(1..1000, fn _ ->
      Process.sleep(10)
      Owl.ProgressBar.inc(id: :users)
    end)

    Owl.LiveScreen.await_render()

## Multiple bars

    1..10
    |> Enum.map(fn index ->
      Task.async(fn ->
        range = 1..Enum.random(100..500)

        label = "Demo Progress ##{index}"

        Owl.ProgressBar.start(
          id: {:demo, index},
          label: label,
          total: range.last,
          timer: true,
          bar_width_ratio: 0.3,
          filled_symbol: "#",
          partial_symbols: []
        )

        Enum.each(range, fn _ ->
          Process.sleep(Enum.random(10..50))
          Owl.ProgressBar.inc(id: {:demo, index})
        end)
      end)
    end)
    |> Task.await_many(:infinity)

    Owl.LiveScreen.await_render()

# `id`

```elixir
@type id() :: any()
```

# `inc`

```elixir
@spec inc(id: id(), step: integer()) :: :ok
```

Increases the `current` value by `step`.

When `current` becomes equal to `total`, the progress bar terminates.

## Options

* `:id` - a required identifier for the progress bar.
* `:step` - the amount by which `current` should be increased. Defaults to 1.

## Examples

    Owl.ProgressBar.inc(id: "Creating users")

    Owl.ProgressBar.inc(id: "Creating users", step: 10)

# `render`

```elixir
@spec render(%{
  optional(:current_time) =&gt; nil | integer(),
  optional(:start_time) =&gt; nil | integer(),
  optional(:screen_width) =&gt; nil | pos_integer(),
  optional(:absolute_values) =&gt; nil | boolean(),
  bar_width_ratio: float(),
  label: Owl.Data.t(),
  total: pos_integer(),
  current: non_neg_integer(),
  start_symbol: Owl.Data.t(),
  end_symbol: Owl.Data.t(),
  filled_symbol: Owl.Data.t(),
  partial_symbols: [Owl.Data.t()],
  empty_symbol: Owl.Data.t()
}) :: Owl.Data.t()
```

Renders a progress bar that can be consumed by `Owl.IO.puts/2`.

Used as a callback for blocks in `Owl.LiveScreen`.

## Examples

    iex> Owl.ProgressBar.render(%{
    ...>   label: "Demo",
    ...>   total: 200,
    ...>   current: 60,
    ...>   bar_width_ratio: 0.7,
    ...>   start_symbol: "[",
    ...>   end_symbol: "]",
    ...>   filled_symbol: "#",
    ...>   partial_symbols: [],
    ...>   empty_symbol: ".",
    ...>   screen_width: 40
    ...> }) |> to_string()
    "Demo      [######.................]  30%"

    iex> Owl.ProgressBar.render(%{
    ...>   label: "Demo",
    ...>   total: 200,
    ...>   current: 8,
    ...>   bar_width_ratio: 0.2,
    ...>   start_symbol: "|",
    ...>   absolute_values: true,
    ...>   end_symbol: "|",
    ...>   filled_symbol: "█",
    ...>   partial_symbols: ["▏", "▎", "▍", "▌", "▋", "▊", "▉"],
    ...>   empty_symbol: " ",
    ...>   screen_width: 40,
    ...>   start_time: -576460748012758993,
    ...>   current_time: -576460748012729828
    ...> }) |> to_string()
    "Demo         8/200 00:29.2 |▎     |   4%"

    iex> Owl.ProgressBar.render(%{
    ...>   label: "Demo",
    ...>   total: 200,
    ...>   current: 8,
    ...>   bar_width_ratio: 0.7,
    ...>   start_symbol: "[",
    ...>   end_symbol: "]",
    ...>   filled_symbol: Owl.Data.tag("≡", :cyan),
    ...>   partial_symbols: [Owl.Data.tag("-", :green), Owl.Data.tag("=", :blue)],
    ...>   empty_symbol: " ",
    ...>   screen_width: 40
    ...> })|> Owl.Data.to_chardata() |> to_string()
    "Demo      [[34m=[39m                      ]   4%[0m"

    iex> Owl.ProgressBar.render(%{
    ...>   label: "Demo",
    ...>   total: 200,
    ...>   current: 60,
    ...>   bar_width_ratio: 0.95,
    ...>   start_symbol: "[",
    ...>   end_symbol: "]",
    ...>   filled_symbol: "#",
    ...>   partial_symbols: [],
    ...>   empty_symbol: ".",
    ...>   screen_width: 40
    ...> }) |> to_string()
    "D…[#########......................]  30%"

    iex> Owl.ProgressBar.render(%{
    ...>   label: "Demo",
    ...>   total: 200,
    ...>   current: 60,
    ...>   bar_width_ratio: 1,
    ...>   start_symbol: "[",
    ...>   end_symbol: "]",
    ...>   filled_symbol: "#",
    ...>   partial_symbols: [],
    ...>   empty_symbol: ".",
    ...>   screen_width: 40
    ...> }) |> to_string()
    "[#########........................]  30%"

# `start`

```elixir
@spec start(
  label: Owl.Data.t(),
  id: id(),
  total: pos_integer(),
  timer: boolean(),
  absolute_values: boolean(),
  current: non_neg_integer(),
  bar_width_ratio: nil | float(),
  start_symbol: Owl.Data.t(),
  end_symbol: Owl.Data.t(),
  filled_symbol: Owl.Data.t(),
  partial_symbols: [Owl.Data.t()],
  empty_symbol: Owl.Data.t(),
  screen_width: pos_integer(),
  live_screen_server: GenServer.server()
) :: DynamicSupervisor.on_start_child()
```

Starts a progress bar on `Owl.LiveScreen`.

## Options

* `:id` - an id of the progress bar. Required.
* `:label` - a label for the progress bar. Required.
* `:total` - the total value. Required.
* `:current` - the current value. Defaults to `0`.
* `:bar_width_ratio` - the width ratio for the bar. Defaults to 0.7.
* `:timer` - set to `true` to launch a timer and display it before the bar in the format `MM:SS`. Defaults to `false`.
* `:absolute_values` - set to `true` to show absolute values before the bar in the format `current/total`. Defaults to `false`.
* `:start_symbol` - a symbol that is rendered at the beginning of the progress bar. Defaults to `"["`.
* `:end_symbol` - a symbol that is rendered at the end of the progress bar. Defaults to `"]"`.
* `:filled_symbol` - a symbol that is used when the `current` value is large enough to fill the cell. Defaults to `"≡"`.
* `:partial_symbols` - a list of symbols used when the `current` value is too small to render `filled_symbol`. Defaults to `["-", "="]`.
* `:empty_symbol` - an empty symbol. Defaults to `" "`.
* `:screen_width` - the width of the output data. Defaults to the terminal width or 80 characters if a terminal is not available.
* `:live_screen_server` - a reference to the `Owl.LiveScreen` server. Defaults to `Owl.LiveScreen`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
