This page documents the Segment NamedTuple — the atomic output unit of Rich's rendering pipeline — along with the cell-width measurement system and the bulk operations that transform collections of segments into fixed-width lines. For how segments are produced from renderables, see the Rendering Pipeline. For the Style objects that segments carry, see Styles and Colors.
Every object rendered by Rich is ultimately converted into a stream of Segment instances before any bytes reach the terminal. A Segment pairs a string of text with an optional Style and an optional sequence of control codes. The Console collects these segments, resolves styles to ANSI escape codes, and writes the result.
Segment position in data flow
Sources: rich/segment.py64-103 rich/segment.py752-784
Segment NamedTupleDefined in rich/segment.py64-103 Segment is a NamedTuple with three fields:
| Field | Type | Description |
|---|---|---|
text | str | The printable (or control) text payload |
style | Optional[Style] | Visual style to apply; None for unstyled |
control | Optional[Sequence[ControlCode]] | Non-printable control codes; None for regular text |
Key properties and methods on a Segment instance:
| Member | Kind | Description |
|---|---|---|
cell_length | property | Terminal cell width of text; 0 for control segments |
is_control | property | True if control is not None |
split_cells(cut) | method | Split at a cell column offset; handles wide chars |
__bool__ | method | True if text is non-empty |
When control is set, the segment carries terminal control codes rather than visible text. The ControlType enum rich/segment.py35-53 enumerates every supported code:
| ControlType | Value | Purpose |
|---|---|---|
BELL | 1 | Terminal bell |
CARRIAGE_RETURN | 2 | Move to column 0 |
HOME | 3 | Move cursor to origin |
CLEAR | 4 | Clear screen |
SHOW_CURSOR / HIDE_CURSOR | 5, 6 | Cursor visibility |
ENABLE_ALT_SCREEN / DISABLE_ALT_SCREEN | 7, 8 | Alternate screen buffer |
CURSOR_UP/DOWN/FORWARD/BACKWARD | 9–12 | Relative cursor motion |
CURSOR_MOVE_TO_COLUMN | 13 | Absolute column position |
CURSOR_MOVE_TO | 14 | Absolute (row, col) position |
ERASE_IN_LINE | 15 | Erase from cursor to end of line |
SET_WINDOW_TITLE | 16 | Terminal window title |
A ControlCode is a tuple of (ControlType,), (ControlType, int|str), or (ControlType, int, int) rich/segment.py56-60
Segment type taxonomy
Sources: rich/segment.py35-103
A terminal cell is one character column. ASCII characters occupy one cell; many CJK, emoji, and other Unicode characters occupy two. Some characters (combining marks, zero-width joiners) occupy zero cells.
The measurement machinery lives in rich/cells.py and rich/_unicode_data/
rich/cells.py| Function | Signature | Description |
|---|---|---|
cell_len | (text, unicode_version="auto") -> int | Cell length of a string; uses cache for strings shorter than 512 chars |
cached_cell_len | (text, unicode_version="auto") -> int | Always-cached variant via lru_cache |
get_character_cell_size | (character, unicode_version="auto") -> int | Cell width of a single character (0, 1, or 2) |
set_cell_size | (text, total, unicode_version="auto") -> str | Crop or pad a string to exactly total cells |
split_text | (text, cell_position, unicode_version="auto") -> Tuple[str, str] | Split a string at a cell offset; pads double-wide chars split in half |
split_graphemes | (text, unicode_version="auto") -> Tuple[List[CellSpan], int] | Break a string into grapheme spans with per-grapheme cell lengths |
chop_cells | (text, width, unicode_version="auto") -> List[str] | Divide text into lines of at most width cells |
_is_single_cell_widths rich/cells.py35 is a fast frozenset.issuperset check that short-circuits measurement for common ASCII and Latin text.
Width tables are pre-computed per Unicode version and stored as CellTable NamedTuples under rich/_unicode_data/ The load() function rich/_unicode_data/__init__.py59-93 selects the closest available version no higher than the requested one. The active version is controlled by the UNICODE_VERSION environment variable; "auto" reads that variable or falls back to "latest".
Supported versions are listed in rich/_unicode_data/_versions.py (currently 4.1.0 through 17.0.0).
Cell-width measurement call chain
Sources: rich/cells.py46-110 rich/_unicode_data/__init__.py59-93 rich/segment.py81-89
All bulk operations are classmethods on Segment. They operate on iterables or lists of Segment objects and are used heavily inside the rendering pipeline.
split_cells(cut) — Split at a Cell ColumnSplits a single Segment into two at the given cell offset. If the cut falls in the middle of a 2-cell wide character (e.g., a CJK character or emoji), both halves are replaced with a space to preserve total width.
Fast path: if all characters in text are single-cell, uses plain string slicing via _is_single_cell_widths. Otherwise delegates to _split_cells (LRU-cached at 16 384 entries) rich/segment.py110-156
split_lines(segments) — Segment Stream → LinesSplits a flat stream of segments on \n characters, yielding one List[Segment] per line. Does not include the newline segments in the output lists.
split_lines_terminator(segments)Like split_lines, but each yielded item is (List[Segment], bool) where the boolean indicates whether the line was terminated by a newline.
split_and_crop_lines(segments, length, style, pad, include_new_lines) — Core Layout OperationThe workhorse of the rendering pipeline. Splits on newlines and enforces a fixed line width by calling adjust_line_length on each line. Returns an iterable of fixed-width List[Segment] rows — the format consumed by Console._render_buffer when writing to the terminal.
Parameters:
| Parameter | Default | Description |
|---|---|---|
length | — | Target cell width |
style | None | Style for padding spaces |
pad | True | Pad short lines with spaces |
include_new_lines | True | Append Segment("\n") to each cropped line |
adjust_line_length(line, length, style, pad) — Crop or Pad One LineAdjusts a single List[Segment] to exactly length cells:
length, then trims the last segment via set_cell_size.divide(segments, cuts) — Column-Based DivisionDivides a segment stream into N groups based on a sorted list of cell positions cuts. Each cut is an absolute column offset. Segments that span a cut boundary are split. Yields List[Segment] per division, handling wide characters the same way split_cells does.
Used by the Table and Layout renderers to allocate columns.
simplify(segments) — Merge Adjacent Same-Style SegmentsScans a segment stream and merges consecutive segments that have identical styles and are not control segments. Reduces segment count without changing visual output. Useful before writing to the terminal.
apply_style(segments, style, post_style) — Wrap StylesReturns a new iterable where each segment's effective style is style + segment.style + post_style. Either or both wrapper styles may be None. Control segments pass through unchanged (their style is set to None).
Used by renderables that need to overlay a container style on top of child output (e.g., Panel, Align).
filter_control(segments, is_control) — Separate Control from TextPartitions segments by their is_control flag. With the default is_control=False, yields only printable (non-control) segments; with is_control=True, yields only control segments.
| Method | Description |
|---|---|
strip_styles(segments) | Replace every style with None |
strip_links(segments) | Remove hyperlinks but keep other style attributes |
remove_color(segments) | Remove color components; keep bold/italic etc. |
Sources: rich/segment.py553-631
| Method | Signature | Description |
|---|---|---|
get_line_length(line) | List[Segment] -> int | Sum of cell lengths for a single row |
get_shape(lines) | List[List[Segment]] -> Tuple[int,int] | (max_width, height) of a 2D grid |
set_shape(lines, width, height, style, new_lines) | — | Crop/pad a grid to exact dimensions |
align_top(lines, width, height, style) | — | Pad rows below to reach height |
align_bottom(lines, width, height, style) | — | Pad rows above to reach height |
align_middle(lines, width, height, style) | — | Distribute padding above and below |
Sources: rich/segment.py401-551
Sources: rich/segment.py158-699
Segments and SegmentLines RenderablesTwo lightweight wrapper classes let you feed raw segment data back into the rendering protocol.
SegmentsWraps an Iterable[Segment] and implements __rich_console__. When new_lines=True, emits a Segment("\n") after each segment. Useful for printing pre-computed segments from outside a __rich_console__ method.
SegmentLinesWraps an Iterable[List[Segment]] (a list of rows) and implements __rich_console__. When new_lines=True, appends a newline segment after each row.
Sources: rich/segment.py702-749
AnsiDecoder in rich/ansi.py120-211 performs the reverse operation: it converts strings containing ANSI escape codes back into Text objects with Style spans. This is used by Text.from_ansi().
The decoder tokenizes the input with _ansi_tokenize rich/ansi.py28-56 which uses the regex re_ansi to identify plain text, SGR sequences (\x1b<FileRef file-url="https://github.com/Textualize/rich/blob/fc41075a/...m), and OSC sequences (used for hyperlinks). SGR codes are mapped to Style modifiers via SGR_STYLE_MAP [rich/ansi.py#L59-L117" min=59 max=117 file-path="...m), and OSC sequences (used for hyperlinks). SGR codes are mapped to Stylemodifiers viaSGR_STYLE_MAP` [rich/ansi.py">Hii which covers bold, dim, italic, underline, colors (standard, 256-color, truecolor), and reverse.
The decoder maintains a running self.style across calls, making it suitable for processing multi-line terminal output incrementally.
Sources: rich/ansi.py10-211
Sources: rich/segment.py310-399 rich/segment.py554-578 rich/style.py690-714
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.