# How bat Handles Line Ranges to Display Specific Parts of a File

> Learn how bat handles line ranges to display specific file parts. Discover absolute numbers, relative offsets, and context modifiers for precise output control.

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

---

**bat parses the `--line-range` flag into a `LineRange` structure that supports absolute numbers, relative offsets from the end, and context modifiers, then filters output during streaming via `LineRanges::check` to display only requested lines.**

The `bat` command-line tool by sharkdp/bat enhances file viewing with syntax highlighting and git integration. When you need to display specific sections of large files, understanding how bat handles line ranges helps you extract exactly the content you need using the `--line-range` (`-r`) flag.

## Understanding the LineRange Syntax

The `--line-range` flag accepts flexible syntax patterns that define lower and upper bounds. These patterns are parsed in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) to handle absolute positions, offsets from the end, and relative ranges.

| Syntax | Meaning |
|--------|---------|
| `N:M` | Print lines *N* through *M* (inclusive). |
| `:M` | Print from the start of the file up to line *M*. |
| `N:` | Print from line *N* to the end of the file. |
| `N` | Print only line *N*. |
| `-K:` | Print the last *K* lines (offset from the end). |
| `:-K` | Print from the start up to the line *K* lines before the end. |
| `N:+K` | Print lines *N* through *N + K* (relative positive offset). |
| `N:-K` | Print lines *N - K* through *N* (relative negative offset). |
| `N::C` | Print line *N* plus *C* lines of context on both sides. |
| `N:M:C` | Print range *N … M* plus *C* lines of context on both sides. |

## Parsing Line Ranges in bat

### The LineRange Structure and parse_range Function

In [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs), the `LineRange` struct stores lower and upper bounds as `RangeBound` variants. The `LineRange::parse_range` function tokenizes the raw string (e.g., `"30:+10"`), detects the presence of colons or `+/-` signs, and builds a `LineRange` whose fields are `RangeBound` variants.

The `RangeBound` enum supports two variants:
- `Absolute(usize)` for fixed line numbers
- `OffsetFromEnd(usize)` for negative offsets (e.g., `-5:`)

See the implementation in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) lines 36-77 for the tokenization logic that handles the various syntax patterns.

### Context Syntax Handling

When the parser encounters three components (e.g., `N:M:C` or `N::C`), it interprets the third value as context lines. In [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) lines 100-124, the code expands the lower bound by subtracting the context value and expands the upper bound by adding it, ensuring the output includes the specified number of lines before and after the target range.

## Resolving Relative and End-Based Offsets

### OffsetFromEnd and File Size Resolution

Relative offsets like `-K:` (last K lines) cannot be resolved until the file size is known. The `LineRange::is_inside` method in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) (lines 133-190) evaluates whether a given line number falls within the range, using the current `MaxBufferedLineNumber` to calculate final positions for `OffsetFromEnd` variants.

This deferred resolution allows bat to evaluate ranges that depend on the final line count while streaming the file, avoiding the need to buffer the entire file upfront.

### Selective Rendering with LineRanges::check

Multiple ranges are managed by the `LineRanges` struct. The `LineRanges::check` method in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) (lines 378-449) classifies each line as `InRange`, `BeforeOrBetweenRanges`, or `AfterLastRange` during the rendering process.

