Expand description
Terminal widgets built on ctl_text: tables, records, rules, stacks,
indents, and a way to swap one widget for another by width.
Every widget implements Renderable. It first measures: the narrowest
width it can be drawn at without breaking a word it keeps whole, and its
natural width. Then it renders lines at the width it is given.
A container measures its children, decides their widths, and renders each child at its own. The result is plain lines of styled spans with no escape sequence in them. Whatever writes the lines to a terminal adds the styling.
The crate re-exports ctl_text and the four types every widget uses:
Context, Overflow, Renderable, and Text.
§Quick start
A Table gives each column the widest cell it holds, and shrinks the
widest columns first when the width runs short. A column sets what
happens to a cell that does not fit, and which edge its cells sit against:
use ctl_layout::{Column, Context, Frame, Overflow, Renderable, Table};
let table = Table::new([
Column::new("id"),
Column::new("title").overflow(Overflow::Ellipsis),
Column::new("age").numeric(),
])
.frame(Frame::HeaderRule)
.row(["job-0014", "Fix the layout of narrow tables", "3"])
.row(["job-0015", "Document each public item", "120"]);
let lines: Vec<String> = table
.render(&Context::new(40))
.iter()
.map(ToString::to_string)
.collect();
assert_eq!(
lines,
[
"id title age",
"────────────────────────────────────────",
"job-0014 Fix the layout of narrow… 3",
"job-0015 Document each public item 120",
]
);A Record draws labelled values, a Rule draws a line with an optional
title, a Stack puts widgets one above the other, and an Indent moves
one right. A stack and an indent take a widget by value or by reference:
use ctl_layout::{Context, Indent, Record, Renderable, Rule, Stack, Text};
let screen = Stack::new()
.spacing(1)
.push(Rule::titled(Text::plain("Release")))
.push(Indent::new(
2,
Record::new()
.row("version", "1.4.0")
.row("channel", "stable"),
));
let lines: Vec<String> = screen
.render(&Context::new(24))
.iter()
.map(ToString::to_string)
.collect();
assert_eq!(
lines,
[
"── Release ─────────────",
"",
" version 1.4.0",
" channel stable",
]
);A Breakpoint draws Definitions where a table no longer fits, so a
narrow terminal gets one line of flags over an indented description:
use ctl_layout::{Breakpoint, Column, Context, Definitions, Frame, Renderable, Table};
let flags = Breakpoint::new(
40,
Definitions::new()
.entry(["-v", "--verbose"], ["Print more detail"])
.entry(["-q", "--quiet"], ["Print nothing on success"]),
Table::new([Column::untitled(), Column::untitled(), Column::untitled()])
.frame(Frame::Plain)
.row(["-v", "--verbose", "Print more detail"])
.row(["-q", "--quiet", "Print nothing on success"]),
);
let at = |width| -> Vec<String> {
flags
.render(&Context::new(width))
.iter()
.map(ToString::to_string)
.collect()
};
assert_eq!(
at(50),
[
"-v --verbose Print more detail",
"-q --quiet Print nothing on success",
]
);
assert_eq!(
at(30),
[
" -v --verbose",
" Print more detail",
" -q --quiet",
" Print nothing on success",
]
);A widget of your own sits in a Stack beside these once it implements
Renderable. Its Measurement and
Line types come through
ctl_layout::ctl_text.
§Widgets
Table: rows under column headers. AColumnsets the header, the overflow policy, and how its cells are aligned (Align). AFrameand aRowSeparationset the rules between them.Record: labelled values, drawn in aRecordStyle.Definitions: entries as a line of labels over indented description lines, the narrow form of a table.Breakpoint: one widget below a width and another from it up.Rule: a horizontal line with an optional title.Stack: widgets one above the other.Indent: a widget moved right.
§Cargo features
This crate has no optional features.
Re-exports§
pub use ctl_text;
Structs§
- Breakpoint
- One widget below a width and another from it up.
- Column
- A column of a table: its header, what it does with a cell wider than it gets, and which edge its cells sit against.
- Context
- What a widget is told when it measures and renders: the width to fill, the tab stop spacing, and the box characters.
- Definitions
- Entries, each a line of labels over indented lines of description.
- Indent
- A widget moved right by a number of cells.
- Record
- Labelled values, one pair to a row.
- Rule
- A rule across the whole width, drawn with
─, or-forBoxChars::Ascii. - Stack
- Widgets one above the other, each rendered at the full width.
- Table
- A table of rows under column headers.
- Text
- Styled text of any length: a paragraph, a table cell, a title.
Enums§
- Align
- Which edge of its column a cell’s text sits against.
- Frame
- What a table draws around and between its columns.
- Overflow
- What happens to a line wider than the width it is given.
- Record
Style - How a
Recordof key and value rows is drawn. - RowSeparation
- What separates consecutive rows of a table.
Traits§
- Renderable
- Content that knows its own size and can draw itself at a width.