# How Bat Style Components Work: From CLI Flags to Terminal Rendering

> Explore how bat style components function in Rust, from CLI flags to terminal rendering. Understand how the CLI flag controls visual decorations with precedence rules.

- Repository: [David Peter/bat](https://github.com/sharkdp/bat)
- Tags: internals
- Published: 2026-03-06

---

**Bat style components are defined in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs) as a Rust enum where variants like `Grid`, `LineNumbers`, and `Header` expand into sub-component sets via the `components()` method, allowing the `--style` CLI flag to add, remove, or override visual decorations with specific precedence rules.**

The `sharkdp/bat` repository renders files with syntax highlighting and rich visual decorations controlled by a modular style system. These **bat style components** translate user-friendly CLI arguments into concrete rendering instructions through a type-safe Rust architecture that handles expansion, parsing, and runtime checks.

## Style Component Architecture

### The StyleComponent Enum

At the core of the system lies the `StyleComponent` enum defined in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs). This enum represents every visual feature available in the terminal output:

```rust
pub enum StyleComponent {
    Auto,
    #[cfg(feature = "git")] Changes,
    Grid,
    Rule,
    Header,
    HeaderFilename,
    HeaderFilesize,
    LineNumbers,
    Snip,
    Full,
    Default,
    Plain,
}

```