The `PrettyPrinter` in [`src/pretty_printer.rs`](https://github.com/sharkdp/bat/blob/main/src/pretty_printer.rs) holds a `HighlightedLineRanges` (wrapping a `LineRanges`) and queries `LineRanges::check` for each line to determine whether to print it and apply syntax highlighting.

## CLI Integration and Rendering Pipeline

### Command-Line Flag Definition

The `--line-range` flag is defined in [`src/bin/bat/clap_app.rs`](https://github.com/sharkdp/bat/blob/main/src/bin/bat/clap_app.rs) (lines 17-24). The configuration specifies `allow_hyphen_values(true)` to ensure that leading hyphens (such as `-10:`) are accepted as part of the range value rather than being interpreted as separate command-line flags.

### Building LineRanges in the Application Layer

In [`src/bin/bat/app.rs`](https://github.com/sharkdp/bat/blob/main/src/bin/bat/app.rs) (lines 486-504), the application transforms each supplied `--line-range` argument into a `LineRange` via `LineRange::from`, then collects them into a `LineRanges` object that is passed to the printer for filtering during output.

### Rendering Integration

The [`controller.rs`](https://github.com/sharkdp/bat/blob/main/controller.rs) module uses `LineRanges::check` to drive paging and output flow, while [`src/pretty_printer.rs`](https://github.com/sharkdp/bat/blob/main/src/pretty_printer.rs) wraps the range checking logic in `HighlightedLineRanges` to determine which lines receive syntax highlighting and are sent to the output buffer.

## Practical Examples

```bash

# Print lines 10 to 20 (inclusive)

bat -r 10:20 source.rs

# Print the first 40 lines

bat -r :40 source.rs

# Print from line 40 to the end of the file

bat -r 40: source.rs

# Print only line 42

bat -r 42 source.rs

# Print the last 5 lines (negative offset from end)

bat -r -5: source.rs

# Print lines 30 to 40, plus 2 lines of context on each side

bat -r 30:40:2 source.rs

# Print line 35 with 5 lines of context (single-line base)

bat -r 35::5 source.rs

# Print a range with a relative "+" offset (30-40)

bat -r 30:+10 source.rs

```

All of these options are parsed by `LineRange::from` and ultimately evaluated by `LineRanges::check` during the rendering pipeline.

## Summary

- **Flexible Syntax**: bat supports absolute ranges (`N:M`), open-ended ranges (`:M`, `N:`), single lines (`N`), end-relative offsets (`-K:`), and context modifiers (`N::C`, `N:M:C`).

- **Structured Representation**: The `LineRange` struct in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) stores bounds as `RangeBound` variants (`Absolute` or `OffsetFromEnd`), parsed by `LineRange::parse_range`.

- **Deferred Resolution**: End-relative offsets are resolved during streaming via `LineRange::is_inside`, which uses the current maximum buffered line number to calculate final positions without loading the entire file.

- **Collection Management**: Multiple ranges are managed by `LineRanges`, which uses `LineRanges::check` to classify each line as `InRange`, `BeforeOrBetweenRanges`, or `AfterLastRange` during output.

- **CLI Integration**: The `--line-range` flag is defined in [`src/bin/bat/clap_app.rs`](https://github.com/sharkdp/bat/blob/main/src/bin/bat/clap_app.rs) with `allow_hyphen_values(true)`, processed in [`src/bin/bat/app.rs`](https://github.com/sharkdp/bat/blob/main/src/bin/bat/app.rs), and consumed by the `PrettyPrinter` in [`src/pretty_printer.rs`](https://github.com/sharkdp/bat/blob/main/src/pretty_printer.rs).

## Frequently Asked Questions

### How does bat handle negative line numbers like -5: to show the last 5 lines?

bat interprets negative offsets using the `OffsetFromEnd` variant of the `RangeBound` enum in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs). When you specify `-5:`, the parser creates a range with a lower bound of `OffsetFromEnd(5)` and an upper bound of `OffsetFromEnd(0)`. The `LineRange::is_inside` method resolves these offsets against the current maximum buffered line number while streaming the file, allowing bat to display the final lines without reading the entire file into memory first.

### Can I specify multiple line ranges in a single bat command?

Yes, you can provide multiple `--line-range` (or `-r`) flags to display disjoint sections of a file. According to [`src/bin/bat/app.rs`](https://github.com/sharkdp/bat/blob/main/src/bin/bat/app.rs) (lines 486-504), each argument is converted to a `LineRange` via `LineRange::from` and collected into a `LineRanges` object. The `LineRanges::check` method in [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) (lines 378-449) then evaluates each line against all specified ranges, printing it if it falls within any of them.

### What is the difference between N:+K and N:M syntax in bat line ranges?

The `N:+K` syntax specifies a relative offset from line N, printing lines N through N+K inclusive, while `N:M` specifies absolute line numbers. In [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs), the `LineRange::parse_range` function detects the `+` or `-` prefix after the colon and constructs bounds accordingly. For `N:+K`, the upper bound becomes `Absolute(N + K)`, whereas for `N:M`, both bounds are parsed as absolute values directly from the input strings without arithmetic modification.

### How does bat add context lines around a specific range?

bat supports context syntax using double colons (`N::C`) or triple components (`N:M:C`), where C represents the number of context lines to add on both sides. In [`src/line_range.rs`](https://github.com/sharkdp/bat/blob/main/src/line_range.rs) (lines 100-124), when the parser detects three components or the `::` pattern, it expands the lower bound by subtracting the context value and expands the upper bound by adding it. This ensures the output includes the specified number of lines before and after the target range while maintaining the original range as the core content.