# Styling
`ProgressStyle` combines a parsed template, progress characters, spinner frames, optional
line color, and custom keys.
## Template Variables
| `{bar}` | `:40`, `:40.#/-` | Progress bar | `########>-------` |
| `{wide_bar}` | none | Width-adaptive progress bar | fills remaining columns |
| `{pos}` | none | Current position | `42` |
| `{count}` | none | Compact current position | `1.2k` |
| `{human_pos}` | none | Alias for compact position | `1.2k` |
| `{len}` | none | Total length or `?` | `100` |
| `{total_count}` | none | Compact total length | `1.5M` |
| `{human_len}` | none | Alias for compact total length | `1.5M` |
| `{remaining}` | none | Remaining units | `58` |
| `{human_remaining}` | none | Compact remaining units | `58.0k` |
| `{ratio}` | `:.3` | Completion ratio | `0.420` |
| `{percent}` | `:.2` | Percentage without `%` | `42` or `42.50` |
| `{elapsed}` | none | Human elapsed time | `3m 14s` |
| `{elapsed_precise}` | none | Precise elapsed time | `00:03:14` |
| `{elapsed_millis}` | none | Millisecond elapsed time | `00:03:14.123` |
| `{eta}` | none | Estimated remaining time | `~12s` |
| `{eta_precise}` | none | Precise ETA | `00:00:12` |
| `{eta_millis}` | none | Millisecond ETA | `00:00:12.345` |
| `{per_sec}` | `:.2` | Average rate | `123.45` |
| `{rate}` | none | Formatted item rate | `1.23k items/s` |
| `{bytes}` | none | Position as bytes | `1.00 MB` |
| `{total_bytes}` | none | Length as bytes | `50.00 MB` |
| `{bytes_per_sec}` | none | Byte throughput | `1.23 MB/s` |
| `{spinner}` | none | Current spinner frame | `-` |
| `{msg}` | `:20`, `:>20`, `:^20` | Message with optional padding/truncation | `downloading` |
| `{prefix}` | `:10`, `:>10`, `:^10` | Prefix with optional padding/truncation | `task` |
| `{postfix}` | `:10`, `:>10`, `:^10` | Postfix with optional padding/truncation | `ok` |
| `{status}` | `:10`, `:>10`, `:^10` | `running`, `spinning`, `finished`, or `abandoned` | `running` |
| `{wide_msg}` | none, `:20`, `:>20`, `:^20` | Terminal-width or explicit-width message field | terminal-width text |
## Bar Format
`{bar:N}` sets the width. `{bar:N.fill/empty}` sets fill and empty characters. Color words
inside a template are accepted for compatibility with terminal-style templates; whole-line
color is configured with `ColorSpec`.
`{wide_bar}` uses the active draw target width. Width detection uses terminal APIs and falls
back to `COLUMNS`/`LINES` or safe defaults when a TTY is not available.
```rust
let style = loaders::ProgressStyle::with_template(
"{prefix} [{bar:30.#/-}] {percent:.1}% {msg}",
)?;
# Ok::<(), loaders::bar::template::TemplateError>(())
```
## Reusable Progress Characters
`ProgressChars` stores fill, head, and empty characters as a reusable value.
```rust
use loaders::{ProgressChars, ProgressStyle};
let style = ProgressStyle::default_bar()
.progress_chars_set(ProgressChars::blocks());
```
Use `try_progress_chars` when parsing user configuration and invalid inputs should return
an error.
## Text Padding and Truncation
String variables support width specs for alignment and fixed width:
- `:20` left-aligned width 20
- `:>20` right-aligned width 20
- `:^20` centered width 20
When the content is longer than the width it is truncated to fit.
## Colors
```rust
use loaders::{Color, ColorSpec, ProgressStyle};
let style = ProgressStyle::default_bar()
.color(ColorSpec::new().set_fg(Color::Cyan).set_bold(true));
```
## Custom Keys
```rust
let style = loaders::ProgressStyle::with_template("{phase} {bar:20}")?
.with_key("phase", |state| format!("phase {}", state.pos / 10 + 1));
# Ok::<(), loaders::bar::template::TemplateError>(())
```