1use crate::color::ColorMode;
7use crate::document::{Document, Fields, Table};
8use crate::render::RenderOptions;
9
10#[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#[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_aligns_values_in_one_column() {
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 let starts: Vec<_> = out
61 .lines()
62 .map(|line| line.find("demo").or_else(|| line.find("@org")))
63 .collect();
64 assert_eq!(starts, [Some(9), Some(9)], "{out}");
65 assert!(!out.contains('\u{1b}'), "{out:?}");
66 }
67
68 #[test]
69 fn never_has_no_ansi() {
70 let out = kv(ColorMode::Never, [("release", "v0.0.1")]);
71 assert!(!out.contains('\u{1b}'), "{out:?}");
72 assert!(out.contains("release"), "{out}");
73 }
74
75 #[test]
76 fn grid_has_headers() {
77 let out = grid(
78 ColorMode::Never,
79 &["id", "runner"],
80 [vec!["linux-x64".into(), "ubuntu-latest".into()]],
81 );
82 assert!(out.contains("linux-x64"), "{out}");
83 assert!(out.contains("ubuntu-latest"), "{out}");
84 assert!(out.contains("id"), "{out}");
85 }
86}