Skip to main content

ctl_core/
table.rs

1//! Compatibility helpers over the semantic document renderer.
2//!
3//! New consumers should compose [`Fields`](crate::Fields) and
4//! [`Table`](crate::Table) inside a [`Document`](crate::Document).
5
6use crate::color::ColorMode;
7use crate::document::{Document, Fields, Table};
8use crate::render::RenderOptions;
9
10/// Two-column token/value fields. Tokens are styled unless `color` is never.
11#[must_use]
12pub fn kv(
13    color: ColorMode,
14    rows: impl IntoIterator<Item = (impl AsRef<str>, impl AsRef<str>)>,
15) -> String {
16    let fields = rows
17        .into_iter()
18        .fold(Fields::new(), |fields, (token, value)| {
19            fields.row(token.as_ref(), value.as_ref())
20        });
21    Document::new()
22        .fields(fields)
23        .render(RenderOptions::new(color))
24        .trim_end()
25        .to_owned()
26}
27
28/// Headered grid. Headers and the first column carry semantic styles.
29#[must_use]
30pub fn grid(
31    color: ColorMode,
32    headers: &[&str],
33    rows: impl IntoIterator<Item = Vec<String>>,
34) -> String {
35    let table = rows.into_iter().fold(
36        Table::new(headers.iter().copied()).token_column(0),
37        Table::row,
38    );
39    Document::new()
40        .table(table)
41        .render(RenderOptions::new(color))
42        .trim_end()
43        .to_owned()
44}
45
46#[cfg(test)]
47mod tests {
48    use super::{grid, kv};
49    use crate::color::ColorMode;
50
51    #[test]
52    fn kv_is_a_table_not_spaces() {
53        let out = kv(
54            ColorMode::Never,
55            [("crate", "demo@0.0.1"), ("package", "@org/pkg@0.0.1")],
56        );
57        assert!(out.contains("crate"), "{out}");
58        assert!(out.contains("demo@0.0.1"), "{out}");
59        assert!(out.contains("package"), "{out}");
60        assert!(out.contains('│') || out.contains('|'), "{out}");
61        assert!(!out.contains('\u{1b}'), "{out:?}");
62    }
63
64    #[test]
65    fn never_has_no_ansi() {
66        let out = kv(ColorMode::Never, [("release", "v0.0.1")]);
67        assert!(!out.contains('\u{1b}'), "{out:?}");
68        assert!(out.contains("release"), "{out}");
69    }
70
71    #[test]
72    fn grid_has_headers() {
73        let out = grid(
74            ColorMode::Never,
75            &["id", "runner"],
76            [vec!["linux-x64".into(), "ubuntu-latest".into()]],
77        );
78        assert!(out.contains("linux-x64"), "{out}");
79        assert!(out.contains("ubuntu-latest"), "{out}");
80        assert!(out.contains("id"), "{out}");
81    }
82}