Line Range Processing is bat's system for filtering and displaying specific portions of input files based on user-specified line number ranges. This system enables users to view only selected lines from files, supporting absolute line numbers, relative offsets from the file end, and context-based ranges.
The line range system is built around several key data structures that work together to represent, parse, and evaluate line ranges.
Sources: src/line_range.rs4-17 src/line_range.rs277-296 src/line_range.rs351-355 src/line_range.rs383-386
The LineRange::parse_range function supports multiple input formats. The parser splits the input string by the : delimiter and interprets the resulting parts based on count and prefixes.
| Format | Example | Description | Lower Bound | Upper Bound |
|---|---|---|---|---|
| Single line | 40 | Display only line 40 | Absolute(40) | Absolute(40) |
| Full range | 40:50 | Display lines 40 through 50 | Absolute(40) | Absolute(50) |
| From start | :50 | Display from beginning to line 50 | Absolute(usize::MIN) | Absolute(50) |
| To end | 40: | Display from line 40 to end | Absolute(40) | Absolute(usize::MAX) |
| Relative addition | 40:+10 | Display 10 lines starting from 40 | Absolute(40) | Absolute(50) |
| Relative subtraction | 40:-10 | Display from 10 lines before 40 to 40 | Absolute(30) | Absolute(40) |
| End-relative upper | :-3 | Display from start to 3rd-to-last line | Absolute(usize::MIN) | OffsetFromEnd(3) |
| End-relative lower | -3: | Display last 3 lines | OffsetFromEnd(3) | Absolute(usize::MAX) |
| Context (Single) | 40::2 | Line 40 with 2 lines of context | Absolute(38) | Absolute(42) |
| Context (Range) | 40:50:2 | Range 40-50 with 2 lines of context | Absolute(38) | Absolute(52) |
Sources: src/line_range.rs40-131
The parsing system transforms string specifications into structured LineRange objects. It uses a custom byte-level iterator for prefixes and standard string splitting for complex ranges.
Sources: src/line_range.rs40-131
The LineRange::is_inside method determines whether a given line number falls within the range. Because end-relative ranges (e.g., -3:) depend on the total line count, the system uses MaxBufferedLineNumber to track whether the end of the file has been reached.
Sources: src/line_range.rs136-166
The LineRanges struct manages a collection of LineRange objects. To avoid unnecessary processing of large files, it tracks boundary metadata to determine if the printer can terminate early.
During construction via LineRanges::from, the struct calculates:
largest_absolute_upper_bound: The highest absolute line number across all ranges. src/line_range.rs311-313smallest_offset_from_end: The minimum offset from the end (closest to the end of file). src/line_range.rs315-317largest_offset_from_end: The maximum offset from the end (furthest from the end of file). src/line_range.rs319-321The check method returns RangeCheckResult::AfterLastRange if the current line number is guaranteed to be beyond all possible ranges. This happens when:
largest_absolute_upper_bound. src/line_range.rs361-363smallest_offset_from_end (if the final line count is known). src/line_range.rs364-367Sources: src/line_range.rs351-375
The HighlightedLineRanges struct is a wrapper around LineRanges used specifically for determining which lines should receive syntax highlighting. This is distinct from display filtering; for example, a user might want to display all lines but only highlight a specific range.
HighlightedLineRanges::default() initializes with LineRanges::none(), meaning no lines are highlighted by default unless specified. src/line_range.rs387-391LineRanges can represent "all lines" using LineRanges::all(), which initializes bounds from usize::MIN to usize::MAX. src/line_range.rs298-303