*(source: [StyleComponent enum](https://github.com/sharkdp/bat/blob/master/src/style.rs#L8-L22))*

Each variant corresponds to a specific decoration: `Grid` draws border lines, `LineNumbers` enables line numbering, `HeaderFilename` displays the file name in a header, and `Plain` disables all visual features. The `#[cfg(feature = "git")]` attribute conditionally includes Git change indicators only when the git feature is compiled.

### Sub-Component Expansion

Style components frequently represent aggregate sets of decorations rather than single features. The `components()` method in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs) (lines 24-62) resolves these variants into concrete sub-component lists based on terminal interactivity:

```rust
pub fn components(self, interactive_terminal: bool) -> &'static [StyleComponent] {
    match self {
        StyleComponent::Auto => {
            if interactive_terminal {
                StyleComponent::Default.components(interactive_terminal)
            } else {
                StyleComponent::Plain.components(interactive_terminal)
            }
        }
        StyleComponent::Full => &[
            #[cfg(feature = "git")] StyleComponent::Changes,
            StyleComponent::Grid,
            StyleComponent::HeaderFilename,
            StyleComponent::HeaderFilesize,
            StyleComponent::LineNumbers,
            StyleComponent::Snip,
        ],
        StyleComponent::Default => &[
            #[cfg(feature = "git")] StyleComponent::Changes,
            StyleComponent::Grid,
            StyleComponent::HeaderFilename,
            StyleComponent::LineNumbers,
            StyleComponent::Snip,
        ],
        StyleComponent::Plain => &[],
        // single-ton components return themselves
        _ => &[self],
    }
}

```

*(source: [components() implementation](https://github.com/sharkdp/bat/blob/master/src/style.rs#L24-L62))*

This method implements the expansion logic:

- **Auto** selects `Default` for interactive terminals and `Plain` for non-interactive environments (like pipes)
- **Full** expands to include file size headers (`HeaderFilesize`) alongside the default set
- **Plain** returns an empty slice, disabling all decorations
- Individual components like `Grid` or `Rule` return themselves as single-element slices

## Parsing and Precedence Rules

### CLI Argument Parsing

The `--style` flag accepts comma-separated component names with optional prefixes to modify the active set. In [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs), the `ComponentAction` enum defines three operations:

```rust
enum ComponentAction { Override, Add, Remove }

impl ComponentAction {
    fn extract_from_str(s: &str) -> (ComponentAction, &str) {
        match s.chars().next() {
            Some('-') => (ComponentAction::Remove, s.strip_prefix('-').unwrap()),
            Some('+') => (ComponentAction::Add,    s.strip_prefix('+').unwrap()),
            _          => (ComponentAction::Override, s),
        }
    }
}

```

*(source: [ComponentAction](https://github.com/sharkdp/bat/blob/master/src/style.rs#L42-L56))*

Prefixing a component with `+` adds it to the current set, `-` removes it, and no prefix replaces the entire configuration.

### Component Set Construction

The `StyleComponentList::to_components()` method (referenced in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs) lines 82-88) applies these actions with strict precedence rules:

1. **Override entries** clear the existing set before applying new components
2. **Add/Remove actions** merge into the current set without clearing previous selections

For example, the combination `[grid] + [numbers]` results in only `{LineNumbers}` because the second list's override behavior replaces the first.

## Runtime Rendering Integration

During file rendering, the finalized `StyleComponents` set drives decoration decisions in [`src/terminal.rs`](https://github.com/sharkdp/bat/blob/main/src/terminal.rs). The code checks specific component availability to conditionally emit visual elements:

```rust
if style.grid()    { /* draw grid */ }
if style.numbers() { /* print line numbers */ }
if style.header()  { /* show header (filename/size) */ }

```

*(source: [Terminal style checks](https://github.com/sharkdp/bat/blob/master/src/terminal.rs#L50-L65))*

These boolean methods on the `StyleComponents` struct provide efficient runtime checks that determine whether to draw grid borders, print line numbers, or display file metadata headers.

## Practical Command-Line Examples

You can combine style components using comma-separated values with prefix modifiers:

```bash

# Show a grid and line numbers

bat --style=grid,numbers file.rs

# Start from the default set and remove the grid

bat --style=default,-grid file.rs

# Add rule lines on top of a previous style definition

bat --style=full,+rule file.rs

```

The `default` keyword initializes the standard component set (Changes, Grid, HeaderFilename, LineNumbers, Snip), allowing you to selectively disable specific features using the `-` prefix.

## Summary

- **Bat style components** are defined in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs) as the `StyleComponent` enum, with variants representing visual decorations like `Grid`, `LineNumbers`, and `Header`.
- The `components()` method expands aggregate variants (`Full`, `Default`, `Auto`, `Plain`) into static slices of concrete sub-components based on terminal interactivity.
- CLI parsing uses `ComponentAction` with `+`, `-`, and no-prefix modifiers to add, remove, or override components, with override actions taking precedence by clearing existing sets.
- Runtime rendering checks in [`src/terminal.rs`](https://github.com/sharkdp/bat/blob/main/src/terminal.rs) query the finalized component set via methods like `style.grid()` and `style.numbers()` to conditionally emit decorations.

## Frequently Asked Questions

### What bat style components are available in the CLI?

The available components are `Auto`, `Changes` (with git feature), `Grid`, `Rule`, `Header`, `HeaderFilename`, `HeaderFilesize`, `LineNumbers`, `Snip`, `Full`, `Default`, and `Plain`. You can view these by running `bat --help` or examining the `StyleComponent` enum in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs) lines 8-22.

### How does the Auto style component determine which decorations to show?

The `Auto` component delegates to `components()` in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs), which checks the `interactive_terminal` parameter. If the terminal is interactive (TTY), it expands to the `Default` component set; otherwise, it expands to `Plain`, disabling all decorations for pipe-friendly output.

### Can I mix additive and subtractive style arguments in one bat command?

Yes. The `--style` flag accepts comma-separated values where `+component` adds to the set and `-component` removes from it. However, if any component appears without a prefix (an override), it clears all previous selections. For example, `bat --style=numbers,-grid` works, but `bat --style=numbers,grid` replaces any inherited styles with just those two components.

### Where does bat resolve the final list of active style components?

Final resolution happens in [`src/style.rs`](https://github.com/sharkdp/bat/blob/main/src/style.rs) within the `StyleComponentList::to_components()` method, which processes the parsed CLI arguments according to precedence rules. The resulting `StyleComponents` set is then consumed by rendering logic in [`src/terminal.rs`](https://github.com/sharkdp/bat/blob/main/src/terminal.rs) to conditionally display decorations.